mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-12-17 20:14:31 -06:00
Compare commits
23 Commits
v2.1.0
...
physicsSim
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4d6f11fed1 | ||
|
|
395e5c1c66 | ||
|
|
f0b6ad89d9 | ||
|
|
0bbc8e6643 | ||
|
|
050184c558 | ||
|
|
b23981e591 | ||
|
|
d78b50874c | ||
|
|
a0d51e21ca | ||
|
|
2f247b1fc9 | ||
|
|
54ded62757 | ||
|
|
5225c86d65 | ||
|
|
d5e757bd9d | ||
|
|
a1ac692b49 | ||
|
|
fcb9f671ae | ||
|
|
36f7b8a928 | ||
|
|
ea5360cb99 | ||
|
|
4f3b4f5f43 | ||
|
|
6bf084ef8f | ||
| 99b3705a76 | |||
|
|
c83ec8228c | ||
|
|
0a30430c4f | ||
| 6592bbea46 | |||
|
|
a62f6d63c6 |
10
.github/workflows/build-and-test.yml
vendored
10
.github/workflows/build-and-test.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
continue-on-error: true
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ windows-2022, ubuntu-20.04, macos-11 ]
|
||||
os: [ windows-2022, ubuntu-22.04, macos-13 ]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -25,9 +25,11 @@ jobs:
|
||||
with:
|
||||
vs-version: '[17,18)'
|
||||
msbuild-architecture: x64
|
||||
- name: Install libssl (Mac Only)
|
||||
if: ${{ matrix.os == 'macos-11' }}
|
||||
run: brew install openssl@3
|
||||
- name: Install libssl and switch to XCode 15.2 (Mac Only)
|
||||
if: ${{ matrix.os == 'macos-13' }}
|
||||
run: |
|
||||
brew install openssl@3
|
||||
sudo xcode-select -s /Applications/Xcode_15.2.app/Contents/Developer
|
||||
- name: cmake
|
||||
uses: lukka/run-cmake@v10
|
||||
with:
|
||||
|
||||
@@ -3,6 +3,7 @@ project(Darkflame)
|
||||
include(CTest)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||||
|
||||
# Read variables from file
|
||||
@@ -272,7 +273,9 @@ link_directories(${PROJECT_BINARY_DIR})
|
||||
|
||||
# Load all of our third party directories
|
||||
add_subdirectory(thirdparty)
|
||||
|
||||
if (UNIX)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
|
||||
endif()
|
||||
# Glob together all headers that need to be precompiled
|
||||
file(
|
||||
GLOB HEADERS_DDATABASE
|
||||
|
||||
@@ -14,13 +14,13 @@
|
||||
"generator": "Unix Makefiles"
|
||||
},
|
||||
{
|
||||
"name": "ci-ubuntu-20.04",
|
||||
"name": "ci-ubuntu-22.04",
|
||||
"displayName": "CI configure step for Ubuntu",
|
||||
"description": "Same as default, Used in GitHub actions workflow",
|
||||
"inherits": "default"
|
||||
},
|
||||
{
|
||||
"name": "ci-macos-11",
|
||||
"name": "ci-macos-13",
|
||||
"displayName": "CI configure step for MacOS",
|
||||
"description": "Same as default, Used in GitHub actions workflow",
|
||||
"inherits": "default"
|
||||
@@ -67,15 +67,15 @@
|
||||
"jobs": 2
|
||||
},
|
||||
{
|
||||
"name": "ci-ubuntu-20.04",
|
||||
"configurePreset": "ci-ubuntu-20.04",
|
||||
"name": "ci-ubuntu-22.04",
|
||||
"configurePreset": "ci-ubuntu-22.04",
|
||||
"displayName": "Linux CI Build",
|
||||
"description": "This preset is used by the CI build on linux",
|
||||
"jobs": 2
|
||||
},
|
||||
{
|
||||
"name": "ci-macos-11",
|
||||
"configurePreset": "ci-macos-11",
|
||||
"name": "ci-macos-13",
|
||||
"configurePreset": "ci-macos-13",
|
||||
"displayName": "MacOS CI Build",
|
||||
"description": "This preset is used by the CI build on MacOS",
|
||||
"jobs": 2
|
||||
@@ -83,8 +83,8 @@
|
||||
],
|
||||
"testPresets": [
|
||||
{
|
||||
"name": "ci-ubuntu-20.04",
|
||||
"configurePreset": "ci-ubuntu-20.04",
|
||||
"name": "ci-ubuntu-22.04",
|
||||
"configurePreset": "ci-ubuntu-22.04",
|
||||
"displayName": "CI Tests on Linux",
|
||||
"description": "Runs all tests on a linux configuration",
|
||||
"execution": {
|
||||
@@ -95,8 +95,8 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ci-macos-11",
|
||||
"configurePreset": "ci-macos-11",
|
||||
"name": "ci-macos-13",
|
||||
"configurePreset": "ci-macos-13",
|
||||
"displayName": "CI Tests on MacOS",
|
||||
"description": "Runs all tests on a Mac configuration",
|
||||
"execution": {
|
||||
|
||||
@@ -356,6 +356,10 @@ The Darkflame Server is automatically built and published as a Docker Container
|
||||
|
||||
## Compose
|
||||
|
||||
> [!WARNING]
|
||||
> It seems that Docker Desktop on Windows with the WSL 2 backend has some issues with MariaDB (c.f. [mariadb-docker#331](https://github.com/MariaDB/mariadb-docker/issues/331)) triggered by NexusDashboard
|
||||
> migrations, so this setup may not work for you. If that is the case, please tell us about your setup in [NexusDashboard#92](https://github.com/DarkflameUniverse/NexusDashboard/issues/92).
|
||||
|
||||
You can use the `docker-compose` tool to [setup a MariaDB database](#database-setup), run the Darkflame Server and manage it with [Nexus Dashboard](https://github.com/DarkflameUniverse/NexusDashboard) all
|
||||
at once. For that:
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include "PlayerContainer.h"
|
||||
#include "Database.h"
|
||||
#include <vector>
|
||||
#include "PacketUtils.h"
|
||||
#include "BitStreamUtils.h"
|
||||
#include "Game.h"
|
||||
#include "dServer.h"
|
||||
@@ -18,6 +17,8 @@
|
||||
#include "eChatInternalMessageType.h"
|
||||
#include "eClientMessageType.h"
|
||||
#include "eGameMessageType.h"
|
||||
#include "StringifiedEnum.h"
|
||||
#include "eGameMasterLevel.h"
|
||||
|
||||
void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
|
||||
//Get from the packet which player we want to do something with:
|
||||
@@ -78,31 +79,27 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
|
||||
|
||||
void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
|
||||
CINSTREAM_SKIP_HEADER;
|
||||
|
||||
LWOOBJID requestorPlayerID;
|
||||
inStream.Read(requestorPlayerID);
|
||||
uint32_t spacing{};
|
||||
inStream.Read(spacing);
|
||||
std::string playerName = "";
|
||||
uint16_t character;
|
||||
bool noMoreLettersInName = false;
|
||||
|
||||
for (uint32_t j = 0; j < 33; j++) {
|
||||
inStream.Read(character);
|
||||
if (character == '\0') noMoreLettersInName = true;
|
||||
if (!noMoreLettersInName) playerName.push_back(static_cast<char>(character));
|
||||
}
|
||||
|
||||
LUWString LUplayerName;
|
||||
char isBestFriendRequest{};
|
||||
|
||||
inStream.Read(requestorPlayerID);
|
||||
inStream.IgnoreBytes(4);
|
||||
inStream.Read(LUplayerName);
|
||||
inStream.Read(isBestFriendRequest);
|
||||
|
||||
auto playerName = LUplayerName.GetAsString();
|
||||
|
||||
auto& requestor = Game::playerContainer.GetPlayerDataMutable(requestorPlayerID);
|
||||
if (!requestor) {
|
||||
LOG("No requestor player %llu sent to %s found.", requestorPlayerID, playerName.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// you cannot friend yourself
|
||||
if (requestor.playerName == playerName) {
|
||||
SendFriendResponse(requestor, requestor, eAddFriendResponseType::MYTHRAN);
|
||||
SendFriendResponse(requestor, requestor, eAddFriendResponseType::GENERALERROR);
|
||||
return;
|
||||
};
|
||||
|
||||
@@ -141,6 +138,13 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent GM friend spam
|
||||
// If the player we are trying to be friends with is not a civilian and we are a civilian, abort the process
|
||||
if (requestee.gmLevel > eGameMasterLevel::CIVILIAN && requestor.gmLevel == eGameMasterLevel::CIVILIAN ) {
|
||||
SendFriendResponse(requestor, requestee, eAddFriendResponseType::MYTHRAN);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isBestFriendRequest) {
|
||||
|
||||
uint8_t oldBestFriendStatus{};
|
||||
@@ -218,15 +222,19 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
|
||||
|
||||
void ChatPacketHandler::HandleFriendResponse(Packet* packet) {
|
||||
CINSTREAM_SKIP_HEADER;
|
||||
LWOOBJID playerID;
|
||||
inStream.Read(playerID);
|
||||
|
||||
eAddFriendResponseCode clientResponseCode = static_cast<eAddFriendResponseCode>(packet->data[0x14]);
|
||||
std::string friendName = PacketUtils::ReadString(0x15, packet, true);
|
||||
LWOOBJID playerID;
|
||||
eAddFriendResponseCode clientResponseCode;
|
||||
LUWString friendName;
|
||||
|
||||
inStream.Read(playerID);
|
||||
inStream.IgnoreBytes(4);
|
||||
inStream.Read(clientResponseCode);
|
||||
inStream.Read(friendName);
|
||||
|
||||
//Now to try and find both of these:
|
||||
auto& requestor = Game::playerContainer.GetPlayerDataMutable(playerID);
|
||||
auto& requestee = Game::playerContainer.GetPlayerDataMutable(friendName);
|
||||
auto& requestee = Game::playerContainer.GetPlayerDataMutable(friendName.GetAsString());
|
||||
if (!requestor || !requestee) return;
|
||||
|
||||
eAddFriendResponseType serverResponseCode{};
|
||||
@@ -288,8 +296,11 @@ void ChatPacketHandler::HandleFriendResponse(Packet* packet) {
|
||||
void ChatPacketHandler::HandleRemoveFriend(Packet* packet) {
|
||||
CINSTREAM_SKIP_HEADER;
|
||||
LWOOBJID playerID;
|
||||
LUWString LUFriendName;
|
||||
inStream.Read(playerID);
|
||||
std::string friendName = PacketUtils::ReadString(0x14, packet, true);
|
||||
inStream.IgnoreBytes(4);
|
||||
inStream.Read(LUFriendName);
|
||||
auto friendName = LUFriendName.GetAsString();
|
||||
|
||||
//we'll have to query the db here to find the user, since you can delete them while they're offline.
|
||||
//First, we need to find their ID:
|
||||
@@ -335,123 +346,144 @@ void ChatPacketHandler::HandleRemoveFriend(Packet* packet) {
|
||||
SendRemoveFriend(goonB, goonAName, true);
|
||||
}
|
||||
|
||||
void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
||||
CINSTREAM_SKIP_HEADER;
|
||||
LWOOBJID playerID = LWOOBJID_EMPTY;
|
||||
inStream.Read(playerID);
|
||||
|
||||
const auto& sender = Game::playerContainer.GetPlayerData(playerID);
|
||||
|
||||
if (!sender) return;
|
||||
|
||||
if (sender.GetIsMuted()) return;
|
||||
|
||||
inStream.SetReadOffset(0x14 * 8);
|
||||
|
||||
uint8_t channel = 0;
|
||||
inStream.Read(channel);
|
||||
|
||||
std::string message = PacketUtils::ReadString(0x66, packet, true, 512);
|
||||
|
||||
LOG("Got a message from (%s) [%d]: %s", sender.playerName.c_str(), channel, message.c_str());
|
||||
|
||||
if (channel != 8) return;
|
||||
|
||||
auto* team = Game::playerContainer.GetTeam(playerID);
|
||||
|
||||
if (team == nullptr) return;
|
||||
|
||||
for (const auto memberId : team->memberIDs) {
|
||||
const auto& otherMember = Game::playerContainer.GetPlayerData(memberId);
|
||||
|
||||
if (!otherMember) return;
|
||||
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||
bitStream.Write(otherMember.playerID);
|
||||
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
||||
bitStream.Write(otherMember.playerID);
|
||||
bitStream.Write<uint8_t>(8);
|
||||
bitStream.Write<unsigned int>(69);
|
||||
bitStream.Write(LUWString(sender.playerName));
|
||||
bitStream.Write(sender.playerID);
|
||||
bitStream.Write<uint16_t>(0);
|
||||
bitStream.Write<uint8_t>(0); //not mythran nametag
|
||||
bitStream.Write(LUWString(otherMember.playerName));
|
||||
bitStream.Write<uint8_t>(0); //not mythran for receiver
|
||||
bitStream.Write<uint8_t>(0); //teams?
|
||||
bitStream.Write(LUWString(message, 512));
|
||||
|
||||
SystemAddress sysAddr = otherMember.sysAddr;
|
||||
SEND_PACKET;
|
||||
}
|
||||
}
|
||||
|
||||
void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
||||
LWOOBJID senderID = PacketUtils::ReadS64(0x08, packet);
|
||||
std::string receiverName = PacketUtils::ReadString(0x66, packet, true);
|
||||
std::string message = PacketUtils::ReadString(0xAA, packet, true, 512);
|
||||
|
||||
//Get the bois:
|
||||
const auto& goonA = Game::playerContainer.GetPlayerData(senderID);
|
||||
const auto& goonB = Game::playerContainer.GetPlayerData(receiverName);
|
||||
if (!goonA || !goonB) return;
|
||||
|
||||
if (goonA.GetIsMuted()) return;
|
||||
|
||||
//To the sender:
|
||||
{
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||
bitStream.Write(goonA.playerID);
|
||||
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
||||
bitStream.Write(goonA.playerID);
|
||||
bitStream.Write<uint8_t>(7);
|
||||
bitStream.Write<unsigned int>(69);
|
||||
bitStream.Write(LUWString(goonA.playerName));
|
||||
bitStream.Write(goonA.playerID);
|
||||
bitStream.Write<uint16_t>(0);
|
||||
bitStream.Write<uint8_t>(0); //not mythran nametag
|
||||
bitStream.Write(LUWString(goonB.playerName));
|
||||
bitStream.Write<uint8_t>(0); //not mythran for receiver
|
||||
bitStream.Write<uint8_t>(0); //success
|
||||
bitStream.Write(LUWString(message, 512));
|
||||
|
||||
SystemAddress sysAddr = goonA.sysAddr;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
//To the receiver:
|
||||
{
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||
bitStream.Write(goonB.playerID);
|
||||
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
||||
bitStream.Write(goonA.playerID);
|
||||
bitStream.Write<uint8_t>(7);
|
||||
bitStream.Write<unsigned int>(69);
|
||||
bitStream.Write(LUWString(goonA.playerName));
|
||||
bitStream.Write(goonA.playerID);
|
||||
bitStream.Write<uint16_t>(0);
|
||||
bitStream.Write<uint8_t>(0); //not mythran nametag
|
||||
bitStream.Write(LUWString(goonB.playerName));
|
||||
bitStream.Write<uint8_t>(0); //not mythran for receiver
|
||||
bitStream.Write<uint8_t>(3); //new whisper
|
||||
bitStream.Write(LUWString(message, 512));
|
||||
|
||||
SystemAddress sysAddr = goonB.sysAddr;
|
||||
SEND_PACKET;
|
||||
}
|
||||
}
|
||||
|
||||
void ChatPacketHandler::HandleTeamInvite(Packet* packet) {
|
||||
void ChatPacketHandler::HandleGMLevelUpdate(Packet* packet) {
|
||||
CINSTREAM_SKIP_HEADER;
|
||||
LWOOBJID playerID;
|
||||
inStream.Read(playerID);
|
||||
std::string invitedPlayer = PacketUtils::ReadString(0x14, packet, true);
|
||||
auto& player = Game::playerContainer.GetPlayerData(playerID);
|
||||
if (!player) return;
|
||||
inStream.Read(player.gmLevel);
|
||||
}
|
||||
|
||||
// the structure the client uses to send this packet is shared in many chat messages
|
||||
// that are sent to the server. Because of this, there are large gaps of unused data in chat messages
|
||||
void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
||||
CINSTREAM_SKIP_HEADER;
|
||||
LWOOBJID playerID;
|
||||
inStream.Read(playerID);
|
||||
|
||||
const auto& sender = Game::playerContainer.GetPlayerData(playerID);
|
||||
if (!sender || sender.GetIsMuted()) return;
|
||||
|
||||
eChatChannel channel;
|
||||
uint32_t size;
|
||||
|
||||
inStream.IgnoreBytes(4);
|
||||
inStream.Read(channel);
|
||||
inStream.Read(size);
|
||||
inStream.IgnoreBytes(77);
|
||||
|
||||
LUWString message(size);
|
||||
inStream.Read(message);
|
||||
|
||||
LOG("Got a message from (%s) via [%s]: %s", sender.playerName.c_str(), StringifiedEnum::ToString(channel).data(), message.GetAsString().c_str());
|
||||
|
||||
switch (channel) {
|
||||
case eChatChannel::TEAM: {
|
||||
auto* team = Game::playerContainer.GetTeam(playerID);
|
||||
if (team == nullptr) return;
|
||||
|
||||
for (const auto memberId : team->memberIDs) {
|
||||
const auto& otherMember = Game::playerContainer.GetPlayerData(memberId);
|
||||
if (!otherMember) return;
|
||||
SendPrivateChatMessage(sender, otherMember, otherMember, message, eChatChannel::TEAM, eChatMessageResponseCode::SENT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG("Unhandled Chat channel [%s]", StringifiedEnum::ToString(channel).data());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// the structure the client uses to send this packet is shared in many chat messages
|
||||
// that are sent to the server. Because of this, there are large gaps of unused data in chat messages
|
||||
void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
||||
CINSTREAM_SKIP_HEADER;
|
||||
LWOOBJID playerID;
|
||||
inStream.Read(playerID);
|
||||
|
||||
const auto& sender = Game::playerContainer.GetPlayerData(playerID);
|
||||
if (!sender || sender.GetIsMuted()) return;
|
||||
|
||||
eChatChannel channel;
|
||||
uint32_t size;
|
||||
LUWString LUReceiverName;
|
||||
|
||||
inStream.IgnoreBytes(4);
|
||||
inStream.Read(channel);
|
||||
if (channel != eChatChannel::PRIVATE_CHAT) LOG("WARNING: Received Private chat with the wrong channel!");
|
||||
|
||||
inStream.Read(size);
|
||||
inStream.IgnoreBytes(77);
|
||||
|
||||
inStream.Read(LUReceiverName);
|
||||
auto receiverName = LUReceiverName.GetAsString();
|
||||
inStream.IgnoreBytes(2);
|
||||
|
||||
LUWString message(size);
|
||||
inStream.Read(message);
|
||||
|
||||
LOG("Got a message from (%s) via [%s]: %s to %s", sender.playerName.c_str(), StringifiedEnum::ToString(channel).data(), message.GetAsString().c_str(), receiverName.c_str());
|
||||
|
||||
const auto& receiver = Game::playerContainer.GetPlayerData(receiverName);
|
||||
if (!receiver) {
|
||||
PlayerData otherPlayer;
|
||||
otherPlayer.playerName = receiverName;
|
||||
auto responseType = Database::Get()->GetCharacterInfo(receiverName)
|
||||
? eChatMessageResponseCode::NOTONLINE
|
||||
: eChatMessageResponseCode::GENERALERROR;
|
||||
|
||||
SendPrivateChatMessage(sender, otherPlayer, sender, message, eChatChannel::GENERAL, responseType);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check to see if they are friends
|
||||
// only freinds can whispr each other
|
||||
for (const auto& fr : receiver.friends) {
|
||||
if (fr.friendID == sender.playerID) {
|
||||
//To the sender:
|
||||
SendPrivateChatMessage(sender, receiver, sender, message, eChatChannel::PRIVATE_CHAT, eChatMessageResponseCode::SENT);
|
||||
//To the receiver:
|
||||
SendPrivateChatMessage(sender, receiver, receiver, message, eChatChannel::PRIVATE_CHAT, eChatMessageResponseCode::RECEIVEDNEWWHISPER);
|
||||
return;
|
||||
}
|
||||
}
|
||||
SendPrivateChatMessage(sender, receiver, sender, message, eChatChannel::GENERAL, eChatMessageResponseCode::NOTFRIENDS);
|
||||
}
|
||||
|
||||
void ChatPacketHandler::SendPrivateChatMessage(const PlayerData& sender, const PlayerData& receiver, const PlayerData& routeTo, const LUWString& message, const eChatChannel channel, const eChatMessageResponseCode responseCode) {
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||
bitStream.Write(routeTo.playerID);
|
||||
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
||||
bitStream.Write(sender.playerID);
|
||||
bitStream.Write(channel);
|
||||
bitStream.Write<uint32_t>(0); // not used
|
||||
bitStream.Write(LUWString(sender.playerName));
|
||||
bitStream.Write(sender.playerID);
|
||||
bitStream.Write<uint16_t>(0); // sourceID
|
||||
bitStream.Write(sender.gmLevel);
|
||||
bitStream.Write(LUWString(receiver.playerName));
|
||||
bitStream.Write(receiver.gmLevel);
|
||||
bitStream.Write(responseCode);
|
||||
bitStream.Write(message);
|
||||
|
||||
SystemAddress sysAddr = routeTo.sysAddr;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
|
||||
void ChatPacketHandler::HandleTeamInvite(Packet* packet) {
|
||||
CINSTREAM_SKIP_HEADER;
|
||||
|
||||
LWOOBJID playerID;
|
||||
LUWString invitedPlayer;
|
||||
|
||||
inStream.Read(playerID);
|
||||
inStream.IgnoreBytes(4);
|
||||
inStream.Read(invitedPlayer);
|
||||
|
||||
const auto& player = Game::playerContainer.GetPlayerData(playerID);
|
||||
|
||||
@@ -463,7 +495,7 @@ void ChatPacketHandler::HandleTeamInvite(Packet* packet) {
|
||||
team = Game::playerContainer.CreateTeam(playerID);
|
||||
}
|
||||
|
||||
const auto& other = Game::playerContainer.GetPlayerData(invitedPlayer);
|
||||
const auto& other = Game::playerContainer.GetPlayerData(invitedPlayer.GetAsString());
|
||||
|
||||
if (!other) return;
|
||||
|
||||
@@ -480,7 +512,7 @@ void ChatPacketHandler::HandleTeamInvite(Packet* packet) {
|
||||
|
||||
SendTeamInvite(other, player);
|
||||
|
||||
LOG("Got team invite: %llu -> %s", playerID, invitedPlayer.c_str());
|
||||
LOG("Got team invite: %llu -> %s", playerID, invitedPlayer.GetAsString().c_str());
|
||||
}
|
||||
|
||||
void ChatPacketHandler::HandleTeamInviteResponse(Packet* packet) {
|
||||
@@ -534,21 +566,25 @@ void ChatPacketHandler::HandleTeamLeave(Packet* packet) {
|
||||
|
||||
void ChatPacketHandler::HandleTeamKick(Packet* packet) {
|
||||
CINSTREAM_SKIP_HEADER;
|
||||
|
||||
LWOOBJID playerID = LWOOBJID_EMPTY;
|
||||
LUWString kickedPlayer;
|
||||
|
||||
inStream.Read(playerID);
|
||||
inStream.IgnoreBytes(4);
|
||||
inStream.Read(kickedPlayer);
|
||||
|
||||
std::string kickedPlayer = PacketUtils::ReadString(0x14, packet, true);
|
||||
|
||||
LOG("(%llu) kicking (%s) from team", playerID, kickedPlayer.c_str());
|
||||
LOG("(%llu) kicking (%s) from team", playerID, kickedPlayer.GetAsString().c_str());
|
||||
|
||||
const auto& kicked = Game::playerContainer.GetPlayerData(kickedPlayer);
|
||||
const auto& kicked = Game::playerContainer.GetPlayerData(kickedPlayer.GetAsString());
|
||||
|
||||
LWOOBJID kickedId = LWOOBJID_EMPTY;
|
||||
|
||||
if (kicked) {
|
||||
kickedId = kicked.playerID;
|
||||
} else {
|
||||
kickedId = Game::playerContainer.GetId(GeneralUtils::UTF8ToUTF16(kickedPlayer));
|
||||
kickedId = Game::playerContainer.GetId(kickedPlayer.string);
|
||||
}
|
||||
|
||||
if (kickedId == LWOOBJID_EMPTY) return;
|
||||
@@ -564,14 +600,17 @@ void ChatPacketHandler::HandleTeamKick(Packet* packet) {
|
||||
|
||||
void ChatPacketHandler::HandleTeamPromote(Packet* packet) {
|
||||
CINSTREAM_SKIP_HEADER;
|
||||
|
||||
LWOOBJID playerID = LWOOBJID_EMPTY;
|
||||
LUWString promotedPlayer;
|
||||
|
||||
inStream.Read(playerID);
|
||||
inStream.IgnoreBytes(4);
|
||||
inStream.Read(promotedPlayer);
|
||||
|
||||
std::string promotedPlayer = PacketUtils::ReadString(0x14, packet, true);
|
||||
LOG("(%llu) promoting (%s) to team leader", playerID, promotedPlayer.GetAsString().c_str());
|
||||
|
||||
LOG("(%llu) promoting (%s) to team leader", playerID, promotedPlayer.c_str());
|
||||
|
||||
const auto& promoted = Game::playerContainer.GetPlayerData(promotedPlayer);
|
||||
const auto& promoted = Game::playerContainer.GetPlayerData(promotedPlayer.GetAsString());
|
||||
|
||||
if (!promoted) return;
|
||||
|
||||
|
||||
@@ -7,14 +7,53 @@ struct PlayerData;
|
||||
|
||||
enum class eAddFriendResponseType : uint8_t;
|
||||
|
||||
enum class eChatChannel : uint8_t {
|
||||
SYSTEMNOTIFY = 0,
|
||||
SYSTEMWARNING,
|
||||
SYSTEMERROR,
|
||||
BROADCAST,
|
||||
LOCAL,
|
||||
LOCALNOANIM,
|
||||
EMOTE,
|
||||
PRIVATE_CHAT,
|
||||
TEAM,
|
||||
TEAMLOCAL,
|
||||
GUILD,
|
||||
GUILDNOTIFY,
|
||||
PROPERTY,
|
||||
ADMIN,
|
||||
COMBATDAMAGE,
|
||||
COMBATHEALING,
|
||||
COMBATLOOT,
|
||||
COMBATEXP,
|
||||
COMBATDEATH,
|
||||
GENERAL,
|
||||
TRADE,
|
||||
LFG,
|
||||
USER
|
||||
};
|
||||
|
||||
|
||||
enum class eChatMessageResponseCode : uint8_t {
|
||||
SENT = 0,
|
||||
NOTONLINE,
|
||||
GENERALERROR,
|
||||
RECEIVEDNEWWHISPER,
|
||||
NOTFRIENDS,
|
||||
SENDERFREETRIAL,
|
||||
RECEIVERFREETRIAL,
|
||||
};
|
||||
|
||||
namespace ChatPacketHandler {
|
||||
void HandleFriendlistRequest(Packet* packet);
|
||||
void HandleFriendRequest(Packet* packet);
|
||||
void HandleFriendResponse(Packet* packet);
|
||||
void HandleRemoveFriend(Packet* packet);
|
||||
void HandleGMLevelUpdate(Packet* packet);
|
||||
|
||||
void HandleChatMessage(Packet* packet);
|
||||
void HandlePrivateChatMessage(Packet* packet);
|
||||
void SendPrivateChatMessage(const PlayerData& sender, const PlayerData& receiver, const PlayerData& routeTo, const LUWString& message, const eChatChannel channel, const eChatMessageResponseCode responseCode);
|
||||
|
||||
void HandleTeamInvite(Packet* packet);
|
||||
void HandleTeamInviteResponse(Packet* packet);
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "eChatInternalMessageType.h"
|
||||
#include "eWorldMessageType.h"
|
||||
#include "ChatIgnoreList.h"
|
||||
#include "StringifiedEnum.h"
|
||||
|
||||
#include "Game.h"
|
||||
#include "Server.h"
|
||||
@@ -223,7 +224,8 @@ void HandlePacket(Packet* packet) {
|
||||
}
|
||||
|
||||
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::CHAT) {
|
||||
switch (static_cast<eChatMessageType>(packet->data[3])) {
|
||||
eChatMessageType chat_message_type = static_cast<eChatMessageType>(packet->data[3]);
|
||||
switch (chat_message_type) {
|
||||
case eChatMessageType::GET_FRIENDS_LIST:
|
||||
ChatPacketHandler::HandleFriendlistRequest(packet);
|
||||
break;
|
||||
@@ -293,9 +295,61 @@ void HandlePacket(Packet* packet) {
|
||||
case eChatMessageType::TEAM_SET_LOOT:
|
||||
ChatPacketHandler::HandleTeamLootOption(packet);
|
||||
break;
|
||||
|
||||
case eChatMessageType::GMLEVEL_UPDATE:
|
||||
ChatPacketHandler::HandleGMLevelUpdate(packet);
|
||||
break;
|
||||
case eChatMessageType::LOGIN_SESSION_NOTIFY:
|
||||
case eChatMessageType::USER_CHANNEL_CHAT_MESSAGE:
|
||||
case eChatMessageType::WORLD_DISCONNECT_REQUEST:
|
||||
case eChatMessageType::WORLD_PROXIMITY_RESPONSE:
|
||||
case eChatMessageType::WORLD_PARCEL_RESPONSE:
|
||||
case eChatMessageType::TEAM_MISSED_INVITE_CHECK:
|
||||
case eChatMessageType::GUILD_CREATE:
|
||||
case eChatMessageType::GUILD_INVITE:
|
||||
case eChatMessageType::GUILD_INVITE_RESPONSE:
|
||||
case eChatMessageType::GUILD_LEAVE:
|
||||
case eChatMessageType::GUILD_KICK:
|
||||
case eChatMessageType::GUILD_GET_STATUS:
|
||||
case eChatMessageType::GUILD_GET_ALL:
|
||||
case eChatMessageType::SHOW_ALL:
|
||||
case eChatMessageType::BLUEPRINT_MODERATED:
|
||||
case eChatMessageType::BLUEPRINT_MODEL_READY:
|
||||
case eChatMessageType::PROPERTY_READY_FOR_APPROVAL:
|
||||
case eChatMessageType::PROPERTY_MODERATION_CHANGED:
|
||||
case eChatMessageType::PROPERTY_BUILDMODE_CHANGED:
|
||||
case eChatMessageType::PROPERTY_BUILDMODE_CHANGED_REPORT:
|
||||
case eChatMessageType::MAIL:
|
||||
case eChatMessageType::WORLD_INSTANCE_LOCATION_REQUEST:
|
||||
case eChatMessageType::REPUTATION_UPDATE:
|
||||
case eChatMessageType::SEND_CANNED_TEXT:
|
||||
case eChatMessageType::CHARACTER_NAME_CHANGE_REQUEST:
|
||||
case eChatMessageType::CSR_REQUEST:
|
||||
case eChatMessageType::CSR_REPLY:
|
||||
case eChatMessageType::GM_KICK:
|
||||
case eChatMessageType::GM_ANNOUNCE:
|
||||
case eChatMessageType::WORLD_ROUTE_PACKET:
|
||||
case eChatMessageType::GET_ZONE_POPULATIONS:
|
||||
case eChatMessageType::REQUEST_MINIMUM_CHAT_MODE:
|
||||
case eChatMessageType::MATCH_REQUEST:
|
||||
case eChatMessageType::UGCMANIFEST_REPORT_MISSING_FILE:
|
||||
case eChatMessageType::UGCMANIFEST_REPORT_DONE_FILE:
|
||||
case eChatMessageType::UGCMANIFEST_REPORT_DONE_BLUEPRINT:
|
||||
case eChatMessageType::UGCC_REQUEST:
|
||||
case eChatMessageType::WHO:
|
||||
case eChatMessageType::WORLD_PLAYERS_PET_MODERATED_ACKNOWLEDGE:
|
||||
case eChatMessageType::ACHIEVEMENT_NOTIFY:
|
||||
case eChatMessageType::GM_CLOSE_PRIVATE_CHAT_WINDOW:
|
||||
case eChatMessageType::UNEXPECTED_DISCONNECT:
|
||||
case eChatMessageType::PLAYER_READY:
|
||||
case eChatMessageType::GET_DONATION_TOTAL:
|
||||
case eChatMessageType::UPDATE_DONATION:
|
||||
case eChatMessageType::PRG_CSR_COMMAND:
|
||||
case eChatMessageType::HEARTBEAT_REQUEST_FROM_WORLD:
|
||||
case eChatMessageType::UPDATE_FREE_TRIAL_STATUS:
|
||||
LOG("Unhandled CHAT Message id: %s (%i)", StringifiedEnum::ToString(chat_message_type).data(), chat_message_type);
|
||||
break;
|
||||
default:
|
||||
LOG("Unknown CHAT id: %i", int(packet->data[3]));
|
||||
LOG("Unknown CHAT Message id: %i", chat_message_type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "Database.h"
|
||||
#include "eConnectionType.h"
|
||||
#include "eChatInternalMessageType.h"
|
||||
#include "eGameMasterLevel.h"
|
||||
#include "ChatPackets.h"
|
||||
#include "dConfig.h"
|
||||
|
||||
@@ -22,6 +23,10 @@ PlayerContainer::~PlayerContainer() {
|
||||
m_Players.clear();
|
||||
}
|
||||
|
||||
PlayerData::PlayerData() {
|
||||
gmLevel = eGameMasterLevel::CIVILIAN;
|
||||
}
|
||||
|
||||
TeamData::TeamData() {
|
||||
lootFlag = Game::config->GetValue("default_team_loot") == "0" ? 0 : 1;
|
||||
}
|
||||
@@ -47,6 +52,7 @@ void PlayerContainer::InsertPlayer(Packet* packet) {
|
||||
|
||||
inStream.Read(data.zoneID);
|
||||
inStream.Read(data.muteExpire);
|
||||
inStream.Read(data.gmLevel);
|
||||
data.sysAddr = packet->systemAddress;
|
||||
|
||||
m_Names[data.playerID] = GeneralUtils::UTF8ToUTF16(data.playerName);
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include "dServer.h"
|
||||
#include <unordered_map>
|
||||
|
||||
enum class eGameMasterLevel : uint8_t;
|
||||
|
||||
struct IgnoreData {
|
||||
IgnoreData(const std::string& name, const LWOOBJID& id) : playerName(name), playerId(id) {}
|
||||
inline bool operator==(const std::string& other) const noexcept {
|
||||
@@ -22,6 +24,7 @@ struct IgnoreData {
|
||||
};
|
||||
|
||||
struct PlayerData {
|
||||
PlayerData();
|
||||
operator bool() const noexcept {
|
||||
return playerID != LWOOBJID_EMPTY;
|
||||
}
|
||||
@@ -42,6 +45,8 @@ struct PlayerData {
|
||||
std::string playerName;
|
||||
std::vector<FriendData> friends;
|
||||
std::vector<IgnoreData> ignoredPlayers;
|
||||
eGameMasterLevel gmLevel;
|
||||
bool isFTP = false;
|
||||
};
|
||||
|
||||
struct TeamData {
|
||||
|
||||
@@ -20,6 +20,12 @@ set(DCOMMON_SOURCES
|
||||
"FdbToSqlite.cpp"
|
||||
)
|
||||
|
||||
# Workaround for compiler bug where the optimized code could result in a memcpy of 0 bytes, even though that isnt possible.
|
||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97185
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
set_source_files_properties("FdbToSqlite.cpp" PROPERTIES COMPILE_FLAGS "-Wno-stringop-overflow")
|
||||
endif()
|
||||
|
||||
add_subdirectory(dClient)
|
||||
|
||||
foreach(file ${DCOMMON_DCLIENT_SOURCES})
|
||||
@@ -62,3 +68,8 @@ else ()
|
||||
endif ()
|
||||
|
||||
target_link_libraries(dCommon ZLIB::ZLIB)
|
||||
|
||||
# Disable deprecation warnings on MD5.cpp and SHA512.cpp for Apple Clang
|
||||
if (APPLE)
|
||||
set_source_files_properties("MD5.cpp" "SHA512.cpp" PROPERTIES COMPILE_FLAGS "-Wno-deprecated-declarations")
|
||||
endif()
|
||||
|
||||
@@ -1,210 +1,24 @@
|
||||
#include "NiPoint3.h"
|
||||
#include "NiQuaternion.h"
|
||||
|
||||
// C++
|
||||
#include <cmath>
|
||||
|
||||
// Static Variables
|
||||
const NiPoint3 NiPoint3::ZERO(0.0f, 0.0f, 0.0f);
|
||||
const NiPoint3 NiPoint3::UNIT_X(1.0f, 0.0f, 0.0f);
|
||||
const NiPoint3 NiPoint3::UNIT_Y(0.0f, 1.0f, 0.0f);
|
||||
const NiPoint3 NiPoint3::UNIT_Z(0.0f, 0.0f, 1.0f);
|
||||
const NiPoint3 NiPoint3::UNIT_ALL(1.0f, 1.0f, 1.0f);
|
||||
|
||||
//! Initializer
|
||||
NiPoint3::NiPoint3(void) {
|
||||
this->x = 0;
|
||||
this->y = 0;
|
||||
this->z = 0;
|
||||
}
|
||||
|
||||
//! Initializer
|
||||
NiPoint3::NiPoint3(float x, float y, float z) {
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
this->z = z;
|
||||
}
|
||||
|
||||
//! Copy Constructor
|
||||
NiPoint3::NiPoint3(const NiPoint3& point) {
|
||||
this->x = point.x;
|
||||
this->y = point.y;
|
||||
this->z = point.z;
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
NiPoint3::~NiPoint3(void) {}
|
||||
|
||||
// MARK: Getters / Setters
|
||||
|
||||
//! Gets the X coordinate
|
||||
float NiPoint3::GetX(void) const {
|
||||
return this->x;
|
||||
}
|
||||
|
||||
//! Sets the X coordinate
|
||||
void NiPoint3::SetX(float x) {
|
||||
this->x = x;
|
||||
}
|
||||
|
||||
//! Gets the Y coordinate
|
||||
float NiPoint3::GetY(void) const {
|
||||
return this->y;
|
||||
}
|
||||
|
||||
//! Sets the Y coordinate
|
||||
void NiPoint3::SetY(float y) {
|
||||
this->y = y;
|
||||
}
|
||||
|
||||
//! Gets the Z coordinate
|
||||
float NiPoint3::GetZ(void) const {
|
||||
return this->z;
|
||||
}
|
||||
|
||||
//! Sets the Z coordinate
|
||||
void NiPoint3::SetZ(float z) {
|
||||
this->z = z;
|
||||
}
|
||||
|
||||
// MARK: Functions
|
||||
// MARK: Member Functions
|
||||
|
||||
//! Gets the length of the vector
|
||||
float NiPoint3::Length(void) const {
|
||||
return sqrt(x * x + y * y + z * z);
|
||||
}
|
||||
|
||||
//! Gets the squared length of a vector
|
||||
float NiPoint3::SquaredLength(void) const {
|
||||
return (x * x + y * y + z * z);
|
||||
}
|
||||
|
||||
//! Returns the dot product of the vector dotted with another vector
|
||||
float NiPoint3::DotProduct(const Vector3& vec) const {
|
||||
return ((this->x * vec.x) + (this->y * vec.y) + (this->z * vec.z));
|
||||
}
|
||||
|
||||
//! Returns the cross product of the vector crossed with another vector
|
||||
Vector3 NiPoint3::CrossProduct(const Vector3& vec) const {
|
||||
return Vector3(((this->y * vec.z) - (this->z * vec.y)),
|
||||
((this->z * vec.x) - (this->x * vec.z)),
|
||||
((this->x * vec.y) - (this->y * vec.x)));
|
||||
float NiPoint3::Length() const {
|
||||
return std::sqrt(x * x + y * y + z * z);
|
||||
}
|
||||
|
||||
//! Unitize the vector
|
||||
NiPoint3 NiPoint3::Unitize(void) const {
|
||||
NiPoint3 NiPoint3::Unitize() const {
|
||||
float length = this->Length();
|
||||
|
||||
return length != 0 ? *this / length : NiPoint3::ZERO;
|
||||
return length != 0 ? *this / length : NiPoint3Constant::ZERO;
|
||||
}
|
||||
|
||||
|
||||
// MARK: Operators
|
||||
|
||||
//! Operator to check for equality
|
||||
bool NiPoint3::operator==(const NiPoint3& point) const {
|
||||
return point.x == this->x && point.y == this->y && point.z == this->z;
|
||||
}
|
||||
|
||||
//! Operator to check for inequality
|
||||
bool NiPoint3::operator!=(const NiPoint3& point) const {
|
||||
return !(*this == point);
|
||||
}
|
||||
|
||||
//! Operator for subscripting
|
||||
float& NiPoint3::operator[](int i) {
|
||||
float* base = &x;
|
||||
return base[i];
|
||||
}
|
||||
|
||||
//! Operator for subscripting
|
||||
const float& NiPoint3::operator[](int i) const {
|
||||
const float* base = &x;
|
||||
return base[i];
|
||||
}
|
||||
|
||||
//! Operator for addition of vectors
|
||||
NiPoint3 NiPoint3::operator+(const NiPoint3& point) const {
|
||||
return NiPoint3(this->x + point.x, this->y + point.y, this->z + point.z);
|
||||
}
|
||||
|
||||
//! Operator for addition of vectors
|
||||
NiPoint3& NiPoint3::operator+=(const NiPoint3& point) {
|
||||
this->x += point.x;
|
||||
this->y += point.y;
|
||||
this->z += point.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
NiPoint3& NiPoint3::operator*=(const float scalar) {
|
||||
this->x *= scalar;
|
||||
this->y *= scalar;
|
||||
this->z *= scalar;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Operator for subtraction of vectors
|
||||
NiPoint3 NiPoint3::operator-(const NiPoint3& point) const {
|
||||
return NiPoint3(this->x - point.x, this->y - point.y, this->z - point.z);
|
||||
}
|
||||
|
||||
//! Operator for addition of a scalar on all vector components
|
||||
NiPoint3 NiPoint3::operator+(float fScalar) const {
|
||||
return NiPoint3(this->x + fScalar, this->y + fScalar, this->z + fScalar);
|
||||
}
|
||||
|
||||
//! Operator for subtraction of a scalar on all vector components
|
||||
NiPoint3 NiPoint3::operator-(float fScalar) const {
|
||||
return NiPoint3(this->x - fScalar, this->y - fScalar, this->z - fScalar);
|
||||
}
|
||||
|
||||
//! Operator for scalar multiplication of a vector
|
||||
NiPoint3 NiPoint3::operator*(float fScalar) const {
|
||||
return NiPoint3(this->x * fScalar, this->y * fScalar, this->z * fScalar);
|
||||
}
|
||||
|
||||
//! Operator for scalar division of a vector
|
||||
NiPoint3 NiPoint3::operator/(float fScalar) const {
|
||||
float retX = this->x != 0 ? this->x / fScalar : 0;
|
||||
float retY = this->y != 0 ? this->y / fScalar : 0;
|
||||
float retZ = this->z != 0 ? this->z / fScalar : 0;
|
||||
return NiPoint3(retX, retY, retZ);
|
||||
}
|
||||
|
||||
|
||||
// MARK: Helper Functions
|
||||
|
||||
//! Checks to see if the point (or vector) is with an Axis-Aligned Bounding Box
|
||||
bool NiPoint3::IsWithinAxisAlignedBox(const NiPoint3& minPoint, const NiPoint3& maxPoint) {
|
||||
if (this->x < minPoint.x) return false;
|
||||
if (this->x > maxPoint.x) return false;
|
||||
if (this->y < minPoint.y) return false;
|
||||
if (this->y > maxPoint.y) return false;
|
||||
|
||||
return (this->z < maxPoint.z && this->z > minPoint.z);
|
||||
}
|
||||
|
||||
//! Checks to see if the point (or vector) is within a sphere
|
||||
bool NiPoint3::IsWithinSpehere(const NiPoint3& sphereCenter, float radius) {
|
||||
Vector3 diffVec = Vector3(x - sphereCenter.GetX(), y - sphereCenter.GetY(), z - sphereCenter.GetZ());
|
||||
return (diffVec.SquaredLength() <= (radius * radius));
|
||||
}
|
||||
|
||||
NiPoint3 NiPoint3::ClosestPointOnLine(const NiPoint3& a, const NiPoint3& b, const NiPoint3& p) {
|
||||
if (a == b) return a;
|
||||
|
||||
const auto pa = p - a;
|
||||
const auto ab = b - a;
|
||||
|
||||
const auto t = pa.DotProduct(ab) / ab.SquaredLength();
|
||||
|
||||
if (t <= 0.0f) return a;
|
||||
|
||||
if (t >= 1.0f) return b;
|
||||
|
||||
return a + ab * t;
|
||||
}
|
||||
|
||||
float NiPoint3::Angle(const NiPoint3& a, const NiPoint3& b) {
|
||||
const auto dot = a.DotProduct(b);
|
||||
const auto lenA = a.SquaredLength();
|
||||
@@ -220,15 +34,7 @@ float NiPoint3::Distance(const NiPoint3& a, const NiPoint3& b) {
|
||||
return std::sqrt(dx * dx + dy * dy + dz * dz);
|
||||
}
|
||||
|
||||
float NiPoint3::DistanceSquared(const NiPoint3& a, const NiPoint3& b) {
|
||||
const auto dx = a.x - b.x;
|
||||
const auto dy = a.y - b.y;
|
||||
const auto dz = a.z - b.z;
|
||||
|
||||
return dx * dx + dy * dy + dz * dz;
|
||||
}
|
||||
|
||||
NiPoint3 NiPoint3::MoveTowards(const NiPoint3& current, const NiPoint3& target, float maxDistanceDelta) {
|
||||
NiPoint3 NiPoint3::MoveTowards(const NiPoint3& current, const NiPoint3& target, const float maxDistanceDelta) {
|
||||
float dx = target.x - current.x;
|
||||
float dy = target.y - current.y;
|
||||
float dz = target.z - current.z;
|
||||
@@ -249,29 +55,3 @@ NiPoint3 NiPoint3::MoveTowards(const NiPoint3& current, const NiPoint3& target,
|
||||
float length = std::sqrt(lengthSquared);
|
||||
return NiPoint3(current.x + dx / length * maxDistanceDelta, current.y + dy / length * maxDistanceDelta, current.z + dz / length * maxDistanceDelta);
|
||||
}
|
||||
|
||||
//This code is yoinked from the MS XNA code, so it should be right, even if it's horrible.
|
||||
NiPoint3 NiPoint3::RotateByQuaternion(const NiQuaternion& rotation) {
|
||||
Vector3 vector;
|
||||
float num12 = rotation.x + rotation.x;
|
||||
float num2 = rotation.y + rotation.y;
|
||||
float num = rotation.z + rotation.z;
|
||||
float num11 = rotation.w * num12;
|
||||
float num10 = rotation.w * num2;
|
||||
float num9 = rotation.w * num;
|
||||
float num8 = rotation.x * num12;
|
||||
float num7 = rotation.x * num2;
|
||||
float num6 = rotation.x * num;
|
||||
float num5 = rotation.y * num2;
|
||||
float num4 = rotation.y * num;
|
||||
float num3 = rotation.z * num;
|
||||
|
||||
NiPoint3 value = *this;
|
||||
float num15 = ((value.x * ((1.0f - num5) - num3)) + (value.y * (num7 - num9))) + (value.z * (num6 + num10));
|
||||
float num14 = ((value.x * (num7 + num9)) + (value.y * ((1.0f - num8) - num3))) + (value.z * (num4 - num11));
|
||||
float num13 = ((value.x * (num6 - num10)) + (value.y * (num4 + num11))) + (value.z * ((1.0f - num8) - num5));
|
||||
vector.x = num15;
|
||||
vector.y = num14;
|
||||
vector.z = num13;
|
||||
return vector;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#ifndef __NIPOINT3_H__
|
||||
#define __NIPOINT3_H__
|
||||
|
||||
/*!
|
||||
\file NiPoint3.hpp
|
||||
@@ -12,13 +13,13 @@ typedef NiPoint3 Vector3; //!< The Vector3 class is technically the NiPoin
|
||||
//! A custom class the defines a point in space
|
||||
class NiPoint3 {
|
||||
public:
|
||||
float x; //!< The x position
|
||||
float y; //!< The y position
|
||||
float z; //!< The z position
|
||||
float x{ 0 }; //!< The x position
|
||||
float y{ 0 }; //!< The y position
|
||||
float z{ 0 }; //!< The z position
|
||||
|
||||
|
||||
//! Initializer
|
||||
NiPoint3(void);
|
||||
constexpr NiPoint3() = default;
|
||||
|
||||
//! Initializer
|
||||
/*!
|
||||
@@ -26,23 +27,21 @@ public:
|
||||
\param y The y coordinate
|
||||
\param z The z coordinate
|
||||
*/
|
||||
NiPoint3(float x, float y, float z);
|
||||
constexpr NiPoint3(const float x, const float y, const float z) noexcept
|
||||
: x{ x }
|
||||
, y{ y }
|
||||
, z{ z } {
|
||||
}
|
||||
|
||||
//! Copy Constructor
|
||||
/*!
|
||||
\param point The point to copy
|
||||
*/
|
||||
NiPoint3(const NiPoint3& point);
|
||||
|
||||
//! Destructor
|
||||
~NiPoint3(void);
|
||||
|
||||
// MARK: Constants
|
||||
static const NiPoint3 ZERO; //!< Point(0, 0, 0)
|
||||
static const NiPoint3 UNIT_X; //!< Point(1, 0, 0)
|
||||
static const NiPoint3 UNIT_Y; //!< Point(0, 1, 0)
|
||||
static const NiPoint3 UNIT_Z; //!< Point(0, 0, 1)
|
||||
static const NiPoint3 UNIT_ALL; //!< Point(1, 1, 1)
|
||||
constexpr NiPoint3(const NiPoint3& point) noexcept
|
||||
: x{ point.x }
|
||||
, y{ point.y }
|
||||
, z{ point.z } {
|
||||
}
|
||||
|
||||
// MARK: Getters / Setters
|
||||
|
||||
@@ -50,38 +49,37 @@ public:
|
||||
/*!
|
||||
\return The x coordinate
|
||||
*/
|
||||
float GetX(void) const;
|
||||
[[nodiscard]] constexpr float GetX() const noexcept;
|
||||
|
||||
//! Sets the X coordinate
|
||||
/*!
|
||||
\param x The x coordinate
|
||||
*/
|
||||
void SetX(float x);
|
||||
constexpr void SetX(const float x) noexcept;
|
||||
|
||||
//! Gets the Y coordinate
|
||||
/*!
|
||||
\return The y coordinate
|
||||
*/
|
||||
float GetY(void) const;
|
||||
[[nodiscard]] constexpr float GetY() const noexcept;
|
||||
|
||||
//! Sets the Y coordinate
|
||||
/*!
|
||||
\param y The y coordinate
|
||||
*/
|
||||
void SetY(float y);
|
||||
constexpr void SetY(const float y) noexcept;
|
||||
|
||||
//! Gets the Z coordinate
|
||||
/*!
|
||||
\return The z coordinate
|
||||
*/
|
||||
float GetZ(void) const;
|
||||
[[nodiscard]] constexpr float GetZ() const noexcept;
|
||||
|
||||
//! Sets the Z coordinate
|
||||
/*!
|
||||
\param z The z coordinate
|
||||
*/
|
||||
void SetZ(float z);
|
||||
|
||||
constexpr void SetZ(const float z) noexcept;
|
||||
|
||||
// MARK: Member Functions
|
||||
|
||||
@@ -89,72 +87,70 @@ public:
|
||||
/*!
|
||||
\return The scalar length of the vector
|
||||
*/
|
||||
float Length(void) const;
|
||||
[[nodiscard]] float Length() const;
|
||||
|
||||
//! Gets the squared length of a vector
|
||||
/*!
|
||||
\return The squared length of a vector
|
||||
*/
|
||||
float SquaredLength(void) const;
|
||||
[[nodiscard]] constexpr float SquaredLength() const noexcept;
|
||||
|
||||
//! Returns the dot product of the vector dotted with another vector
|
||||
/*!
|
||||
\param vec The second vector
|
||||
\return The dot product of the two vectors
|
||||
*/
|
||||
float DotProduct(const Vector3& vec) const;
|
||||
[[nodiscard]] constexpr float DotProduct(const Vector3& vec) const noexcept;
|
||||
|
||||
//! Returns the cross product of the vector crossed with another vector
|
||||
/*!
|
||||
\param vec The second vector
|
||||
\return The cross product of the two vectors
|
||||
*/
|
||||
Vector3 CrossProduct(const Vector3& vec) const;
|
||||
[[nodiscard]] constexpr Vector3 CrossProduct(const Vector3& vec) const noexcept;
|
||||
|
||||
//! Unitize the vector
|
||||
/*!
|
||||
\returns The current vector
|
||||
*/
|
||||
NiPoint3 Unitize(void) const;
|
||||
|
||||
[[nodiscard]] NiPoint3 Unitize() const;
|
||||
|
||||
// MARK: Operators
|
||||
|
||||
//! Operator to check for equality
|
||||
bool operator==(const NiPoint3& point) const;
|
||||
constexpr bool operator==(const NiPoint3& point) const noexcept;
|
||||
|
||||
//! Operator to check for inequality
|
||||
bool operator!=(const NiPoint3& point) const;
|
||||
constexpr bool operator!=(const NiPoint3& point) const noexcept;
|
||||
|
||||
//! Operator for subscripting
|
||||
float& operator[](int i);
|
||||
constexpr float& operator[](const int i) noexcept;
|
||||
|
||||
//! Operator for subscripting
|
||||
const float& operator[](int i) const;
|
||||
constexpr const float& operator[](const int i) const noexcept;
|
||||
|
||||
//! Operator for addition of vectors
|
||||
NiPoint3 operator+(const NiPoint3& point) const;
|
||||
constexpr NiPoint3 operator+(const NiPoint3& point) const noexcept;
|
||||
|
||||
//! Operator for addition of vectors
|
||||
NiPoint3& operator+=(const NiPoint3& point);
|
||||
constexpr NiPoint3& operator+=(const NiPoint3& point) noexcept;
|
||||
|
||||
NiPoint3& operator*=(const float scalar);
|
||||
constexpr NiPoint3& operator*=(const float scalar) noexcept;
|
||||
|
||||
//! Operator for subtraction of vectors
|
||||
NiPoint3 operator-(const NiPoint3& point) const;
|
||||
constexpr NiPoint3 operator-(const NiPoint3& point) const noexcept;
|
||||
|
||||
//! Operator for addition of a scalar on all vector components
|
||||
NiPoint3 operator+(float fScalar) const;
|
||||
constexpr NiPoint3 operator+(const float fScalar) const noexcept;
|
||||
|
||||
//! Operator for subtraction of a scalar on all vector components
|
||||
NiPoint3 operator-(float fScalar) const;
|
||||
constexpr NiPoint3 operator-(const float fScalar) const noexcept;
|
||||
|
||||
//! Operator for scalar multiplication of a vector
|
||||
NiPoint3 operator*(float fScalar) const;
|
||||
constexpr NiPoint3 operator*(const float fScalar) const noexcept;
|
||||
|
||||
//! Operator for scalar division of a vector
|
||||
NiPoint3 operator/(float fScalar) const;
|
||||
|
||||
constexpr NiPoint3 operator/(const float fScalar) const noexcept;
|
||||
|
||||
// MARK: Helper Functions
|
||||
|
||||
@@ -164,14 +160,14 @@ public:
|
||||
\param maxPoint The maximum point of the bounding box
|
||||
\return Whether or not this point lies within the box
|
||||
*/
|
||||
bool IsWithinAxisAlignedBox(const NiPoint3& minPoint, const NiPoint3& maxPoint);
|
||||
[[nodiscard]] constexpr bool IsWithinAxisAlignedBox(const NiPoint3& minPoint, const NiPoint3& maxPoint) noexcept;
|
||||
|
||||
//! Checks to see if the point (or vector) is within a sphere
|
||||
/*!
|
||||
\param sphereCenter The sphere center
|
||||
\param radius The radius
|
||||
*/
|
||||
bool IsWithinSpehere(const NiPoint3& sphereCenter, float radius);
|
||||
[[nodiscard]] constexpr bool IsWithinSphere(const NiPoint3& sphereCenter, const float radius) noexcept;
|
||||
|
||||
/*!
|
||||
\param a Start of line
|
||||
@@ -179,15 +175,30 @@ public:
|
||||
\param p Refrence point
|
||||
\return The point of line AB which is closest to P
|
||||
*/
|
||||
static NiPoint3 ClosestPointOnLine(const NiPoint3& a, const NiPoint3& b, const NiPoint3& p);
|
||||
[[nodiscard]] static constexpr NiPoint3 ClosestPointOnLine(const NiPoint3& a, const NiPoint3& b, const NiPoint3& p) noexcept;
|
||||
|
||||
static float Angle(const NiPoint3& a, const NiPoint3& b);
|
||||
[[nodiscard]] static float Angle(const NiPoint3& a, const NiPoint3& b);
|
||||
|
||||
static float Distance(const NiPoint3& a, const NiPoint3& b);
|
||||
[[nodiscard]] static float Distance(const NiPoint3& a, const NiPoint3& b);
|
||||
|
||||
static float DistanceSquared(const NiPoint3& a, const NiPoint3& b);
|
||||
[[nodiscard]] static constexpr float DistanceSquared(const NiPoint3& a, const NiPoint3& b) noexcept;
|
||||
|
||||
static NiPoint3 MoveTowards(const NiPoint3& current, const NiPoint3& target, float maxDistanceDelta);
|
||||
[[nodiscard]] static NiPoint3 MoveTowards(const NiPoint3& current, const NiPoint3& target, const float maxDistanceDelta);
|
||||
|
||||
NiPoint3 RotateByQuaternion(const NiQuaternion& rotation);
|
||||
//This code is yoinked from the MS XNA code, so it should be right, even if it's horrible.
|
||||
[[nodiscard]] constexpr NiPoint3 RotateByQuaternion(const NiQuaternion& rotation) noexcept;
|
||||
};
|
||||
|
||||
// Static Variables
|
||||
namespace NiPoint3Constant {
|
||||
constexpr NiPoint3 ZERO(0.0f, 0.0f, 0.0f);
|
||||
constexpr NiPoint3 UNIT_X(1.0f, 0.0f, 0.0f);
|
||||
constexpr NiPoint3 UNIT_Y(0.0f, 1.0f, 0.0f);
|
||||
constexpr NiPoint3 UNIT_Z(0.0f, 0.0f, 1.0f);
|
||||
constexpr NiPoint3 UNIT_ALL(1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
// .inl file needed for code organization and to circumvent circular dependency issues
|
||||
#include "NiPoint3.inl"
|
||||
|
||||
#endif // !__NIPOINT3_H__
|
||||
|
||||
196
dCommon/NiPoint3.inl
Normal file
196
dCommon/NiPoint3.inl
Normal file
@@ -0,0 +1,196 @@
|
||||
#pragma once
|
||||
#ifndef __NIPOINT3_H__
|
||||
#error "This should only be included inline in NiPoint3.h: Do not include directly!"
|
||||
#endif
|
||||
|
||||
#include "NiQuaternion.h"
|
||||
|
||||
// MARK: Getters / Setters
|
||||
|
||||
//! Gets the X coordinate
|
||||
constexpr float NiPoint3::GetX() const noexcept {
|
||||
return this->x;
|
||||
}
|
||||
|
||||
//! Sets the X coordinate
|
||||
constexpr void NiPoint3::SetX(const float x) noexcept {
|
||||
this->x = x;
|
||||
}
|
||||
|
||||
//! Gets the Y coordinate
|
||||
constexpr float NiPoint3::GetY() const noexcept {
|
||||
return this->y;
|
||||
}
|
||||
|
||||
//! Sets the Y coordinate
|
||||
constexpr void NiPoint3::SetY(const float y) noexcept {
|
||||
this->y = y;
|
||||
}
|
||||
|
||||
//! Gets the Z coordinate
|
||||
constexpr float NiPoint3::GetZ() const noexcept {
|
||||
return this->z;
|
||||
}
|
||||
|
||||
//! Sets the Z coordinate
|
||||
constexpr void NiPoint3::SetZ(const float z) noexcept {
|
||||
this->z = z;
|
||||
}
|
||||
|
||||
// MARK: Member Functions
|
||||
|
||||
//! Gets the squared length of a vector
|
||||
constexpr float NiPoint3::SquaredLength() const noexcept {
|
||||
return (x * x + y * y + z * z);
|
||||
}
|
||||
|
||||
//! Returns the dot product of the vector dotted with another vector
|
||||
constexpr float NiPoint3::DotProduct(const Vector3& vec) const noexcept {
|
||||
return ((this->x * vec.x) + (this->y * vec.y) + (this->z * vec.z));
|
||||
}
|
||||
|
||||
//! Returns the cross product of the vector crossed with another vector
|
||||
constexpr Vector3 NiPoint3::CrossProduct(const Vector3& vec) const noexcept {
|
||||
return Vector3(((this->y * vec.z) - (this->z * vec.y)),
|
||||
((this->z * vec.x) - (this->x * vec.z)),
|
||||
((this->x * vec.y) - (this->y * vec.x)));
|
||||
}
|
||||
|
||||
// MARK: Operators
|
||||
|
||||
//! Operator to check for equality
|
||||
constexpr bool NiPoint3::operator==(const NiPoint3& point) const noexcept {
|
||||
return point.x == this->x && point.y == this->y && point.z == this->z;
|
||||
}
|
||||
|
||||
//! Operator to check for inequality
|
||||
constexpr bool NiPoint3::operator!=(const NiPoint3& point) const noexcept {
|
||||
return !(*this == point);
|
||||
}
|
||||
|
||||
//! Operator for subscripting
|
||||
constexpr float& NiPoint3::operator[](const int i) noexcept {
|
||||
float* base = &x;
|
||||
return base[i];
|
||||
}
|
||||
|
||||
//! Operator for subscripting
|
||||
constexpr const float& NiPoint3::operator[](const int i) const noexcept {
|
||||
const float* base = &x;
|
||||
return base[i];
|
||||
}
|
||||
|
||||
//! Operator for addition of vectors
|
||||
constexpr NiPoint3 NiPoint3::operator+(const NiPoint3& point) const noexcept {
|
||||
return NiPoint3(this->x + point.x, this->y + point.y, this->z + point.z);
|
||||
}
|
||||
|
||||
//! Operator for addition of vectors
|
||||
constexpr NiPoint3& NiPoint3::operator+=(const NiPoint3& point) noexcept {
|
||||
this->x += point.x;
|
||||
this->y += point.y;
|
||||
this->z += point.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr NiPoint3& NiPoint3::operator*=(const float scalar) noexcept {
|
||||
this->x *= scalar;
|
||||
this->y *= scalar;
|
||||
this->z *= scalar;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Operator for subtraction of vectors
|
||||
constexpr NiPoint3 NiPoint3::operator-(const NiPoint3& point) const noexcept {
|
||||
return NiPoint3(this->x - point.x, this->y - point.y, this->z - point.z);
|
||||
}
|
||||
|
||||
//! Operator for addition of a scalar on all vector components
|
||||
constexpr NiPoint3 NiPoint3::operator+(const float fScalar) const noexcept {
|
||||
return NiPoint3(this->x + fScalar, this->y + fScalar, this->z + fScalar);
|
||||
}
|
||||
|
||||
//! Operator for subtraction of a scalar on all vector components
|
||||
constexpr NiPoint3 NiPoint3::operator-(const float fScalar) const noexcept {
|
||||
return NiPoint3(this->x - fScalar, this->y - fScalar, this->z - fScalar);
|
||||
}
|
||||
|
||||
//! Operator for scalar multiplication of a vector
|
||||
constexpr NiPoint3 NiPoint3::operator*(const float fScalar) const noexcept {
|
||||
return NiPoint3(this->x * fScalar, this->y * fScalar, this->z * fScalar);
|
||||
}
|
||||
|
||||
//! Operator for scalar division of a vector
|
||||
constexpr NiPoint3 NiPoint3::operator/(const float fScalar) const noexcept {
|
||||
float retX = this->x != 0 ? this->x / fScalar : 0;
|
||||
float retY = this->y != 0 ? this->y / fScalar : 0;
|
||||
float retZ = this->z != 0 ? this->z / fScalar : 0;
|
||||
return NiPoint3(retX, retY, retZ);
|
||||
}
|
||||
|
||||
// MARK: Helper Functions
|
||||
|
||||
//! Checks to see if the point (or vector) is with an Axis-Aligned Bounding Box
|
||||
constexpr bool NiPoint3::IsWithinAxisAlignedBox(const NiPoint3& minPoint, const NiPoint3& maxPoint) noexcept {
|
||||
if (this->x < minPoint.x) return false;
|
||||
if (this->x > maxPoint.x) return false;
|
||||
if (this->y < minPoint.y) return false;
|
||||
if (this->y > maxPoint.y) return false;
|
||||
|
||||
return (this->z < maxPoint.z && this->z > minPoint.z);
|
||||
}
|
||||
|
||||
//! Checks to see if the point (or vector) is within a sphere
|
||||
constexpr bool NiPoint3::IsWithinSphere(const NiPoint3& sphereCenter, const float radius) noexcept {
|
||||
Vector3 diffVec = Vector3(x - sphereCenter.GetX(), y - sphereCenter.GetY(), z - sphereCenter.GetZ());
|
||||
return (diffVec.SquaredLength() <= (radius * radius));
|
||||
}
|
||||
|
||||
constexpr NiPoint3 NiPoint3::ClosestPointOnLine(const NiPoint3& a, const NiPoint3& b, const NiPoint3& p) noexcept {
|
||||
if (a == b) return a;
|
||||
|
||||
const auto pa = p - a;
|
||||
const auto ab = b - a;
|
||||
|
||||
const auto t = pa.DotProduct(ab) / ab.SquaredLength();
|
||||
|
||||
if (t <= 0.0f) return a;
|
||||
|
||||
if (t >= 1.0f) return b;
|
||||
|
||||
return a + ab * t;
|
||||
}
|
||||
|
||||
constexpr float NiPoint3::DistanceSquared(const NiPoint3& a, const NiPoint3& b) noexcept {
|
||||
const auto dx = a.x - b.x;
|
||||
const auto dy = a.y - b.y;
|
||||
const auto dz = a.z - b.z;
|
||||
|
||||
return dx * dx + dy * dy + dz * dz;
|
||||
}
|
||||
|
||||
//This code is yoinked from the MS XNA code, so it should be right, even if it's horrible.
|
||||
constexpr NiPoint3 NiPoint3::RotateByQuaternion(const NiQuaternion& rotation) noexcept {
|
||||
Vector3 vector;
|
||||
float num12 = rotation.x + rotation.x;
|
||||
float num2 = rotation.y + rotation.y;
|
||||
float num = rotation.z + rotation.z;
|
||||
float num11 = rotation.w * num12;
|
||||
float num10 = rotation.w * num2;
|
||||
float num9 = rotation.w * num;
|
||||
float num8 = rotation.x * num12;
|
||||
float num7 = rotation.x * num2;
|
||||
float num6 = rotation.x * num;
|
||||
float num5 = rotation.y * num2;
|
||||
float num4 = rotation.y * num;
|
||||
float num3 = rotation.z * num;
|
||||
|
||||
NiPoint3 value = *this;
|
||||
float num15 = ((value.x * ((1.0f - num5) - num3)) + (value.y * (num7 - num9))) + (value.z * (num6 + num10));
|
||||
float num14 = ((value.x * (num7 + num9)) + (value.y * ((1.0f - num8) - num3))) + (value.z * (num4 - num11));
|
||||
float num13 = ((value.x * (num6 - num10)) + (value.y * (num4 + num11))) + (value.z * ((1.0f - num8) - num5));
|
||||
vector.x = num15;
|
||||
vector.y = num14;
|
||||
vector.z = num13;
|
||||
return vector;
|
||||
}
|
||||
@@ -3,89 +3,8 @@
|
||||
// C++
|
||||
#include <cmath>
|
||||
|
||||
// Static Variables
|
||||
const NiQuaternion NiQuaternion::IDENTITY(1, 0, 0, 0);
|
||||
|
||||
//! The initializer
|
||||
NiQuaternion::NiQuaternion(void) {
|
||||
this->w = 1;
|
||||
this->x = 0;
|
||||
this->y = 0;
|
||||
this->z = 0;
|
||||
}
|
||||
|
||||
//! The initializer
|
||||
NiQuaternion::NiQuaternion(float w, float x, float y, float z) {
|
||||
this->w = w;
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
this->z = z;
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
NiQuaternion::~NiQuaternion(void) {}
|
||||
|
||||
|
||||
// MARK: Setters / Getters
|
||||
|
||||
//! Gets the W coordinate
|
||||
float NiQuaternion::GetW(void) const {
|
||||
return this->w;
|
||||
}
|
||||
|
||||
//! Sets the W coordinate
|
||||
void NiQuaternion::SetW(float w) {
|
||||
this->w = w;
|
||||
}
|
||||
|
||||
//! Gets the X coordinate
|
||||
float NiQuaternion::GetX(void) const {
|
||||
return this->x;
|
||||
}
|
||||
|
||||
//! Sets the X coordinate
|
||||
void NiQuaternion::SetX(float x) {
|
||||
this->x = x;
|
||||
}
|
||||
|
||||
//! Gets the Y coordinate
|
||||
float NiQuaternion::GetY(void) const {
|
||||
return this->y;
|
||||
}
|
||||
|
||||
//! Sets the Y coordinate
|
||||
void NiQuaternion::SetY(float y) {
|
||||
this->y = y;
|
||||
}
|
||||
|
||||
//! Gets the Z coordinate
|
||||
float NiQuaternion::GetZ(void) const {
|
||||
return this->z;
|
||||
}
|
||||
|
||||
//! Sets the Z coordinate
|
||||
void NiQuaternion::SetZ(float z) {
|
||||
this->z = z;
|
||||
}
|
||||
|
||||
|
||||
// MARK: Member Functions
|
||||
|
||||
//! Returns the forward vector from the quaternion
|
||||
Vector3 NiQuaternion::GetForwardVector(void) const {
|
||||
return Vector3(2 * (x * z + w * y), 2 * (y * z - w * x), 1 - 2 * (x * x + y * y));
|
||||
}
|
||||
|
||||
//! Returns the up vector from the quaternion
|
||||
Vector3 NiQuaternion::GetUpVector(void) const {
|
||||
return Vector3(2 * (x * y - w * z), 1 - 2 * (x * x + z * z), 2 * (y * z + w * x));
|
||||
}
|
||||
|
||||
//! Returns the right vector from the quaternion
|
||||
Vector3 NiQuaternion::GetRightVector(void) const {
|
||||
return Vector3(1 - 2 * (y * y + z * z), 2 * (x * y + w * z), 2 * (x * z - w * y));
|
||||
}
|
||||
|
||||
Vector3 NiQuaternion::GetEulerAngles() const {
|
||||
Vector3 angles;
|
||||
|
||||
@@ -111,22 +30,9 @@ Vector3 NiQuaternion::GetEulerAngles() const {
|
||||
return angles;
|
||||
}
|
||||
|
||||
// MARK: Operators
|
||||
|
||||
//! Operator to check for equality
|
||||
bool NiQuaternion::operator==(const NiQuaternion& rot) const {
|
||||
return rot.x == this->x && rot.y == this->y && rot.z == this->z && rot.w == this->w;
|
||||
}
|
||||
|
||||
//! Operator to check for inequality
|
||||
bool NiQuaternion::operator!=(const NiQuaternion& rot) const {
|
||||
return !(*this == rot);
|
||||
}
|
||||
|
||||
|
||||
// MARK: Helper Functions
|
||||
|
||||
//! Look from a specific point in space to another point in space
|
||||
//! Look from a specific point in space to another point in space (Y-locked)
|
||||
NiQuaternion NiQuaternion::LookAt(const NiPoint3& sourcePoint, const NiPoint3& destPoint) {
|
||||
//To make sure we don't orient around the X/Z axis:
|
||||
NiPoint3 source = sourcePoint;
|
||||
@@ -136,7 +42,7 @@ NiQuaternion NiQuaternion::LookAt(const NiPoint3& sourcePoint, const NiPoint3& d
|
||||
|
||||
NiPoint3 forwardVector = NiPoint3(dest - source).Unitize();
|
||||
|
||||
NiPoint3 posZ = NiPoint3::UNIT_Z;
|
||||
NiPoint3 posZ = NiPoint3Constant::UNIT_Z;
|
||||
NiPoint3 vecA = posZ.CrossProduct(forwardVector).Unitize();
|
||||
|
||||
float dot = posZ.DotProduct(forwardVector);
|
||||
@@ -148,10 +54,11 @@ NiQuaternion NiQuaternion::LookAt(const NiPoint3& sourcePoint, const NiPoint3& d
|
||||
return NiQuaternion::CreateFromAxisAngle(vecA, rotAngle);
|
||||
}
|
||||
|
||||
//! Look from a specific point in space to another point in space
|
||||
NiQuaternion NiQuaternion::LookAtUnlocked(const NiPoint3& sourcePoint, const NiPoint3& destPoint) {
|
||||
NiPoint3 forwardVector = NiPoint3(destPoint - sourcePoint).Unitize();
|
||||
|
||||
NiPoint3 posZ = NiPoint3::UNIT_Z;
|
||||
NiPoint3 posZ = NiPoint3Constant::UNIT_Z;
|
||||
NiPoint3 vecA = posZ.CrossProduct(forwardVector).Unitize();
|
||||
|
||||
float dot = posZ.DotProduct(forwardVector);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#ifndef __NIQUATERNION_H__
|
||||
#define __NIQUATERNION_H__
|
||||
|
||||
// Custom Classes
|
||||
#include "NiPoint3.h"
|
||||
@@ -14,14 +15,14 @@ typedef NiQuaternion Quaternion; //!< A typedef for a shorthand version o
|
||||
//! A class that defines a rotation in space
|
||||
class NiQuaternion {
|
||||
public:
|
||||
float w; //!< The w coordinate
|
||||
float x; //!< The x coordinate
|
||||
float y; //!< The y coordinate
|
||||
float z; //!< The z coordinate
|
||||
float w{ 1 }; //!< The w coordinate
|
||||
float x{ 0 }; //!< The x coordinate
|
||||
float y{ 0 }; //!< The y coordinate
|
||||
float z{ 0 }; //!< The z coordinate
|
||||
|
||||
|
||||
//! The initializer
|
||||
NiQuaternion(void);
|
||||
constexpr NiQuaternion() = default;
|
||||
|
||||
//! The initializer
|
||||
/*!
|
||||
@@ -30,13 +31,12 @@ public:
|
||||
\param y The y coordinate
|
||||
\param z The z coordinate
|
||||
*/
|
||||
NiQuaternion(float w, float x, float y, float z);
|
||||
|
||||
//! Destructor
|
||||
~NiQuaternion(void);
|
||||
|
||||
// MARK: Constants
|
||||
static const NiQuaternion IDENTITY; //!< Quaternion(1, 0, 0, 0)
|
||||
constexpr NiQuaternion(const float w, const float x, const float y, const float z) noexcept
|
||||
: w{ w }
|
||||
, x{ x }
|
||||
, y{ y }
|
||||
, z{ z } {
|
||||
}
|
||||
|
||||
// MARK: Setters / Getters
|
||||
|
||||
@@ -44,50 +44,49 @@ public:
|
||||
/*!
|
||||
\return The w coordinate
|
||||
*/
|
||||
float GetW(void) const;
|
||||
[[nodiscard]] constexpr float GetW() const noexcept;
|
||||
|
||||
//! Sets the W coordinate
|
||||
/*!
|
||||
\param w The w coordinate
|
||||
*/
|
||||
void SetW(float w);
|
||||
constexpr void SetW(const float w) noexcept;
|
||||
|
||||
//! Gets the X coordinate
|
||||
/*!
|
||||
\return The x coordinate
|
||||
*/
|
||||
float GetX(void) const;
|
||||
[[nodiscard]] constexpr float GetX() const noexcept;
|
||||
|
||||
//! Sets the X coordinate
|
||||
/*!
|
||||
\param x The x coordinate
|
||||
*/
|
||||
void SetX(float x);
|
||||
constexpr void SetX(const float x) noexcept;
|
||||
|
||||
//! Gets the Y coordinate
|
||||
/*!
|
||||
\return The y coordinate
|
||||
*/
|
||||
float GetY(void) const;
|
||||
[[nodiscard]] constexpr float GetY() const noexcept;
|
||||
|
||||
//! Sets the Y coordinate
|
||||
/*!
|
||||
\param y The y coordinate
|
||||
*/
|
||||
void SetY(float y);
|
||||
constexpr void SetY(const float y) noexcept;
|
||||
|
||||
//! Gets the Z coordinate
|
||||
/*!
|
||||
\return The z coordinate
|
||||
*/
|
||||
float GetZ(void) const;
|
||||
[[nodiscard]] constexpr float GetZ() const noexcept;
|
||||
|
||||
//! Sets the Z coordinate
|
||||
/*!
|
||||
\param z The z coordinate
|
||||
*/
|
||||
void SetZ(float z);
|
||||
|
||||
constexpr void SetZ(const float z) noexcept;
|
||||
|
||||
// MARK: Member Functions
|
||||
|
||||
@@ -95,31 +94,29 @@ public:
|
||||
/*!
|
||||
\return The forward vector of the quaternion
|
||||
*/
|
||||
Vector3 GetForwardVector(void) const;
|
||||
[[nodiscard]] constexpr Vector3 GetForwardVector() const noexcept;
|
||||
|
||||
//! Returns the up vector from the quaternion
|
||||
/*!
|
||||
\return The up vector fo the quaternion
|
||||
*/
|
||||
Vector3 GetUpVector(void) const;
|
||||
[[nodiscard]] constexpr Vector3 GetUpVector() const noexcept;
|
||||
|
||||
//! Returns the right vector from the quaternion
|
||||
/*!
|
||||
\return The right vector of the quaternion
|
||||
*/
|
||||
Vector3 GetRightVector(void) const;
|
||||
|
||||
Vector3 GetEulerAngles() const;
|
||||
[[nodiscard]] constexpr Vector3 GetRightVector() const noexcept;
|
||||
|
||||
[[nodiscard]] Vector3 GetEulerAngles() const;
|
||||
|
||||
// MARK: Operators
|
||||
|
||||
//! Operator to check for equality
|
||||
bool operator==(const NiQuaternion& rot) const;
|
||||
constexpr bool operator==(const NiQuaternion& rot) const noexcept;
|
||||
|
||||
//! Operator to check for inequality
|
||||
bool operator!=(const NiQuaternion& rot) const;
|
||||
|
||||
constexpr bool operator!=(const NiQuaternion& rot) const noexcept;
|
||||
|
||||
// MARK: Helper Functions
|
||||
|
||||
@@ -129,7 +126,7 @@ public:
|
||||
\param destPoint The destination location
|
||||
\return The Quaternion with the rotation towards the destination
|
||||
*/
|
||||
static NiQuaternion LookAt(const NiPoint3& sourcePoint, const NiPoint3& destPoint);
|
||||
[[nodiscard]] static NiQuaternion LookAt(const NiPoint3& sourcePoint, const NiPoint3& destPoint);
|
||||
|
||||
//! Look from a specific point in space to another point in space
|
||||
/*!
|
||||
@@ -137,7 +134,7 @@ public:
|
||||
\param destPoint The destination location
|
||||
\return The Quaternion with the rotation towards the destination
|
||||
*/
|
||||
static NiQuaternion LookAtUnlocked(const NiPoint3& sourcePoint, const NiPoint3& destPoint);
|
||||
[[nodiscard]] static NiQuaternion LookAtUnlocked(const NiPoint3& sourcePoint, const NiPoint3& destPoint);
|
||||
|
||||
//! Creates a Quaternion from a specific axis and angle relative to that axis
|
||||
/*!
|
||||
@@ -145,7 +142,17 @@ public:
|
||||
\param angle The angle relative to this axis
|
||||
\return A quaternion created from the axis and angle
|
||||
*/
|
||||
static NiQuaternion CreateFromAxisAngle(const Vector3& axis, float angle);
|
||||
[[nodiscard]] static NiQuaternion CreateFromAxisAngle(const Vector3& axis, float angle);
|
||||
|
||||
static NiQuaternion FromEulerAngles(const NiPoint3& eulerAngles);
|
||||
[[nodiscard]] static NiQuaternion FromEulerAngles(const NiPoint3& eulerAngles);
|
||||
};
|
||||
|
||||
// Static Variables
|
||||
namespace NiQuaternionConstant {
|
||||
constexpr NiQuaternion IDENTITY(1, 0, 0, 0);
|
||||
}
|
||||
|
||||
// Include constexpr and inline function definitions in a seperate file for readability
|
||||
#include "NiQuaternion.inl"
|
||||
|
||||
#endif // !__NIQUATERNION_H__
|
||||
|
||||
75
dCommon/NiQuaternion.inl
Normal file
75
dCommon/NiQuaternion.inl
Normal file
@@ -0,0 +1,75 @@
|
||||
#pragma once
|
||||
#ifndef __NIQUATERNION_H__
|
||||
#error "This should only be included inline in NiQuaternion.h: Do not include directly!"
|
||||
#endif
|
||||
|
||||
// MARK: Setters / Getters
|
||||
|
||||
//! Gets the W coordinate
|
||||
constexpr float NiQuaternion::GetW() const noexcept {
|
||||
return this->w;
|
||||
}
|
||||
|
||||
//! Sets the W coordinate
|
||||
constexpr void NiQuaternion::SetW(const float w) noexcept {
|
||||
this->w = w;
|
||||
}
|
||||
|
||||
//! Gets the X coordinate
|
||||
constexpr float NiQuaternion::GetX() const noexcept {
|
||||
return this->x;
|
||||
}
|
||||
|
||||
//! Sets the X coordinate
|
||||
constexpr void NiQuaternion::SetX(const float x) noexcept {
|
||||
this->x = x;
|
||||
}
|
||||
|
||||
//! Gets the Y coordinate
|
||||
constexpr float NiQuaternion::GetY() const noexcept {
|
||||
return this->y;
|
||||
}
|
||||
|
||||
//! Sets the Y coordinate
|
||||
constexpr void NiQuaternion::SetY(const float y) noexcept {
|
||||
this->y = y;
|
||||
}
|
||||
|
||||
//! Gets the Z coordinate
|
||||
constexpr float NiQuaternion::GetZ() const noexcept {
|
||||
return this->z;
|
||||
}
|
||||
|
||||
//! Sets the Z coordinate
|
||||
constexpr void NiQuaternion::SetZ(const float z) noexcept {
|
||||
this->z = z;
|
||||
}
|
||||
|
||||
// MARK: Member Functions
|
||||
|
||||
//! Returns the forward vector from the quaternion
|
||||
constexpr Vector3 NiQuaternion::GetForwardVector() const noexcept {
|
||||
return Vector3(2 * (x * z + w * y), 2 * (y * z - w * x), 1 - 2 * (x * x + y * y));
|
||||
}
|
||||
|
||||
//! Returns the up vector from the quaternion
|
||||
constexpr Vector3 NiQuaternion::GetUpVector() const noexcept {
|
||||
return Vector3(2 * (x * y - w * z), 1 - 2 * (x * x + z * z), 2 * (y * z + w * x));
|
||||
}
|
||||
|
||||
//! Returns the right vector from the quaternion
|
||||
constexpr Vector3 NiQuaternion::GetRightVector() const noexcept {
|
||||
return Vector3(1 - 2 * (y * y + z * z), 2 * (x * y + w * z), 2 * (x * z - w * y));
|
||||
}
|
||||
|
||||
// MARK: Operators
|
||||
|
||||
//! Operator to check for equality
|
||||
constexpr bool NiQuaternion::operator==(const NiQuaternion& rot) const noexcept {
|
||||
return rot.x == this->x && rot.y == this->y && rot.z == this->z && rot.w == this->w;
|
||||
}
|
||||
|
||||
//! Operator to check for inequality
|
||||
constexpr bool NiQuaternion::operator!=(const NiQuaternion& rot) const noexcept {
|
||||
return !(*this == rot);
|
||||
}
|
||||
@@ -32,17 +32,17 @@ struct RemoteInputInfo {
|
||||
|
||||
struct LocalSpaceInfo {
|
||||
LWOOBJID objectId = LWOOBJID_EMPTY;
|
||||
NiPoint3 position = NiPoint3::ZERO;
|
||||
NiPoint3 linearVelocity = NiPoint3::ZERO;
|
||||
NiPoint3 position = NiPoint3Constant::ZERO;
|
||||
NiPoint3 linearVelocity = NiPoint3Constant::ZERO;
|
||||
};
|
||||
|
||||
struct PositionUpdate {
|
||||
NiPoint3 position = NiPoint3::ZERO;
|
||||
NiQuaternion rotation = NiQuaternion::IDENTITY;
|
||||
NiPoint3 position = NiPoint3Constant::ZERO;
|
||||
NiQuaternion rotation = NiQuaternionConstant::IDENTITY;
|
||||
bool onGround = false;
|
||||
bool onRail = false;
|
||||
NiPoint3 velocity = NiPoint3::ZERO;
|
||||
NiPoint3 angularVelocity = NiPoint3::ZERO;
|
||||
NiPoint3 velocity = NiPoint3Constant::ZERO;
|
||||
NiPoint3 angularVelocity = NiPoint3Constant::ZERO;
|
||||
LocalSpaceInfo localSpaceInfo;
|
||||
RemoteInputInfo remoteInputInfo;
|
||||
};
|
||||
|
||||
@@ -9,15 +9,15 @@ namespace StringifiedEnum {
|
||||
const std::string_view ToString(const T e) {
|
||||
static_assert(std::is_enum_v<T>, "Not an enum"); // Check type
|
||||
|
||||
constexpr auto sv = &magic_enum::enum_entries<T>();
|
||||
constexpr auto& sv = magic_enum::enum_entries<T>();
|
||||
|
||||
const auto it = std::lower_bound(
|
||||
sv->begin(), sv->end(), e,
|
||||
sv.begin(), sv.end(), e,
|
||||
[&](const std::pair<T, std::string_view>& lhs, const T rhs) { return lhs.first < rhs; }
|
||||
);
|
||||
|
||||
std::string_view output;
|
||||
if (it != sv->end() && it->first == e) {
|
||||
if (it != sv.end() && it->first == e) {
|
||||
output = it->second;
|
||||
} else {
|
||||
output = "UNKNOWN";
|
||||
|
||||
@@ -2,7 +2,7 @@ set(DGAME_SOURCES "Character.cpp"
|
||||
"Entity.cpp"
|
||||
"EntityManager.cpp"
|
||||
"LeaderboardManager.cpp"
|
||||
"Player.cpp"
|
||||
"PlayerManager.cpp"
|
||||
"TeamManager.cpp"
|
||||
"TradingManager.cpp"
|
||||
"User.cpp"
|
||||
|
||||
@@ -451,7 +451,7 @@ void Character::LoadXmlRespawnCheckpoints() {
|
||||
auto* r = points->FirstChildElement("r");
|
||||
while (r != nullptr) {
|
||||
int32_t map = 0;
|
||||
NiPoint3 point = NiPoint3::ZERO;
|
||||
NiPoint3 point = NiPoint3Constant::ZERO;
|
||||
|
||||
r->QueryAttribute("w", &map);
|
||||
r->QueryAttribute("x", &point.x);
|
||||
@@ -513,7 +513,7 @@ void Character::SetRespawnPoint(LWOMAPID map, const NiPoint3& point) {
|
||||
const NiPoint3& Character::GetRespawnPoint(LWOMAPID map) const {
|
||||
const auto& pair = m_WorldRespawnCheckpoints.find(map);
|
||||
|
||||
if (pair == m_WorldRespawnCheckpoints.end()) return NiPoint3::ZERO;
|
||||
if (pair == m_WorldRespawnCheckpoints.end()) return NiPoint3Constant::ZERO;
|
||||
|
||||
return pair->second;
|
||||
}
|
||||
|
||||
@@ -457,6 +457,8 @@ public:
|
||||
|
||||
void SetBillboardVisible(bool visible);
|
||||
|
||||
User* GetParentUser() const { return m_ParentUser; }
|
||||
|
||||
private:
|
||||
void UpdateInfoFromDatabase();
|
||||
/**
|
||||
|
||||
184
dGame/Entity.cpp
184
dGame/Entity.cpp
@@ -15,7 +15,6 @@
|
||||
#include "Spawner.h"
|
||||
#include "UserManager.h"
|
||||
#include "dpWorld.h"
|
||||
#include "Player.h"
|
||||
#include "LUTriggers.h"
|
||||
#include "User.h"
|
||||
#include "EntityTimer.h"
|
||||
@@ -25,6 +24,8 @@
|
||||
#include "eTriggerEventType.h"
|
||||
#include "eObjectBits.h"
|
||||
#include "PositionUpdate.h"
|
||||
#include "eChatMessageType.h"
|
||||
#include "PlayerManager.h"
|
||||
|
||||
//Component includes:
|
||||
#include "Component.h"
|
||||
@@ -94,7 +95,7 @@
|
||||
#include "CDSkillBehaviorTable.h"
|
||||
#include "CDZoneTableTable.h"
|
||||
|
||||
Entity::Entity(const LWOOBJID& objectID, EntityInfo info, Entity* parentEntity) {
|
||||
Entity::Entity(const LWOOBJID& objectID, EntityInfo info, User* parentUser, Entity* parentEntity) {
|
||||
m_ObjectID = objectID;
|
||||
m_TemplateID = info.lot;
|
||||
m_ParentEntity = parentEntity;
|
||||
@@ -123,9 +124,42 @@ Entity::Entity(const LWOOBJID& objectID, EntityInfo info, Entity* parentEntity)
|
||||
m_SpawnerNodeID = info.spawnerNodeID;
|
||||
|
||||
if (info.lot != 1) m_PlayerIsReadyForUpdates = true;
|
||||
if (parentUser) {
|
||||
m_Character = parentUser->GetLastUsedChar();
|
||||
parentUser->SetLoggedInChar(objectID);
|
||||
m_GMLevel = m_Character->GetGMLevel();
|
||||
|
||||
m_Character->SetEntity(this);
|
||||
|
||||
PlayerManager::AddPlayer(this);
|
||||
}
|
||||
}
|
||||
|
||||
Entity::~Entity() {
|
||||
if (IsPlayer()) {
|
||||
LOG("Deleted player");
|
||||
|
||||
// Make sure the player exists first. Remove afterwards to prevent the OnPlayerExist functions from not being able to find the player.
|
||||
if (!PlayerManager::RemovePlayer(this)) {
|
||||
LOG("Unable to find player to remove from manager.");
|
||||
return;
|
||||
}
|
||||
|
||||
Entity* zoneControl = Game::entityManager->GetZoneControlEntity();
|
||||
for (CppScripts::Script* script : CppScripts::GetEntityScripts(zoneControl)) {
|
||||
script->OnPlayerExit(zoneControl, this);
|
||||
}
|
||||
|
||||
std::vector<Entity*> scriptedActs = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::SCRIPTED_ACTIVITY);
|
||||
for (Entity* scriptEntity : scriptedActs) {
|
||||
if (scriptEntity->GetObjectID() != zoneControl->GetObjectID()) { // Don't want to trigger twice on instance worlds
|
||||
for (CppScripts::Script* script : CppScripts::GetEntityScripts(scriptEntity)) {
|
||||
script->OnPlayerExit(scriptEntity, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_Character) {
|
||||
m_Character->SaveXMLToDatabase();
|
||||
}
|
||||
@@ -211,7 +245,7 @@ void Entity::Initialize() {
|
||||
* Not all components are implemented. Some are represented by a nullptr, as they hold no data.
|
||||
*/
|
||||
|
||||
if (GetParentUser()) {
|
||||
if (m_Character && m_Character->GetParentUser()) {
|
||||
AddComponent<MissionComponent>()->LoadFromXml(m_Character->GetXMLDoc());
|
||||
}
|
||||
|
||||
@@ -436,7 +470,8 @@ void Entity::Initialize() {
|
||||
|
||||
AddComponent<PlayerForcedMovementComponent>();
|
||||
|
||||
AddComponent<CharacterComponent>(m_Character)->LoadFromXml(m_Character->GetXMLDoc());
|
||||
auto& systemAddress = m_Character->GetParentUser() ? m_Character->GetParentUser()->GetSystemAddress() : UNASSIGNED_SYSTEM_ADDRESS;
|
||||
AddComponent<CharacterComponent>(m_Character, systemAddress)->LoadFromXml(m_Character->GetXMLDoc());
|
||||
|
||||
AddComponent<GhostComponent>();
|
||||
}
|
||||
@@ -787,14 +822,6 @@ bool Entity::operator!=(const Entity& other) const {
|
||||
return other.m_ObjectID != m_ObjectID;
|
||||
}
|
||||
|
||||
User* Entity::GetParentUser() const {
|
||||
if (!IsPlayer()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return static_cast<const Player*>(this)->GetParentUser();
|
||||
}
|
||||
|
||||
Component* Entity::GetComponent(eReplicaComponentType componentID) const {
|
||||
const auto& index = m_Components.find(componentID);
|
||||
|
||||
@@ -849,18 +876,24 @@ void Entity::SetProximityRadius(dpEntity* entity, std::string name) {
|
||||
|
||||
void Entity::SetGMLevel(eGameMasterLevel value) {
|
||||
m_GMLevel = value;
|
||||
if (GetParentUser()) {
|
||||
Character* character = GetParentUser()->GetLastUsedChar();
|
||||
if (m_Character) m_Character->SetGMLevel(value);
|
||||
|
||||
if (character) {
|
||||
character->SetGMLevel(value);
|
||||
}
|
||||
}
|
||||
auto* characterComponent = GetComponent<CharacterComponent>();
|
||||
if (!characterComponent) return;
|
||||
|
||||
CharacterComponent* character = GetComponent<CharacterComponent>();
|
||||
if (character) character->SetGMLevel(value);
|
||||
characterComponent->SetGMLevel(value);
|
||||
|
||||
GameMessages::SendGMLevelBroadcast(m_ObjectID, value);
|
||||
|
||||
// Update the chat server of our GM Level
|
||||
{
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::GMLEVEL_UPDATE);
|
||||
bitStream.Write(m_ObjectID);
|
||||
bitStream.Write(m_GMLevel);
|
||||
|
||||
Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false);
|
||||
}
|
||||
}
|
||||
|
||||
void Entity::WriteBaseReplicaData(RakNet::BitStream* outBitStream, eReplicaPacketType packetType) {
|
||||
@@ -1345,17 +1378,11 @@ void Entity::OnCollisionPhantom(const LWOOBJID otherEntity) {
|
||||
}
|
||||
|
||||
if (!other->GetIsDead()) {
|
||||
auto* combat = GetComponent<BaseCombatAIComponent>();
|
||||
|
||||
if (combat != nullptr) {
|
||||
if (GetComponent<BaseCombatAIComponent>() != nullptr) {
|
||||
const auto index = std::find(m_TargetsInPhantom.begin(), m_TargetsInPhantom.end(), otherEntity);
|
||||
|
||||
if (index != m_TargetsInPhantom.end()) return;
|
||||
|
||||
const auto valid = combat->IsEnemy(otherEntity);
|
||||
|
||||
if (!valid) return;
|
||||
|
||||
m_TargetsInPhantom.push_back(otherEntity);
|
||||
}
|
||||
}
|
||||
@@ -1624,18 +1651,23 @@ bool Entity::GetIsDead() const {
|
||||
|
||||
void Entity::AddLootItem(const Loot::Info& info) {
|
||||
if (!IsPlayer()) return;
|
||||
auto& droppedLoot = static_cast<Player*>(this)->GetDroppedLoot();
|
||||
|
||||
auto* characterComponent = GetComponent<CharacterComponent>();
|
||||
if (!characterComponent) return;
|
||||
|
||||
auto& droppedLoot = characterComponent->GetDroppedLoot();
|
||||
droppedLoot.insert(std::make_pair(info.id, info));
|
||||
}
|
||||
|
||||
void Entity::PickupItem(const LWOOBJID& objectID) {
|
||||
if (!IsPlayer()) return;
|
||||
InventoryComponent* inv = GetComponent<InventoryComponent>();
|
||||
if (!inv) return;
|
||||
auto* characterComponent = GetComponent<CharacterComponent>();
|
||||
if (!inv || !characterComponent) return;
|
||||
|
||||
CDObjectsTable* objectsTable = CDClientManager::Instance().GetTable<CDObjectsTable>();
|
||||
|
||||
auto& droppedLoot = static_cast<Player*>(this)->GetDroppedLoot();
|
||||
auto& droppedLoot = characterComponent->GetDroppedLoot();
|
||||
|
||||
for (const auto& p : droppedLoot) {
|
||||
if (p.first == objectID) {
|
||||
@@ -1671,22 +1703,28 @@ void Entity::PickupItem(const LWOOBJID& objectID) {
|
||||
|
||||
bool Entity::CanPickupCoins(uint64_t count) {
|
||||
if (!IsPlayer()) return false;
|
||||
auto* player = static_cast<Player*>(this);
|
||||
auto droppedCoins = player->GetDroppedCoins();
|
||||
|
||||
auto* characterComponent = GetComponent<CharacterComponent>();
|
||||
if (!characterComponent) return false;
|
||||
|
||||
auto droppedCoins = characterComponent->GetDroppedCoins();
|
||||
if (count > droppedCoins) {
|
||||
return false;
|
||||
} else {
|
||||
player->SetDroppedCoins(droppedCoins - count);
|
||||
characterComponent->SetDroppedCoins(droppedCoins - count);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void Entity::RegisterCoinDrop(uint64_t count) {
|
||||
if (!IsPlayer()) return;
|
||||
auto* player = static_cast<Player*>(this);
|
||||
auto droppedCoins = player->GetDroppedCoins();
|
||||
|
||||
auto* characterComponent = GetComponent<CharacterComponent>();
|
||||
if (!characterComponent) return;
|
||||
|
||||
auto droppedCoins = characterComponent->GetDroppedCoins();
|
||||
droppedCoins += count;
|
||||
player->SetDroppedCoins(droppedCoins);
|
||||
characterComponent->SetDroppedCoins(droppedCoins);
|
||||
}
|
||||
|
||||
void Entity::AddChild(Entity* child) {
|
||||
@@ -1851,7 +1889,7 @@ const NiPoint3& Entity::GetPosition() const {
|
||||
return vehicel->GetPosition();
|
||||
}
|
||||
|
||||
return NiPoint3::ZERO;
|
||||
return NiPoint3Constant::ZERO;
|
||||
}
|
||||
|
||||
const NiQuaternion& Entity::GetRotation() const {
|
||||
@@ -1879,7 +1917,7 @@ const NiQuaternion& Entity::GetRotation() const {
|
||||
return vehicel->GetRotation();
|
||||
}
|
||||
|
||||
return NiQuaternion::IDENTITY;
|
||||
return NiQuaternionConstant::IDENTITY;
|
||||
}
|
||||
|
||||
void Entity::SetPosition(const NiPoint3& position) {
|
||||
@@ -1980,25 +2018,21 @@ void Entity::SetNetworkId(const uint16_t id) {
|
||||
m_NetworkID = id;
|
||||
}
|
||||
|
||||
std::vector<LWOOBJID>& Entity::GetTargetsInPhantom() {
|
||||
std::vector<LWOOBJID> valid;
|
||||
|
||||
std::vector<LWOOBJID> Entity::GetTargetsInPhantom() {
|
||||
// Clean up invalid targets, like disconnected players
|
||||
for (auto i = 0u; i < m_TargetsInPhantom.size(); ++i) {
|
||||
const auto id = m_TargetsInPhantom.at(i);
|
||||
m_TargetsInPhantom.erase(std::remove_if(m_TargetsInPhantom.begin(), m_TargetsInPhantom.end(), [](const LWOOBJID id) {
|
||||
return !Game::entityManager->GetEntity(id);
|
||||
}), m_TargetsInPhantom.end());
|
||||
|
||||
auto* entity = Game::entityManager->GetEntity(id);
|
||||
std::vector<LWOOBJID> enemies;
|
||||
for (const auto id : m_TargetsInPhantom) {
|
||||
auto* combat = GetComponent<BaseCombatAIComponent>();
|
||||
if (!combat || !combat->IsEnemy(id)) continue;
|
||||
|
||||
if (entity == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
valid.push_back(id);
|
||||
enemies.push_back(id);
|
||||
}
|
||||
|
||||
m_TargetsInPhantom = valid;
|
||||
|
||||
return m_TargetsInPhantom;
|
||||
return enemies;
|
||||
}
|
||||
|
||||
void Entity::SendNetworkVar(const std::string& data, const SystemAddress& sysAddr) {
|
||||
@@ -2084,9 +2118,9 @@ void Entity::ProcessPositionUpdate(PositionUpdate& update) {
|
||||
havokVehiclePhysicsComponent->SetIsOnGround(update.onGround);
|
||||
havokVehiclePhysicsComponent->SetIsOnRail(update.onRail);
|
||||
havokVehiclePhysicsComponent->SetVelocity(update.velocity);
|
||||
havokVehiclePhysicsComponent->SetDirtyVelocity(update.velocity != NiPoint3::ZERO);
|
||||
havokVehiclePhysicsComponent->SetDirtyVelocity(update.velocity != NiPoint3Constant::ZERO);
|
||||
havokVehiclePhysicsComponent->SetAngularVelocity(update.angularVelocity);
|
||||
havokVehiclePhysicsComponent->SetDirtyAngularVelocity(update.angularVelocity != NiPoint3::ZERO);
|
||||
havokVehiclePhysicsComponent->SetDirtyAngularVelocity(update.angularVelocity != NiPoint3Constant::ZERO);
|
||||
havokVehiclePhysicsComponent->SetRemoteInputInfo(update.remoteInputInfo);
|
||||
} else {
|
||||
// Need to get the mount's controllable physics
|
||||
@@ -2097,17 +2131,17 @@ void Entity::ProcessPositionUpdate(PositionUpdate& update) {
|
||||
possessedControllablePhysicsComponent->SetIsOnGround(update.onGround);
|
||||
possessedControllablePhysicsComponent->SetIsOnRail(update.onRail);
|
||||
possessedControllablePhysicsComponent->SetVelocity(update.velocity);
|
||||
possessedControllablePhysicsComponent->SetDirtyVelocity(update.velocity != NiPoint3::ZERO);
|
||||
possessedControllablePhysicsComponent->SetDirtyVelocity(update.velocity != NiPoint3Constant::ZERO);
|
||||
possessedControllablePhysicsComponent->SetAngularVelocity(update.angularVelocity);
|
||||
possessedControllablePhysicsComponent->SetDirtyAngularVelocity(update.angularVelocity != NiPoint3::ZERO);
|
||||
possessedControllablePhysicsComponent->SetDirtyAngularVelocity(update.angularVelocity != NiPoint3Constant::ZERO);
|
||||
}
|
||||
Game::entityManager->SerializeEntity(possassableEntity);
|
||||
}
|
||||
}
|
||||
|
||||
if (!updateChar) {
|
||||
update.velocity = NiPoint3::ZERO;
|
||||
update.angularVelocity = NiPoint3::ZERO;
|
||||
update.velocity = NiPoint3Constant::ZERO;
|
||||
update.angularVelocity = NiPoint3Constant::ZERO;
|
||||
}
|
||||
|
||||
// Handle statistics
|
||||
@@ -2121,13 +2155,37 @@ void Entity::ProcessPositionUpdate(PositionUpdate& update) {
|
||||
controllablePhysicsComponent->SetIsOnGround(update.onGround);
|
||||
controllablePhysicsComponent->SetIsOnRail(update.onRail);
|
||||
controllablePhysicsComponent->SetVelocity(update.velocity);
|
||||
controllablePhysicsComponent->SetDirtyVelocity(update.velocity != NiPoint3::ZERO);
|
||||
controllablePhysicsComponent->SetDirtyVelocity(update.velocity != NiPoint3Constant::ZERO);
|
||||
controllablePhysicsComponent->SetAngularVelocity(update.angularVelocity);
|
||||
controllablePhysicsComponent->SetDirtyAngularVelocity(update.angularVelocity != NiPoint3::ZERO);
|
||||
controllablePhysicsComponent->SetDirtyAngularVelocity(update.angularVelocity != NiPoint3Constant::ZERO);
|
||||
|
||||
auto* player = static_cast<Player*>(this);
|
||||
player->SetGhostReferencePoint(update.position);
|
||||
Game::entityManager->QueueGhostUpdate(player->GetObjectID());
|
||||
auto* ghostComponent = GetComponent<GhostComponent>();
|
||||
if (ghostComponent) ghostComponent->SetGhostReferencePoint(update.position);
|
||||
Game::entityManager->QueueGhostUpdate(GetObjectID());
|
||||
|
||||
if (updateChar) Game::entityManager->SerializeEntity(this);
|
||||
}
|
||||
|
||||
const SystemAddress& Entity::GetSystemAddress() const {
|
||||
auto* characterComponent = GetComponent<CharacterComponent>();
|
||||
return characterComponent ? characterComponent->GetSystemAddress() : UNASSIGNED_SYSTEM_ADDRESS;
|
||||
}
|
||||
|
||||
const NiPoint3& Entity::GetRespawnPosition() const {
|
||||
auto* characterComponent = GetComponent<CharacterComponent>();
|
||||
return characterComponent ? characterComponent->GetRespawnPosition() : NiPoint3Constant::ZERO;
|
||||
}
|
||||
|
||||
const NiQuaternion& Entity::GetRespawnRotation() const {
|
||||
auto* characterComponent = GetComponent<CharacterComponent>();
|
||||
return characterComponent ? characterComponent->GetRespawnRotation() : NiQuaternionConstant::IDENTITY;
|
||||
}
|
||||
|
||||
void Entity::SetRespawnPos(const NiPoint3& position) {
|
||||
auto* characterComponent = GetComponent<CharacterComponent>();
|
||||
if (characterComponent) characterComponent->SetRespawnPos(position);
|
||||
}
|
||||
void Entity::SetRespawnRot(const NiQuaternion& rotation) {
|
||||
auto* characterComponent = GetComponent<CharacterComponent>();
|
||||
if (characterComponent) characterComponent->SetRespawnRot(rotation);
|
||||
}
|
||||
|
||||
@@ -47,10 +47,10 @@ namespace CppScripts {
|
||||
*/
|
||||
class Entity {
|
||||
public:
|
||||
explicit Entity(const LWOOBJID& objectID, EntityInfo info, Entity* parentEntity = nullptr);
|
||||
virtual ~Entity();
|
||||
explicit Entity(const LWOOBJID& objectID, EntityInfo info, User* parentUser = nullptr, Entity* parentEntity = nullptr);
|
||||
~Entity();
|
||||
|
||||
virtual void Initialize();
|
||||
void Initialize();
|
||||
|
||||
bool operator==(const Entity& other) const;
|
||||
bool operator!=(const Entity& other) const;
|
||||
@@ -104,9 +104,7 @@ public:
|
||||
|
||||
const NiQuaternion& GetRotation() const;
|
||||
|
||||
virtual User* GetParentUser() const;
|
||||
|
||||
virtual const SystemAddress& GetSystemAddress() const { return UNASSIGNED_SYSTEM_ADDRESS; };
|
||||
const SystemAddress& GetSystemAddress() const;
|
||||
|
||||
/**
|
||||
* Setters
|
||||
@@ -128,11 +126,9 @@ public:
|
||||
|
||||
void SetRotation(const NiQuaternion& rotation);
|
||||
|
||||
virtual void SetRespawnPos(const NiPoint3& position) {}
|
||||
void SetRespawnPos(const NiPoint3& position);
|
||||
|
||||
virtual void SetRespawnRot(const NiQuaternion& rotation) {}
|
||||
|
||||
virtual void SetSystemAddress(const SystemAddress& value) {};
|
||||
void SetRespawnRot(const NiQuaternion& rotation);
|
||||
|
||||
/**
|
||||
* Component management
|
||||
@@ -229,8 +225,8 @@ public:
|
||||
void TriggerEvent(eTriggerEventType event, Entity* optionalTarget = nullptr);
|
||||
void ScheduleDestructionAfterUpdate() { m_ShouldDestroyAfterUpdate = true; }
|
||||
|
||||
virtual const NiPoint3& GetRespawnPosition() const { return NiPoint3::ZERO; }
|
||||
virtual const NiQuaternion& GetRespawnRotation() const { return NiQuaternion::IDENTITY; }
|
||||
const NiPoint3& GetRespawnPosition() const;
|
||||
const NiQuaternion& GetRespawnRotation() const;
|
||||
|
||||
void Sleep();
|
||||
void Wake();
|
||||
@@ -293,7 +289,7 @@ public:
|
||||
/*
|
||||
* Collision
|
||||
*/
|
||||
std::vector<LWOOBJID>& GetTargetsInPhantom();
|
||||
std::vector<LWOOBJID> GetTargetsInPhantom();
|
||||
|
||||
Entity* GetScheduledKiller() { return m_ScheduleKiller; }
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include "GeneralUtils.h"
|
||||
#include "dServer.h"
|
||||
#include "Spawner.h"
|
||||
#include "Player.h"
|
||||
#include "SkillComponent.h"
|
||||
#include "SwitchComponent.h"
|
||||
#include "UserManager.h"
|
||||
@@ -23,6 +22,8 @@
|
||||
#include "eGameMasterLevel.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
#include "eReplicaPacketType.h"
|
||||
#include "PlayerManager.h"
|
||||
#include "GhostComponent.h"
|
||||
|
||||
// Configure which zones have ghosting disabled, mostly small worlds.
|
||||
std::vector<LWOMAPID> EntityManager::m_GhostingExcludedZones = {
|
||||
@@ -116,14 +117,7 @@ Entity* EntityManager::CreateEntity(EntityInfo info, User* user, Entity* parentE
|
||||
|
||||
info.id = id;
|
||||
|
||||
Entity* entity;
|
||||
|
||||
// Check if the entitty if a player, in case use the extended player entity class
|
||||
if (user != nullptr) {
|
||||
entity = new Player(id, info, user, parentEntity);
|
||||
} else {
|
||||
entity = new Entity(id, info, parentEntity);
|
||||
}
|
||||
Entity* entity = new Entity(id, info, user, parentEntity);
|
||||
|
||||
// Initialize the entity
|
||||
entity->Initialize();
|
||||
@@ -187,8 +181,9 @@ void EntityManager::SerializeEntities() {
|
||||
entity->WriteComponents(&stream, eReplicaPacketType::SERIALIZATION);
|
||||
|
||||
if (entity->GetIsGhostingCandidate()) {
|
||||
for (auto* player : Player::GetAllPlayers()) {
|
||||
if (player->IsObserved(toSerialize)) {
|
||||
for (auto* player : PlayerManager::GetAllPlayers()) {
|
||||
auto* ghostComponent = player->GetComponent<GhostComponent>();
|
||||
if (ghostComponent && ghostComponent->IsObserved(toSerialize)) {
|
||||
Game::server->Send(&stream, player->GetSystemAddress(), false);
|
||||
}
|
||||
}
|
||||
@@ -376,11 +371,12 @@ void EntityManager::ConstructEntity(Entity* entity, const SystemAddress& sysAddr
|
||||
if (skipChecks) {
|
||||
Game::server->Send(&stream, UNASSIGNED_SYSTEM_ADDRESS, true);
|
||||
} else {
|
||||
for (auto* player : Player::GetAllPlayers()) {
|
||||
for (auto* player : PlayerManager::GetAllPlayers()) {
|
||||
if (player->GetPlayerReadyForUpdates()) {
|
||||
Game::server->Send(&stream, player->GetSystemAddress(), false);
|
||||
} else {
|
||||
player->AddLimboConstruction(entity->GetObjectID());
|
||||
auto* ghostComponent = player->GetComponent<GhostComponent>();
|
||||
if (ghostComponent) ghostComponent->AddLimboConstruction(entity->GetObjectID());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -405,7 +401,7 @@ void EntityManager::ConstructAllEntities(const SystemAddress& sysAddr) {
|
||||
}
|
||||
}
|
||||
|
||||
UpdateGhosting(Player::GetPlayer(sysAddr));
|
||||
UpdateGhosting(PlayerManager::GetPlayer(sysAddr));
|
||||
}
|
||||
|
||||
void EntityManager::DestructEntity(Entity* entity, const SystemAddress& sysAddr) {
|
||||
@@ -418,9 +414,10 @@ void EntityManager::DestructEntity(Entity* entity, const SystemAddress& sysAddr)
|
||||
|
||||
Game::server->Send(&stream, sysAddr, sysAddr == UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
||||
for (auto* player : Player::GetAllPlayers()) {
|
||||
for (auto* player : PlayerManager::GetAllPlayers()) {
|
||||
if (!player->GetPlayerReadyForUpdates()) {
|
||||
player->RemoveLimboConstruction(entity->GetObjectID());
|
||||
auto* ghostComponent = player->GetComponent<GhostComponent>();
|
||||
if (ghostComponent) ghostComponent->RemoveLimboConstruction(entity->GetObjectID());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -465,7 +462,7 @@ void EntityManager::QueueGhostUpdate(LWOOBJID playerID) {
|
||||
|
||||
void EntityManager::UpdateGhosting() {
|
||||
for (const auto playerID : m_PlayersToUpdateGhosting) {
|
||||
auto* player = Player::GetPlayer(playerID);
|
||||
auto* player = PlayerManager::GetPlayer(playerID);
|
||||
|
||||
if (player == nullptr) {
|
||||
continue;
|
||||
@@ -477,19 +474,20 @@ void EntityManager::UpdateGhosting() {
|
||||
m_PlayersToUpdateGhosting.clear();
|
||||
}
|
||||
|
||||
void EntityManager::UpdateGhosting(Player* player) {
|
||||
void EntityManager::UpdateGhosting(Entity* player) {
|
||||
if (player == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* missionComponent = player->GetComponent<MissionComponent>();
|
||||
auto* ghostComponent = player->GetComponent<GhostComponent>();
|
||||
|
||||
if (missionComponent == nullptr) {
|
||||
if (missionComponent == nullptr || !ghostComponent) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& referencePoint = player->GetGhostReferencePoint();
|
||||
const auto isOverride = player->GetGhostOverride();
|
||||
const auto& referencePoint = ghostComponent->GetGhostReferencePoint();
|
||||
const auto isOverride = ghostComponent->GetGhostOverride();
|
||||
|
||||
for (auto* entity : m_EntitiesToGhost) {
|
||||
const auto isAudioEmitter = entity->GetLOT() == 6368;
|
||||
@@ -498,7 +496,7 @@ void EntityManager::UpdateGhosting(Player* player) {
|
||||
|
||||
const int32_t id = entity->GetObjectID();
|
||||
|
||||
const auto observed = player->IsObserved(id);
|
||||
const auto observed = ghostComponent->IsObserved(id);
|
||||
|
||||
const auto distance = NiPoint3::DistanceSquared(referencePoint, entityPoint);
|
||||
|
||||
@@ -510,7 +508,7 @@ void EntityManager::UpdateGhosting(Player* player) {
|
||||
}
|
||||
|
||||
if (observed && distance > ghostingDistanceMax && !isOverride) {
|
||||
player->GhostEntity(id);
|
||||
ghostComponent->GhostEntity(id);
|
||||
|
||||
DestructEntity(entity, player->GetSystemAddress());
|
||||
|
||||
@@ -527,7 +525,7 @@ void EntityManager::UpdateGhosting(Player* player) {
|
||||
}
|
||||
}
|
||||
|
||||
player->ObserveEntity(id);
|
||||
ghostComponent->ObserveEntity(id);
|
||||
|
||||
ConstructEntity(entity, player->GetSystemAddress());
|
||||
|
||||
@@ -548,23 +546,26 @@ void EntityManager::CheckGhosting(Entity* entity) {
|
||||
|
||||
const auto isAudioEmitter = entity->GetLOT() == 6368;
|
||||
|
||||
for (auto* player : Player::GetAllPlayers()) {
|
||||
const auto& entityPoint = player->GetGhostReferencePoint();
|
||||
for (auto* player : PlayerManager::GetAllPlayers()) {
|
||||
auto* ghostComponent = player->GetComponent<GhostComponent>();
|
||||
if (!ghostComponent) continue;
|
||||
|
||||
const auto& entityPoint = ghostComponent->GetGhostReferencePoint();
|
||||
|
||||
const int32_t id = entity->GetObjectID();
|
||||
|
||||
const auto observed = player->IsObserved(id);
|
||||
const auto observed = ghostComponent->IsObserved(id);
|
||||
|
||||
const auto distance = NiPoint3::DistanceSquared(referencePoint, entityPoint);
|
||||
|
||||
if (observed && distance > ghostingDistanceMax) {
|
||||
player->GhostEntity(id);
|
||||
ghostComponent->GhostEntity(id);
|
||||
|
||||
DestructEntity(entity, player->GetSystemAddress());
|
||||
|
||||
entity->SetObservers(entity->GetObservers() - 1);
|
||||
} else if (!observed && ghostingDistanceMin > distance) {
|
||||
player->ObserveEntity(id);
|
||||
ghostComponent->ObserveEntity(id);
|
||||
|
||||
ConstructEntity(entity, player->GetSystemAddress());
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
float GetGhostDistanceMin() const;
|
||||
void QueueGhostUpdate(LWOOBJID playerID);
|
||||
void UpdateGhosting();
|
||||
void UpdateGhosting(Player* player);
|
||||
void UpdateGhosting(Entity* player);
|
||||
void CheckGhosting(Entity* entity);
|
||||
Entity* GetGhostCandidate(int32_t id);
|
||||
bool GetGhostingEnabled() const;
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include "Singleton.h"
|
||||
#include "dCommonVars.h"
|
||||
#include "LDFFormat.h"
|
||||
|
||||
|
||||
193
dGame/Player.cpp
193
dGame/Player.cpp
@@ -1,193 +0,0 @@
|
||||
#include "Player.h"
|
||||
|
||||
#include <ctime>
|
||||
|
||||
#include "Character.h"
|
||||
#include "UserManager.h"
|
||||
#include "EntityManager.h"
|
||||
#include "Game.h"
|
||||
#include "Logger.h"
|
||||
#include "dZoneManager.h"
|
||||
#include "User.h"
|
||||
#include "CppScripts.h"
|
||||
#include "Loot.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
namespace {
|
||||
std::vector<Player*> m_Players;
|
||||
};
|
||||
|
||||
const std::vector<Player*>& Player::GetAllPlayers() {
|
||||
return m_Players;
|
||||
}
|
||||
|
||||
void Player::SetGhostReferencePoint(const NiPoint3& value) {
|
||||
m_GhostReferencePoint = value;
|
||||
}
|
||||
|
||||
void Player::SetGhostOverridePoint(const NiPoint3& value) {
|
||||
m_GhostOverridePoint = value;
|
||||
}
|
||||
|
||||
void Player::SetRespawnPos(const NiPoint3& position) {
|
||||
if (!m_Character) return;
|
||||
|
||||
m_respawnPos = position;
|
||||
|
||||
m_Character->SetRespawnPoint(Game::zoneManager->GetZone()->GetWorldID(), position);
|
||||
|
||||
}
|
||||
|
||||
void Player::SetRespawnRot(const NiQuaternion& rotation) {
|
||||
m_respawnRot = rotation;
|
||||
}
|
||||
|
||||
void Player::SetSystemAddress(const SystemAddress& value) {
|
||||
m_SystemAddress = value;
|
||||
}
|
||||
|
||||
Player::Player(const LWOOBJID& objectID, const EntityInfo info, User* user, Entity* parentEntity) : Entity(objectID, info, parentEntity) {
|
||||
m_ParentUser = user;
|
||||
m_Character = m_ParentUser->GetLastUsedChar();
|
||||
m_ParentUser->SetLoggedInChar(objectID);
|
||||
m_GMLevel = m_Character->GetGMLevel();
|
||||
m_SystemAddress = m_ParentUser->GetSystemAddress();
|
||||
m_DroppedCoins = 0;
|
||||
|
||||
m_GhostReferencePoint = NiPoint3::ZERO;
|
||||
m_GhostOverridePoint = NiPoint3::ZERO;
|
||||
m_GhostOverride = false;
|
||||
|
||||
int32_t initialObservedEntitiesCapacity = 256;
|
||||
m_ObservedEntities.resize(initialObservedEntitiesCapacity);
|
||||
|
||||
m_Character->SetEntity(this);
|
||||
|
||||
const auto& iter = std::find(m_Players.begin(), m_Players.end(), this);
|
||||
|
||||
if (iter == m_Players.end()) {
|
||||
m_Players.push_back(this);
|
||||
}
|
||||
}
|
||||
|
||||
void Player::AddLimboConstruction(LWOOBJID objectId) {
|
||||
const auto iter = std::find(m_LimboConstructions.begin(), m_LimboConstructions.end(), objectId);
|
||||
if (iter == m_LimboConstructions.end()) {
|
||||
m_LimboConstructions.push_back(objectId);
|
||||
}
|
||||
}
|
||||
|
||||
void Player::RemoveLimboConstruction(LWOOBJID objectId) {
|
||||
const auto iter = std::find(m_LimboConstructions.begin(), m_LimboConstructions.end(), objectId);
|
||||
if (iter != m_LimboConstructions.end()) {
|
||||
m_LimboConstructions.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
void Player::ConstructLimboEntities() {
|
||||
for (const auto& objectId : m_LimboConstructions) {
|
||||
auto* entity = Game::entityManager->GetEntity(objectId);
|
||||
if (!entity) continue;
|
||||
|
||||
Game::entityManager->ConstructEntity(entity, m_SystemAddress);
|
||||
}
|
||||
|
||||
m_LimboConstructions.clear();
|
||||
}
|
||||
|
||||
void Player::ObserveEntity(int32_t id) {
|
||||
for (auto& observedEntity : m_ObservedEntities) {
|
||||
if (observedEntity == 0 || observedEntity == id) {
|
||||
observedEntity = id;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_ObservedEntities.reserve(m_ObservedEntities.size() + 1);
|
||||
|
||||
m_ObservedEntities.push_back(id);
|
||||
}
|
||||
|
||||
bool Player::IsObserved(int32_t id) {
|
||||
return std::find(m_ObservedEntities.begin(), m_ObservedEntities.end(), id) != m_ObservedEntities.end();
|
||||
}
|
||||
|
||||
void Player::GhostEntity(int32_t id) {
|
||||
for (auto& observedEntity : m_ObservedEntities) {
|
||||
if (observedEntity == id) {
|
||||
observedEntity = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Player* Player::GetPlayer(const SystemAddress& sysAddr) {
|
||||
auto* entity = UserManager::Instance()->GetUser(sysAddr)->GetLastUsedChar()->GetEntity();
|
||||
|
||||
return static_cast<Player*>(entity);
|
||||
}
|
||||
|
||||
Player* Player::GetPlayer(const std::string& name) {
|
||||
const auto characters = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::CHARACTER);
|
||||
|
||||
Player* player = nullptr;
|
||||
for (auto* character : characters) {
|
||||
if (!character->IsPlayer()) continue;
|
||||
|
||||
if (GeneralUtils::CaseInsensitiveStringCompare(name, character->GetCharacter()->GetName())) {
|
||||
player = dynamic_cast<Player*>(character);
|
||||
}
|
||||
}
|
||||
|
||||
return player;
|
||||
}
|
||||
|
||||
Player* Player::GetPlayer(LWOOBJID playerID) {
|
||||
Player* playerToReturn = nullptr;
|
||||
for (auto* player : m_Players) {
|
||||
if (player->GetObjectID() == playerID) {
|
||||
playerToReturn = player;
|
||||
}
|
||||
}
|
||||
|
||||
return playerToReturn;
|
||||
}
|
||||
|
||||
Player::~Player() {
|
||||
LOG("Deleted player");
|
||||
|
||||
for (auto& observedEntity : m_ObservedEntities) {
|
||||
if (observedEntity == 0) continue;
|
||||
|
||||
auto* entity = Game::entityManager->GetGhostCandidate(observedEntity);
|
||||
if (!entity) continue;
|
||||
|
||||
entity->SetObservers(entity->GetObservers() - 1);
|
||||
}
|
||||
|
||||
m_LimboConstructions.clear();
|
||||
|
||||
const auto iter = std::find(m_Players.begin(), m_Players.end(), this);
|
||||
|
||||
if (iter == m_Players.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsPlayer()) {
|
||||
Entity* zoneControl = Game::entityManager->GetZoneControlEntity();
|
||||
for (CppScripts::Script* script : CppScripts::GetEntityScripts(zoneControl)) {
|
||||
script->OnPlayerExit(zoneControl, this);
|
||||
}
|
||||
|
||||
std::vector<Entity*> scriptedActs = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::SCRIPTED_ACTIVITY);
|
||||
for (Entity* scriptEntity : scriptedActs) {
|
||||
if (scriptEntity->GetObjectID() != zoneControl->GetObjectID()) { // Don't want to trigger twice on instance worlds
|
||||
for (CppScripts::Script* script : CppScripts::GetEntityScripts(scriptEntity)) {
|
||||
script->OnPlayerExit(scriptEntity, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_Players.erase(iter);
|
||||
}
|
||||
110
dGame/Player.h
110
dGame/Player.h
@@ -1,110 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Entity.h"
|
||||
|
||||
/**
|
||||
* Extended Entity for player data and behavior.
|
||||
*
|
||||
* Contains properties only a player entity would require, like associated SystemAddress and User.
|
||||
*
|
||||
* Keeps track of which entities are observed by this user for ghosting.
|
||||
*/
|
||||
class Player final : public Entity
|
||||
{
|
||||
public:
|
||||
explicit Player(const LWOOBJID& objectID, EntityInfo info, User* user, Entity* parentEntity = nullptr);
|
||||
|
||||
/**
|
||||
* Getters
|
||||
*/
|
||||
|
||||
User* GetParentUser() const override { return m_ParentUser; };
|
||||
|
||||
const SystemAddress& GetSystemAddress() const override { return m_SystemAddress; };
|
||||
|
||||
const NiPoint3& GetRespawnPosition() const override { return m_respawnPos; };
|
||||
|
||||
const NiQuaternion& GetRespawnRotation() const override { return m_respawnRot; };
|
||||
|
||||
const NiPoint3& GetGhostReferencePoint() const { return m_GhostOverride ? m_GhostOverridePoint : m_GhostReferencePoint; };
|
||||
|
||||
const NiPoint3& GetOriginGhostReferencePoint() const { return m_GhostReferencePoint; };
|
||||
|
||||
const NiPoint3& GetGhostOverridePoint() const { return m_GhostOverridePoint; };
|
||||
|
||||
bool GetGhostOverride() const { return m_GhostOverride; };
|
||||
|
||||
std::map<LWOOBJID, Loot::Info>& GetDroppedLoot() { return m_DroppedLoot; };
|
||||
|
||||
uint64_t GetDroppedCoins() const { return m_DroppedCoins; };
|
||||
|
||||
/**
|
||||
* Setters
|
||||
*/
|
||||
|
||||
void SetGhostOverride(bool value) { m_GhostOverride = value; };
|
||||
|
||||
void SetDroppedCoins(const uint64_t value) { m_DroppedCoins = value; };
|
||||
|
||||
void SetSystemAddress(const SystemAddress& value) override;
|
||||
|
||||
void SetRespawnPos(const NiPoint3& position) override;
|
||||
|
||||
void SetRespawnRot(const NiQuaternion& rotation) override;
|
||||
|
||||
void SetGhostReferencePoint(const NiPoint3& value);
|
||||
|
||||
void SetGhostOverridePoint(const NiPoint3& value);
|
||||
|
||||
/**
|
||||
* Ghosting
|
||||
*/
|
||||
|
||||
void AddLimboConstruction(LWOOBJID objectId);
|
||||
|
||||
void RemoveLimboConstruction(LWOOBJID objectId);
|
||||
|
||||
void ConstructLimboEntities();
|
||||
|
||||
void ObserveEntity(const int32_t id);
|
||||
|
||||
bool IsObserved(const int32_t id);
|
||||
|
||||
void GhostEntity(const int32_t id);
|
||||
|
||||
/**
|
||||
* Static methods
|
||||
*/
|
||||
|
||||
static Player* GetPlayer(const SystemAddress& sysAddr);
|
||||
|
||||
static Player* GetPlayer(const std::string& name);
|
||||
|
||||
static Player* GetPlayer(LWOOBJID playerID);
|
||||
|
||||
static const std::vector<Player*>& GetAllPlayers();
|
||||
|
||||
~Player() override;
|
||||
private:
|
||||
SystemAddress m_SystemAddress;
|
||||
|
||||
NiPoint3 m_respawnPos;
|
||||
|
||||
NiQuaternion m_respawnRot;
|
||||
|
||||
User* m_ParentUser;
|
||||
|
||||
NiPoint3 m_GhostReferencePoint;
|
||||
|
||||
NiPoint3 m_GhostOverridePoint;
|
||||
|
||||
bool m_GhostOverride;
|
||||
|
||||
std::vector<int32_t> m_ObservedEntities;
|
||||
|
||||
std::vector<LWOOBJID> m_LimboConstructions;
|
||||
|
||||
std::map<LWOOBJID, Loot::Info> m_DroppedLoot;
|
||||
|
||||
uint64_t m_DroppedCoins;
|
||||
};
|
||||
67
dGame/PlayerManager.cpp
Normal file
67
dGame/PlayerManager.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#include "PlayerManager.h"
|
||||
|
||||
#include "Character.h"
|
||||
#include "User.h"
|
||||
#include "UserManager.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
namespace {
|
||||
std::vector<Entity*> m_Players;
|
||||
};
|
||||
|
||||
const std::vector<Entity*>& PlayerManager::GetAllPlayers() {
|
||||
return m_Players;
|
||||
}
|
||||
|
||||
void PlayerManager::AddPlayer(Entity* player) {
|
||||
const auto& iter = std::find(m_Players.begin(), m_Players.end(), player);
|
||||
|
||||
if (iter == m_Players.end()) {
|
||||
m_Players.push_back(player);
|
||||
}
|
||||
}
|
||||
|
||||
bool PlayerManager::RemovePlayer(Entity* player) {
|
||||
const auto iter = std::find(m_Players.begin(), m_Players.end(), player);
|
||||
|
||||
const bool toReturn = iter != m_Players.end();
|
||||
if (toReturn) {
|
||||
m_Players.erase(iter);
|
||||
}
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
Entity* PlayerManager::GetPlayer(const SystemAddress& sysAddr) {
|
||||
auto* entity = UserManager::Instance()->GetUser(sysAddr)->GetLastUsedChar()->GetEntity();
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
Entity* PlayerManager::GetPlayer(const std::string& name) {
|
||||
const auto characters = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::CHARACTER);
|
||||
|
||||
Entity* player = nullptr;
|
||||
for (auto* character : characters) {
|
||||
if (!character->IsPlayer()) continue;
|
||||
|
||||
if (GeneralUtils::CaseInsensitiveStringCompare(name, character->GetCharacter()->GetName())) {
|
||||
player = character;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return player;
|
||||
}
|
||||
|
||||
Entity* PlayerManager::GetPlayer(LWOOBJID playerID) {
|
||||
Entity* playerToReturn = nullptr;
|
||||
for (auto* player : m_Players) {
|
||||
if (player->GetObjectID() == playerID) {
|
||||
playerToReturn = player;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return playerToReturn;
|
||||
}
|
||||
25
dGame/PlayerManager.h
Normal file
25
dGame/PlayerManager.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef __PLAYERMANAGER__H__
|
||||
#define __PLAYERMANAGER__H__
|
||||
|
||||
#include "dCommonVars.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
class Entity;
|
||||
struct SystemAddress;
|
||||
|
||||
namespace PlayerManager {
|
||||
void AddPlayer(Entity* player);
|
||||
|
||||
bool RemovePlayer(Entity* player);
|
||||
|
||||
Entity* GetPlayer(const SystemAddress& sysAddr);
|
||||
|
||||
Entity* GetPlayer(const std::string& name);
|
||||
|
||||
Entity* GetPlayer(LWOOBJID playerID);
|
||||
|
||||
const std::vector<Entity*>& GetAllPlayers();
|
||||
};
|
||||
|
||||
#endif //!__PLAYERMANAGER__H__
|
||||
@@ -451,7 +451,7 @@ void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet)
|
||||
"User %i tried to rename a character that it does not own!",
|
||||
u->GetAccountID());
|
||||
|
||||
std::find_if(u->GetCharacters().begin(), u->GetCharacters().end(), [&](Character* c) {
|
||||
auto unusedItr = std::find_if(u->GetCharacters().begin(), u->GetCharacters().end(), [&](Character* c) {
|
||||
if (c->GetID() == charID) {
|
||||
character = c;
|
||||
return true;
|
||||
|
||||
@@ -33,7 +33,7 @@ void ProjectileAttackBehavior::Handle(BehaviorContext* context, RakNet::BitStrea
|
||||
}
|
||||
|
||||
if (m_useMouseposit && !branch.isSync) {
|
||||
NiPoint3 targetPosition = NiPoint3::ZERO;
|
||||
NiPoint3 targetPosition = NiPoint3Constant::ZERO;
|
||||
if (!bitStream->Read(targetPosition)) {
|
||||
LOG("Unable to read targetPosition from bitStream, aborting Handle! %i", bitStream->GetNumberOfUnreadBits());
|
||||
return;
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include "WorldPackets.h"
|
||||
#include "EntityManager.h"
|
||||
#include "ChatPackets.h"
|
||||
#include "Player.h"
|
||||
#include "BitStreamUtils.h"
|
||||
#include "dServer.h"
|
||||
#include "GeneralUtils.h"
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "Metrics.hpp"
|
||||
#include "CDComponentsRegistryTable.h"
|
||||
#include "CDPhysicsComponentTable.h"
|
||||
#include "dNavMesh.h"
|
||||
|
||||
BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id): Component(parent) {
|
||||
m_Target = LWOOBJID_EMPTY;
|
||||
@@ -128,17 +129,17 @@ BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id):
|
||||
m_dpEntity->SetPosition(m_Parent->GetPosition());
|
||||
m_dpEntityEnemy->SetPosition(m_Parent->GetPosition());
|
||||
|
||||
dpWorld::Instance().AddEntity(m_dpEntity);
|
||||
dpWorld::Instance().AddEntity(m_dpEntityEnemy);
|
||||
dpWorld::AddEntity(m_dpEntity);
|
||||
dpWorld::AddEntity(m_dpEntityEnemy);
|
||||
|
||||
}
|
||||
|
||||
BaseCombatAIComponent::~BaseCombatAIComponent() {
|
||||
if (m_dpEntity)
|
||||
dpWorld::Instance().RemoveEntity(m_dpEntity);
|
||||
dpWorld::RemoveEntity(m_dpEntity);
|
||||
|
||||
if (m_dpEntityEnemy)
|
||||
dpWorld::Instance().RemoveEntity(m_dpEntityEnemy);
|
||||
dpWorld::RemoveEntity(m_dpEntityEnemy);
|
||||
}
|
||||
|
||||
void BaseCombatAIComponent::Update(const float deltaTime) {
|
||||
@@ -184,7 +185,7 @@ void BaseCombatAIComponent::Update(const float deltaTime) {
|
||||
bool stunnedThisFrame = m_Stunned;
|
||||
CalculateCombat(deltaTime); // Putting this here for now
|
||||
|
||||
if (m_StartPosition == NiPoint3::ZERO) {
|
||||
if (m_StartPosition == NiPoint3Constant::ZERO) {
|
||||
m_StartPosition = m_Parent->GetPosition();
|
||||
}
|
||||
|
||||
@@ -653,8 +654,8 @@ void BaseCombatAIComponent::Wander() {
|
||||
|
||||
auto destination = m_StartPosition + delta;
|
||||
|
||||
if (dpWorld::Instance().IsLoaded()) {
|
||||
destination.y = dpWorld::Instance().GetNavMesh()->GetHeightAtPoint(destination);
|
||||
if (dpWorld::IsLoaded()) {
|
||||
destination.y = dpWorld::GetNavMesh()->GetHeightAtPoint(destination);
|
||||
}
|
||||
|
||||
if (Vector3::DistanceSquared(destination, m_MovementAI->GetParent()->GetPosition()) < 2 * 2) {
|
||||
|
||||
@@ -45,9 +45,9 @@ struct AiSkillEntry
|
||||
/**
|
||||
* Handles the AI of entities, making them wander, tether and attack their enemies
|
||||
*/
|
||||
class BaseCombatAIComponent : public Component {
|
||||
class BaseCombatAIComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::BASE_COMBAT_AI;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::BASE_COMBAT_AI;
|
||||
|
||||
BaseCombatAIComponent(Entity* parentEntity, uint32_t id);
|
||||
~BaseCombatAIComponent() override;
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
/**
|
||||
* Attached to bouncer entities, allowing other entities to bounce off of it
|
||||
*/
|
||||
class BouncerComponent : public Component {
|
||||
class BouncerComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::BOUNCER;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::BOUNCER;
|
||||
|
||||
BouncerComponent(Entity* parentEntity);
|
||||
~BouncerComponent() override;
|
||||
|
||||
@@ -47,9 +47,9 @@ struct Buff {
|
||||
/**
|
||||
* Allows for the application of buffs to the parent entity, altering health, armor and imagination.
|
||||
*/
|
||||
class BuffComponent : public Component {
|
||||
class BuffComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::BUFF;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::BUFF;
|
||||
|
||||
explicit BuffComponent(Entity* parent);
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ void BuildBorderComponent::OnUse(Entity* originator) {
|
||||
4,
|
||||
0,
|
||||
-1,
|
||||
NiPoint3::ZERO,
|
||||
NiPoint3Constant::ZERO,
|
||||
0
|
||||
);
|
||||
} else {
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
/**
|
||||
* Component for the build border, allowing the user to start building when interacting with it
|
||||
*/
|
||||
class BuildBorderComponent : public Component {
|
||||
class BuildBorderComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::BUILD_BORDER;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::BUILD_BORDER;
|
||||
|
||||
BuildBorderComponent(Entity* parent);
|
||||
~BuildBorderComponent() override;
|
||||
|
||||
@@ -27,7 +27,6 @@ set(DGAME_DCOMPONENTS_SOURCES
|
||||
"PlayerForcedMovementComponent.cpp"
|
||||
"PossessableComponent.cpp"
|
||||
"PossessorComponent.cpp"
|
||||
"PropertyComponent.cpp"
|
||||
"PropertyEntranceComponent.cpp"
|
||||
"PropertyManagementComponent.cpp"
|
||||
"PropertyVendorComponent.cpp"
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "WorldPackets.h"
|
||||
#include <ctime>
|
||||
|
||||
CharacterComponent::CharacterComponent(Entity* parent, Character* character) : Component(parent) {
|
||||
CharacterComponent::CharacterComponent(Entity* parent, Character* character, const SystemAddress& systemAddress) : Component(parent) {
|
||||
m_Character = character;
|
||||
|
||||
m_IsRacing = false;
|
||||
@@ -46,6 +46,7 @@ CharacterComponent::CharacterComponent(Entity* parent, Character* character) : C
|
||||
m_CurrentActivity = eGameActivity::NONE;
|
||||
m_CountryCode = 0;
|
||||
m_LastUpdateTimestamp = std::time(nullptr);
|
||||
m_SystemAddress = systemAddress;
|
||||
}
|
||||
|
||||
bool CharacterComponent::LandingAnimDisabled(int zoneID) {
|
||||
@@ -762,8 +763,8 @@ void CharacterComponent::UpdateClientMinimap(bool showFaction, std::string ventu
|
||||
}
|
||||
|
||||
void CharacterComponent::AwardClaimCodes() {
|
||||
if (!m_Parent) return;
|
||||
auto* user = m_Parent->GetParentUser();
|
||||
if (!m_Parent || !m_Parent->GetCharacter()) return;
|
||||
auto* user = m_Parent->GetCharacter()->GetParentUser();
|
||||
if (!user) return;
|
||||
|
||||
auto rewardCodes = Database::Get()->GetRewardCodesByAccountID(user->GetAccountID());
|
||||
@@ -817,3 +818,20 @@ void CharacterComponent::SendToZone(LWOMAPID zoneId, LWOCLONEID cloneId) const {
|
||||
Game::entityManager->DestructEntity(entity);
|
||||
});
|
||||
}
|
||||
|
||||
const SystemAddress& CharacterComponent::GetSystemAddress() const {
|
||||
return m_SystemAddress;
|
||||
}
|
||||
|
||||
void CharacterComponent::SetRespawnPos(const NiPoint3& position) {
|
||||
if (!m_Character) return;
|
||||
|
||||
m_respawnPos = position;
|
||||
|
||||
m_Character->SetRespawnPoint(Game::zoneManager->GetZone()->GetWorldID(), position);
|
||||
|
||||
}
|
||||
|
||||
void CharacterComponent::SetRespawnRot(const NiQuaternion& rotation) {
|
||||
m_respawnRot = rotation;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "tinyxml2.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
#include <array>
|
||||
#include "Loot.h"
|
||||
|
||||
enum class eGameActivity : uint32_t;
|
||||
|
||||
@@ -61,11 +62,11 @@ enum StatisticID {
|
||||
/**
|
||||
* Represents a character, including their rockets and stats
|
||||
*/
|
||||
class CharacterComponent : public Component {
|
||||
class CharacterComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::CHARACTER;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::CHARACTER;
|
||||
|
||||
CharacterComponent(Entity* parent, Character* character);
|
||||
CharacterComponent(Entity* parent, Character* character, const SystemAddress& systemAddress);
|
||||
~CharacterComponent() override;
|
||||
|
||||
void LoadFromXml(tinyxml2::XMLDocument* doc) override;
|
||||
@@ -289,6 +290,22 @@ public:
|
||||
*/
|
||||
void SendToZone(LWOMAPID zoneId, LWOCLONEID cloneId = 0) const;
|
||||
|
||||
const SystemAddress& GetSystemAddress() const;
|
||||
|
||||
const NiPoint3& GetRespawnPosition() const { return m_respawnPos; };
|
||||
|
||||
void SetRespawnPos(const NiPoint3& position);
|
||||
|
||||
const NiQuaternion& GetRespawnRotation() const { return m_respawnRot; };
|
||||
|
||||
void SetRespawnRot(const NiQuaternion& rotation);
|
||||
|
||||
std::map<LWOOBJID, Loot::Info>& GetDroppedLoot() { return m_DroppedLoot; };
|
||||
|
||||
uint64_t GetDroppedCoins() const { return m_DroppedCoins; };
|
||||
|
||||
void SetDroppedCoins(const uint64_t value) { m_DroppedCoins = value; };
|
||||
|
||||
/**
|
||||
* Character info regarding this character, including clothing styles, etc.
|
||||
*/
|
||||
@@ -579,6 +596,16 @@ private:
|
||||
std::array<uint64_t, 4> m_ClaimCodes{};
|
||||
|
||||
void AwardClaimCodes();
|
||||
|
||||
SystemAddress m_SystemAddress;
|
||||
|
||||
NiPoint3 m_respawnPos;
|
||||
|
||||
NiQuaternion m_respawnRot;
|
||||
|
||||
std::map<LWOOBJID, Loot::Info> m_DroppedLoot;
|
||||
|
||||
uint64_t m_DroppedCoins = 0;
|
||||
};
|
||||
|
||||
#endif // CHARACTERCOMPONENT_H
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
class CollectibleComponent : public Component {
|
||||
class CollectibleComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::COLLECTIBLE;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::COLLECTIBLE;
|
||||
CollectibleComponent(Entity* parentEntity, int32_t collectibleId) : Component(parentEntity), m_CollectibleId(collectibleId) {}
|
||||
|
||||
int16_t GetCollectibleId() const { return m_CollectibleId; }
|
||||
|
||||
@@ -7,8 +7,7 @@ class Entity;
|
||||
/**
|
||||
* Component base class, provides methods for game loop updates, usage events and loading and saving to XML.
|
||||
*/
|
||||
class Component
|
||||
{
|
||||
class Component {
|
||||
public:
|
||||
Component(Entity* parent);
|
||||
virtual ~Component();
|
||||
|
||||
@@ -57,13 +57,13 @@ ControllablePhysicsComponent::ControllablePhysicsComponent(Entity* entity) : Phy
|
||||
float radius = 1.5f;
|
||||
m_dpEntity = new dpEntity(m_Parent->GetObjectID(), radius, false);
|
||||
m_dpEntity->SetCollisionGroup(COLLISION_GROUP_DYNAMIC | COLLISION_GROUP_FRIENDLY);
|
||||
dpWorld::Instance().AddEntity(m_dpEntity);
|
||||
dpWorld::AddEntity(m_dpEntity);
|
||||
}
|
||||
}
|
||||
|
||||
ControllablePhysicsComponent::~ControllablePhysicsComponent() {
|
||||
if (m_dpEntity) {
|
||||
dpWorld::Instance().RemoveEntity(m_dpEntity);
|
||||
dpWorld::RemoveEntity(m_dpEntity);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ enum class eStateChangeType : uint32_t;
|
||||
*/
|
||||
class ControllablePhysicsComponent : public PhysicsComponent {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::CONTROLLABLE_PHYSICS;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::CONTROLLABLE_PHYSICS;
|
||||
|
||||
ControllablePhysicsComponent(Entity* entity);
|
||||
~ControllablePhysicsComponent() override;
|
||||
|
||||
@@ -251,13 +251,14 @@ void DestroyableComponent::SetMaxHealth(float value, bool playAnim) {
|
||||
|
||||
if (playAnim) {
|
||||
// Now update the player bar
|
||||
if (!m_Parent->GetParentUser()) return;
|
||||
auto* characterComponent = m_Parent->GetComponent<CharacterComponent>();
|
||||
if (!characterComponent) return;
|
||||
|
||||
AMFArrayValue args;
|
||||
args.Insert("amount", std::to_string(difference));
|
||||
args.Insert("type", "health");
|
||||
|
||||
GameMessages::SendUIMessageServerToSingleClient(m_Parent, m_Parent->GetParentUser()->GetSystemAddress(), "MaxPlayerBarUpdate", args);
|
||||
GameMessages::SendUIMessageServerToSingleClient(m_Parent, characterComponent->GetSystemAddress(), "MaxPlayerBarUpdate", args);
|
||||
}
|
||||
|
||||
Game::entityManager->SerializeEntity(m_Parent);
|
||||
@@ -292,13 +293,14 @@ void DestroyableComponent::SetMaxArmor(float value, bool playAnim) {
|
||||
|
||||
if (playAnim) {
|
||||
// Now update the player bar
|
||||
if (!m_Parent->GetParentUser()) return;
|
||||
auto* characterComponent = m_Parent->GetComponent<CharacterComponent>();
|
||||
if (!characterComponent) return;
|
||||
|
||||
AMFArrayValue args;
|
||||
args.Insert("amount", std::to_string(value));
|
||||
args.Insert("type", "armor");
|
||||
|
||||
GameMessages::SendUIMessageServerToSingleClient(m_Parent, m_Parent->GetParentUser()->GetSystemAddress(), "MaxPlayerBarUpdate", args);
|
||||
GameMessages::SendUIMessageServerToSingleClient(m_Parent, characterComponent->GetSystemAddress(), "MaxPlayerBarUpdate", args);
|
||||
}
|
||||
|
||||
Game::entityManager->SerializeEntity(m_Parent);
|
||||
@@ -332,13 +334,14 @@ void DestroyableComponent::SetMaxImagination(float value, bool playAnim) {
|
||||
|
||||
if (playAnim) {
|
||||
// Now update the player bar
|
||||
if (!m_Parent->GetParentUser()) return;
|
||||
auto* characterComponent = m_Parent->GetComponent<CharacterComponent>();
|
||||
if (!characterComponent) return;
|
||||
|
||||
AMFArrayValue args;
|
||||
args.Insert("amount", std::to_string(difference));
|
||||
args.Insert("type", "imagination");
|
||||
|
||||
GameMessages::SendUIMessageServerToSingleClient(m_Parent, m_Parent->GetParentUser()->GetSystemAddress(), "MaxPlayerBarUpdate", args);
|
||||
GameMessages::SendUIMessageServerToSingleClient(m_Parent, characterComponent->GetSystemAddress(), "MaxPlayerBarUpdate", args);
|
||||
}
|
||||
Game::entityManager->SerializeEntity(m_Parent);
|
||||
}
|
||||
|
||||
@@ -17,9 +17,9 @@ enum class eStateChangeType : uint32_t;
|
||||
* Represents the stats of an entity, for example its health, imagination and armor. Also handles factions, which
|
||||
* indicate which enemies this entity has.
|
||||
*/
|
||||
class DestroyableComponent : public Component {
|
||||
class DestroyableComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::DESTROYABLE;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::DESTROYABLE;
|
||||
|
||||
DestroyableComponent(Entity* parentEntity);
|
||||
~DestroyableComponent() override;
|
||||
|
||||
@@ -8,7 +8,7 @@ class Entity;
|
||||
|
||||
class DonationVendorComponent final : public VendorComponent {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::DONATION_VENDOR;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::DONATION_VENDOR;
|
||||
DonationVendorComponent(Entity* parent);
|
||||
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override;
|
||||
uint32_t GetActivityID() {return m_ActivityId;};
|
||||
|
||||
@@ -1,4 +1,57 @@
|
||||
#include "GhostComponent.h"
|
||||
|
||||
// TODO Move ghosting related code from Player to here
|
||||
GhostComponent::GhostComponent(Entity* parent) : Component(parent) {}
|
||||
GhostComponent::GhostComponent(Entity* parent) : Component(parent) {
|
||||
m_GhostReferencePoint = NiPoint3Constant::ZERO;
|
||||
m_GhostOverridePoint = NiPoint3Constant::ZERO;
|
||||
m_GhostOverride = false;
|
||||
}
|
||||
|
||||
GhostComponent::~GhostComponent() {
|
||||
for (auto& observedEntity : m_ObservedEntities) {
|
||||
if (observedEntity == 0) continue;
|
||||
|
||||
auto* entity = Game::entityManager->GetGhostCandidate(observedEntity);
|
||||
if (!entity) continue;
|
||||
|
||||
entity->SetObservers(entity->GetObservers() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void GhostComponent::SetGhostReferencePoint(const NiPoint3& value) {
|
||||
m_GhostReferencePoint = value;
|
||||
}
|
||||
|
||||
void GhostComponent::SetGhostOverridePoint(const NiPoint3& value) {
|
||||
m_GhostOverridePoint = value;
|
||||
}
|
||||
|
||||
void GhostComponent::AddLimboConstruction(LWOOBJID objectId) {
|
||||
m_LimboConstructions.insert(objectId);
|
||||
}
|
||||
|
||||
void GhostComponent::RemoveLimboConstruction(LWOOBJID objectId) {
|
||||
m_LimboConstructions.erase(objectId);
|
||||
}
|
||||
|
||||
void GhostComponent::ConstructLimboEntities() {
|
||||
for (const auto& objectId : m_LimboConstructions) {
|
||||
auto* entity = Game::entityManager->GetEntity(objectId);
|
||||
if (!entity) continue;
|
||||
|
||||
Game::entityManager->ConstructEntity(entity, m_Parent->GetSystemAddress());
|
||||
}
|
||||
|
||||
m_LimboConstructions.clear();
|
||||
}
|
||||
|
||||
void GhostComponent::ObserveEntity(int32_t id) {
|
||||
m_ObservedEntities.insert(id);
|
||||
}
|
||||
|
||||
bool GhostComponent::IsObserved(int32_t id) {
|
||||
return m_ObservedEntities.contains(id);
|
||||
}
|
||||
|
||||
void GhostComponent::GhostEntity(int32_t id) {
|
||||
m_ObservedEntities.erase(id);
|
||||
}
|
||||
|
||||
@@ -3,11 +3,52 @@
|
||||
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
#include <unordered_set>
|
||||
|
||||
class GhostComponent : public Component {
|
||||
class NiPoint3;
|
||||
|
||||
class GhostComponent final : public Component {
|
||||
public:
|
||||
static inline const eReplicaComponentType ComponentType = eReplicaComponentType::GHOST;
|
||||
GhostComponent(Entity* parent);
|
||||
~GhostComponent() override;
|
||||
|
||||
void SetGhostOverride(bool value) { m_GhostOverride = value; };
|
||||
|
||||
const NiPoint3& GetGhostReferencePoint() const { return m_GhostOverride ? m_GhostOverridePoint : m_GhostReferencePoint; };
|
||||
|
||||
const NiPoint3& GetOriginGhostReferencePoint() const { return m_GhostReferencePoint; };
|
||||
|
||||
const NiPoint3& GetGhostOverridePoint() const { return m_GhostOverridePoint; };
|
||||
|
||||
bool GetGhostOverride() const { return m_GhostOverride; };
|
||||
|
||||
void SetGhostReferencePoint(const NiPoint3& value);
|
||||
|
||||
void SetGhostOverridePoint(const NiPoint3& value);
|
||||
|
||||
void AddLimboConstruction(const LWOOBJID objectId);
|
||||
|
||||
void RemoveLimboConstruction(const LWOOBJID objectId);
|
||||
|
||||
void ConstructLimboEntities();
|
||||
|
||||
void ObserveEntity(const int32_t id);
|
||||
|
||||
bool IsObserved(const int32_t id);
|
||||
|
||||
void GhostEntity(const int32_t id);
|
||||
|
||||
private:
|
||||
NiPoint3 m_GhostReferencePoint;
|
||||
|
||||
NiPoint3 m_GhostOverridePoint;
|
||||
|
||||
std::unordered_set<int32_t> m_ObservedEntities;
|
||||
|
||||
std::unordered_set<LWOOBJID> m_LimboConstructions;
|
||||
|
||||
bool m_GhostOverride;
|
||||
};
|
||||
|
||||
#endif //!__GHOSTCOMPONENT__H__
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
#include "EntityManager.h"
|
||||
|
||||
HavokVehiclePhysicsComponent::HavokVehiclePhysicsComponent(Entity* parent) : PhysicsComponent(parent) {
|
||||
m_Velocity = NiPoint3::ZERO;
|
||||
m_AngularVelocity = NiPoint3::ZERO;
|
||||
m_Velocity = NiPoint3Constant::ZERO;
|
||||
m_AngularVelocity = NiPoint3Constant::ZERO;
|
||||
m_IsOnGround = true;
|
||||
m_IsOnRail = false;
|
||||
m_DirtyPosition = true;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
class HavokVehiclePhysicsComponent : public PhysicsComponent {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::HAVOK_VEHICLE_PHYSICS;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::HAVOK_VEHICLE_PHYSICS;
|
||||
|
||||
HavokVehiclePhysicsComponent(Entity* parentEntity);
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "Character.h"
|
||||
#include "EntityManager.h"
|
||||
#include "ItemSet.h"
|
||||
#include "Player.h"
|
||||
#include "PetComponent.h"
|
||||
#include "PossessorComponent.h"
|
||||
#include "PossessableComponent.h"
|
||||
@@ -1223,7 +1222,7 @@ void InventoryComponent::SpawnPet(Item* item) {
|
||||
EntityInfo info{};
|
||||
info.lot = item->GetLot();
|
||||
info.pos = m_Parent->GetPosition();
|
||||
info.rot = NiQuaternion::IDENTITY;
|
||||
info.rot = NiQuaternionConstant::IDENTITY;
|
||||
info.spawnerID = m_Parent->GetObjectID();
|
||||
|
||||
auto* pet = Game::entityManager->CreateEntity(info);
|
||||
|
||||
@@ -35,10 +35,9 @@ enum class eItemType : int32_t;
|
||||
* of different types, each type representing a different group of items, see `eInventoryType` for a list of
|
||||
* inventories.
|
||||
*/
|
||||
class InventoryComponent : public Component
|
||||
{
|
||||
class InventoryComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::INVENTORY;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::INVENTORY;
|
||||
explicit InventoryComponent(Entity* parent, tinyxml2::XMLDocument* document = nullptr);
|
||||
|
||||
void Update(float deltaTime) override;
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
class ItemComponent : public Component {
|
||||
class ItemComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::ITEM;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::ITEM;
|
||||
|
||||
ItemComponent(Entity* entity) : Component(entity) {}
|
||||
|
||||
|
||||
@@ -11,10 +11,10 @@
|
||||
* Component that handles the LOT that is shown in the LUP exhibit in the LUP world. Works by setting a timer and
|
||||
* switching the LOTs around that we'd like to display.
|
||||
*/
|
||||
class LUPExhibitComponent : public Component
|
||||
class LUPExhibitComponent final : public Component
|
||||
{
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::LUP_EXHIBIT;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::LUP_EXHIBIT;
|
||||
|
||||
LUPExhibitComponent(Entity* parent) : Component(parent) {};
|
||||
void Update(float deltaTime) override;
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
class LevelProgressionComponent : public Component {
|
||||
class LevelProgressionComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::LEVEL_PROGRESSION;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::LEVEL_PROGRESSION;
|
||||
|
||||
/**
|
||||
* Constructor for this component
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
class MiniGameControlComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MINI_GAME_CONTROL;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::MINI_GAME_CONTROL;
|
||||
|
||||
MiniGameControlComponent(Entity* parent) : Component(parent) {}
|
||||
void Serialize(RakNet::BitStream* outBitStream, bool isConstruction);
|
||||
|
||||
@@ -24,10 +24,9 @@ class AchievementCacheKey;
|
||||
* The mission inventory of an entity. Tracks mission state for each mission that can be accepted and allows for
|
||||
* progression of each of the mission task types (see eMissionTaskType).
|
||||
*/
|
||||
class MissionComponent : public Component
|
||||
{
|
||||
class MissionComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MISSION;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::MISSION;
|
||||
|
||||
explicit MissionComponent(Entity* parent);
|
||||
~MissionComponent() override;
|
||||
|
||||
@@ -59,9 +59,9 @@ private:
|
||||
/**
|
||||
* Allows entities to offer missions to other entities, depending on their mission inventory progression.
|
||||
*/
|
||||
class MissionOfferComponent : public Component {
|
||||
class MissionOfferComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MISSION_OFFER;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::MISSION_OFFER;
|
||||
|
||||
MissionOfferComponent(Entity* parent, LOT parentLot);
|
||||
|
||||
|
||||
@@ -22,9 +22,9 @@ class MoveToInventoryMessage;
|
||||
/**
|
||||
* Component that represents entities that are a model, e.g. collectible models and BBB models.
|
||||
*/
|
||||
class ModelComponent : public Component {
|
||||
class ModelComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MODEL;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::MODEL;
|
||||
|
||||
ModelComponent(Entity* parent);
|
||||
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
* same as having said items in your inventory (the subkey for this component) this component is the one that
|
||||
* renders the entity into the world.
|
||||
*/
|
||||
class ModuleAssemblyComponent : public Component {
|
||||
class ModuleAssemblyComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MODULE_ASSEMBLY;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::MODULE_ASSEMBLY;
|
||||
|
||||
ModuleAssemblyComponent(Entity* parent);
|
||||
~ModuleAssemblyComponent() override;
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
#include "CDComponentsRegistryTable.h"
|
||||
#include "CDPhysicsComponentTable.h"
|
||||
|
||||
#include "dNavMesh.h"
|
||||
|
||||
namespace {
|
||||
/**
|
||||
* Cache of all lots and their respective speeds
|
||||
@@ -41,7 +43,7 @@ MovementAIComponent::MovementAIComponent(Entity* parent, MovementAIInfo info) :
|
||||
m_NextWaypoint = m_Parent->GetPosition();
|
||||
m_Acceleration = 0.4f;
|
||||
m_PullingToPoint = false;
|
||||
m_PullPoint = NiPoint3::ZERO;
|
||||
m_PullPoint = NiPoint3Constant::ZERO;
|
||||
m_HaltDistance = 0;
|
||||
m_TimeToTravel = 0;
|
||||
m_TimeTravelled = 0;
|
||||
@@ -86,7 +88,7 @@ void MovementAIComponent::Update(const float deltaTime) {
|
||||
|
||||
SetPosition(source);
|
||||
|
||||
NiPoint3 velocity = NiPoint3::ZERO;
|
||||
NiPoint3 velocity = NiPoint3Constant::ZERO;
|
||||
|
||||
if (m_Acceleration > 0 && m_BaseSpeed > 0 && AdvanceWaypointIndex()) // Do we have another waypoint to seek?
|
||||
{
|
||||
@@ -169,8 +171,8 @@ NiPoint3 MovementAIComponent::ApproximateLocation() const {
|
||||
|
||||
auto approximation = source + ((destination - source) * percentageToWaypoint);
|
||||
|
||||
if (dpWorld::Instance().IsLoaded()) {
|
||||
approximation.y = dpWorld::Instance().GetNavMesh()->GetHeightAtPoint(approximation);
|
||||
if (dpWorld::IsLoaded()) {
|
||||
approximation.y = dpWorld::GetNavMesh()->GetHeightAtPoint(approximation);
|
||||
}
|
||||
|
||||
return approximation;
|
||||
@@ -181,8 +183,8 @@ bool MovementAIComponent::Warp(const NiPoint3& point) {
|
||||
|
||||
NiPoint3 destination = point;
|
||||
|
||||
if (dpWorld::Instance().IsLoaded()) {
|
||||
destination.y = dpWorld::Instance().GetNavMesh()->GetHeightAtPoint(point);
|
||||
if (dpWorld::IsLoaded()) {
|
||||
destination.y = dpWorld::GetNavMesh()->GetHeightAtPoint(point);
|
||||
|
||||
if (std::abs(destination.y - point.y) > 3) {
|
||||
return false;
|
||||
@@ -201,7 +203,7 @@ void MovementAIComponent::Stop() {
|
||||
|
||||
SetPosition(ApproximateLocation());
|
||||
|
||||
SetVelocity(NiPoint3::ZERO);
|
||||
SetVelocity(NiPoint3Constant::ZERO);
|
||||
|
||||
m_TimeToTravel = 0;
|
||||
m_TimeTravelled = 0;
|
||||
@@ -302,8 +304,8 @@ void MovementAIComponent::SetDestination(const NiPoint3& destination) {
|
||||
}
|
||||
|
||||
std::vector<NiPoint3> computedPath;
|
||||
if (dpWorld::Instance().IsLoaded()) {
|
||||
computedPath = dpWorld::Instance().GetNavMesh()->GetPath(m_Parent->GetPosition(), destination, m_Info.wanderSpeed);
|
||||
if (dpWorld::IsLoaded()) {
|
||||
computedPath = dpWorld::GetNavMesh()->GetPath(m_Parent->GetPosition(), destination, m_Info.wanderSpeed);
|
||||
}
|
||||
|
||||
// Somehow failed
|
||||
@@ -328,8 +330,8 @@ void MovementAIComponent::SetDestination(const NiPoint3& destination) {
|
||||
|
||||
// Simply path
|
||||
for (auto& point : computedPath) {
|
||||
if (dpWorld::Instance().IsLoaded()) {
|
||||
point.y = dpWorld::Instance().GetNavMesh()->GetHeightAtPoint(point);
|
||||
if (dpWorld::IsLoaded()) {
|
||||
point.y = dpWorld::GetNavMesh()->GetHeightAtPoint(point);
|
||||
}
|
||||
|
||||
m_InterpolatedWaypoints.push_back(point);
|
||||
|
||||
@@ -55,9 +55,9 @@ struct MovementAIInfo {
|
||||
* Component that handles the movement settings of an entity. Not to be confused with the BaseCombatAI component that
|
||||
* actually handles attackig and following enemy entities.
|
||||
*/
|
||||
class MovementAIComponent : public Component {
|
||||
class MovementAIComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MOVEMENT_AI;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::MOVEMENT_AI;
|
||||
|
||||
MovementAIComponent(Entity* parentEntity, MovementAIInfo info);
|
||||
|
||||
|
||||
@@ -104,9 +104,9 @@ public:
|
||||
* don't at all do what you expect them to as we don't instruct the client of changes made here.
|
||||
* ^^^ Trivia: This made the red blocks platform and property platforms a pain to implement.
|
||||
*/
|
||||
class MovingPlatformComponent : public Component {
|
||||
class MovingPlatformComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MOVING_PLATFORM;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::MOVING_PLATFORM;
|
||||
|
||||
MovingPlatformComponent(Entity* parent, const std::string& pathName);
|
||||
~MovingPlatformComponent() override;
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
* Component that handles the LUP/WBL rocket launchpad that can be interacted with to travel to WBL worlds.
|
||||
*
|
||||
*/
|
||||
class MultiZoneEntranceComponent : public Component {
|
||||
class MultiZoneEntranceComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MULTI_ZONE_ENTRANCE;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::MULTI_ZONE_ENTRANCE;
|
||||
|
||||
/**
|
||||
* Constructor for this component, builds the m_LUPWorlds vector
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "eObjectBits.h"
|
||||
#include "eGameMasterLevel.h"
|
||||
#include "eMissionState.h"
|
||||
#include "dNavMesh.h"
|
||||
|
||||
std::unordered_map<LOT, PetComponent::PetPuzzleData> PetComponent::buildCache{};
|
||||
std::unordered_map<LWOOBJID, LWOOBJID> PetComponent::currentActivities{};
|
||||
@@ -83,7 +84,7 @@ PetComponent::PetComponent(Entity* parentEntity, uint32_t componentId) : Compone
|
||||
m_DatabaseId = LWOOBJID_EMPTY;
|
||||
m_Status = 67108866; // Tamable
|
||||
m_Ability = ePetAbilityType::Invalid;
|
||||
m_StartPosition = NiPoint3::ZERO;
|
||||
m_StartPosition = NiPoint3Constant::ZERO;
|
||||
m_MovementAI = nullptr;
|
||||
m_TresureTime = 0;
|
||||
m_Preconditions = nullptr;
|
||||
@@ -250,17 +251,17 @@ void PetComponent::OnUse(Entity* originator) {
|
||||
NiPoint3 forward = NiQuaternion::LookAt(m_Parent->GetPosition(), originator->GetPosition()).GetForwardVector();
|
||||
forward.y = 0;
|
||||
|
||||
if (dpWorld::Instance().IsLoaded()) {
|
||||
if (dpWorld::IsLoaded()) {
|
||||
NiPoint3 attempt = petPosition + forward * interactionDistance;
|
||||
|
||||
float y = dpWorld::Instance().GetNavMesh()->GetHeightAtPoint(attempt);
|
||||
float y = dpWorld::GetNavMesh()->GetHeightAtPoint(attempt);
|
||||
|
||||
while (std::abs(y - petPosition.y) > 4 && interactionDistance > 10) {
|
||||
const NiPoint3 forward = m_Parent->GetRotation().GetForwardVector();
|
||||
|
||||
attempt = originatorPosition + forward * interactionDistance;
|
||||
|
||||
y = dpWorld::Instance().GetNavMesh()->GetHeightAtPoint(attempt);
|
||||
y = dpWorld::GetNavMesh()->GetHeightAtPoint(attempt);
|
||||
|
||||
interactionDistance -= 0.5f;
|
||||
}
|
||||
@@ -311,7 +312,7 @@ void PetComponent::OnUse(Entity* originator) {
|
||||
}
|
||||
|
||||
void PetComponent::Update(float deltaTime) {
|
||||
if (m_StartPosition == NiPoint3::ZERO) {
|
||||
if (m_StartPosition == NiPoint3Constant::ZERO) {
|
||||
m_StartPosition = m_Parent->GetPosition();
|
||||
}
|
||||
|
||||
@@ -446,7 +447,7 @@ void PetComponent::Update(float deltaTime) {
|
||||
if (distance < 5 * 5) {
|
||||
m_Interaction = closestTresure->GetObjectID();
|
||||
|
||||
Command(NiPoint3::ZERO, LWOOBJID_EMPTY, 1, 202, true);
|
||||
Command(NiPoint3Constant::ZERO, LWOOBJID_EMPTY, 1, 202, true);
|
||||
|
||||
m_TresureTime = 2;
|
||||
} else if (distance < 10 * 10) {
|
||||
@@ -530,7 +531,7 @@ void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) {
|
||||
EntityInfo info{};
|
||||
info.lot = cached->second.puzzleModelLot;
|
||||
info.pos = position;
|
||||
info.rot = NiQuaternion::IDENTITY;
|
||||
info.rot = NiQuaternionConstant::IDENTITY;
|
||||
info.spawnerID = tamer->GetObjectID();
|
||||
|
||||
auto* modelEntity = Game::entityManager->CreateEntity(info);
|
||||
@@ -590,9 +591,9 @@ void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) {
|
||||
LWOOBJID_EMPTY,
|
||||
false,
|
||||
ePetTamingNotifyType::NAMINGPET,
|
||||
NiPoint3::ZERO,
|
||||
NiPoint3::ZERO,
|
||||
NiQuaternion::IDENTITY,
|
||||
NiPoint3Constant::ZERO,
|
||||
NiPoint3Constant::ZERO,
|
||||
NiQuaternionConstant::IDENTITY,
|
||||
UNASSIGNED_SYSTEM_ADDRESS
|
||||
);
|
||||
|
||||
@@ -670,9 +671,9 @@ void PetComponent::RequestSetPetName(std::u16string name) {
|
||||
m_Tamer,
|
||||
false,
|
||||
ePetTamingNotifyType::SUCCESS,
|
||||
NiPoint3::ZERO,
|
||||
NiPoint3::ZERO,
|
||||
NiQuaternion::IDENTITY,
|
||||
NiPoint3Constant::ZERO,
|
||||
NiPoint3Constant::ZERO,
|
||||
NiQuaternionConstant::IDENTITY,
|
||||
UNASSIGNED_SYSTEM_ADDRESS
|
||||
);
|
||||
|
||||
@@ -711,9 +712,9 @@ void PetComponent::ClientExitTamingMinigame(bool voluntaryExit) {
|
||||
m_Tamer,
|
||||
false,
|
||||
ePetTamingNotifyType::QUIT,
|
||||
NiPoint3::ZERO,
|
||||
NiPoint3::ZERO,
|
||||
NiQuaternion::IDENTITY,
|
||||
NiPoint3Constant::ZERO,
|
||||
NiPoint3Constant::ZERO,
|
||||
NiQuaternionConstant::IDENTITY,
|
||||
UNASSIGNED_SYSTEM_ADDRESS
|
||||
);
|
||||
|
||||
@@ -762,9 +763,9 @@ void PetComponent::ClientFailTamingMinigame() {
|
||||
m_Tamer,
|
||||
false,
|
||||
ePetTamingNotifyType::FAILED,
|
||||
NiPoint3::ZERO,
|
||||
NiPoint3::ZERO,
|
||||
NiQuaternion::IDENTITY,
|
||||
NiPoint3Constant::ZERO,
|
||||
NiPoint3Constant::ZERO,
|
||||
NiQuaternionConstant::IDENTITY,
|
||||
UNASSIGNED_SYSTEM_ADDRESS
|
||||
);
|
||||
|
||||
@@ -812,8 +813,8 @@ void PetComponent::Wander() {
|
||||
|
||||
auto destination = m_StartPosition + delta;
|
||||
|
||||
if (dpWorld::Instance().IsLoaded()) {
|
||||
destination.y = dpWorld::Instance().GetNavMesh()->GetHeightAtPoint(destination);
|
||||
if (dpWorld::IsLoaded()) {
|
||||
destination.y = dpWorld::GetNavMesh()->GetHeightAtPoint(destination);
|
||||
}
|
||||
|
||||
if (Vector3::DistanceSquared(destination, m_MovementAI->GetParent()->GetPosition()) < 2 * 2) {
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
* Represents an entity that is a pet. This pet can be tamed and consequently follows the tamer around, allowing it
|
||||
* to dig for treasure and activate pet bouncers.
|
||||
*/
|
||||
class PetComponent : public Component
|
||||
class PetComponent final : public Component
|
||||
{
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::PET;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::PET;
|
||||
|
||||
explicit PetComponent(Entity* parentEntity, uint32_t componentId);
|
||||
~PetComponent() override;
|
||||
|
||||
@@ -156,89 +156,48 @@ PhantomPhysicsComponent::PhantomPhysicsComponent(Entity* parent) : PhysicsCompon
|
||||
//temp test
|
||||
if (info->physicsAsset == "miscellaneous\\misc_phys_10x1x5.hkx") {
|
||||
m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 10.0f, 5.0f, 1.0f);
|
||||
|
||||
m_dpEntity->SetScale(m_Scale);
|
||||
m_dpEntity->SetRotation(m_Rotation);
|
||||
m_dpEntity->SetPosition(m_Position);
|
||||
|
||||
dpWorld::Instance().AddEntity(m_dpEntity);
|
||||
} else if (info->physicsAsset == "miscellaneous\\misc_phys_640x640.hkx") {
|
||||
// Move this down by 13.521004 units so it is still effectively at the same height as before
|
||||
m_Position = m_Position - NiPoint3::UNIT_Y * 13.521004f;
|
||||
// TODO Fix physics simulation to do simulation at high velocities due to bullet through paper problem...
|
||||
m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 1638.4f, 13.521004f * 2.0f, 1638.4f);
|
||||
|
||||
m_dpEntity->SetScale(m_Scale);
|
||||
m_dpEntity->SetRotation(m_Rotation);
|
||||
m_dpEntity->SetPosition(m_Position);
|
||||
|
||||
dpWorld::Instance().AddEntity(m_dpEntity);
|
||||
// Move this down by 13.521004 units so it is still effectively at the same height as before
|
||||
m_Position = m_Position - NiPoint3Constant::UNIT_Y * 13.521004f;
|
||||
} else if (info->physicsAsset == "env\\trigger_wall_tall.hkx") {
|
||||
m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 10.0f, 25.0f, 1.0f);
|
||||
m_dpEntity->SetScale(m_Scale);
|
||||
m_dpEntity->SetRotation(m_Rotation);
|
||||
m_dpEntity->SetPosition(m_Position);
|
||||
dpWorld::Instance().AddEntity(m_dpEntity);
|
||||
} else if (info->physicsAsset == "env\\env_gen_placeholderphysics.hkx") {
|
||||
m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 20.0f, 20.0f, 20.0f);
|
||||
m_dpEntity->SetScale(m_Scale);
|
||||
m_dpEntity->SetRotation(m_Rotation);
|
||||
m_dpEntity->SetPosition(m_Position);
|
||||
dpWorld::Instance().AddEntity(m_dpEntity);
|
||||
} else if (info->physicsAsset == "env\\POI_trigger_wall.hkx") {
|
||||
m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 1.0f, 12.5f, 20.0f); // Not sure what the real size is
|
||||
m_dpEntity->SetScale(m_Scale);
|
||||
m_dpEntity->SetRotation(m_Rotation);
|
||||
m_dpEntity->SetPosition(m_Position);
|
||||
dpWorld::Instance().AddEntity(m_dpEntity);
|
||||
} else if (info->physicsAsset == "env\\NG_NinjaGo\\env_ng_gen_gate_chamber_puzzle_ceiling_tile_falling_phantom.hkx") {
|
||||
m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 18.0f, 5.0f, 15.0f);
|
||||
m_dpEntity->SetScale(m_Scale);
|
||||
m_dpEntity->SetRotation(m_Rotation);
|
||||
m_dpEntity->SetPosition(m_Position + m_Rotation.GetForwardVector() * 7.5f);
|
||||
dpWorld::Instance().AddEntity(m_dpEntity);
|
||||
m_Position += m_Rotation.GetForwardVector() * 7.5f;
|
||||
} else if (info->physicsAsset == "env\\NG_NinjaGo\\ng_flamejet_brick_phantom.HKX") {
|
||||
m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 1.0f, 1.0f, 12.0f);
|
||||
m_dpEntity->SetScale(m_Scale);
|
||||
m_dpEntity->SetRotation(m_Rotation);
|
||||
m_dpEntity->SetPosition(m_Position + m_Rotation.GetForwardVector() * 6.0f);
|
||||
dpWorld::Instance().AddEntity(m_dpEntity);
|
||||
m_Position += m_Rotation.GetForwardVector() * 6.0f;
|
||||
} else if (info->physicsAsset == "env\\Ring_Trigger.hkx") {
|
||||
m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 6.0f, 6.0f, 6.0f);
|
||||
m_dpEntity->SetScale(m_Scale);
|
||||
m_dpEntity->SetRotation(m_Rotation);
|
||||
m_dpEntity->SetPosition(m_Position);
|
||||
dpWorld::Instance().AddEntity(m_dpEntity);
|
||||
} else if (info->physicsAsset == "env\\vfx_propertyImaginationBall.hkx") {
|
||||
m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 4.5f);
|
||||
m_dpEntity->SetScale(m_Scale);
|
||||
m_dpEntity->SetRotation(m_Rotation);
|
||||
m_dpEntity->SetPosition(m_Position);
|
||||
dpWorld::Instance().AddEntity(m_dpEntity);
|
||||
} else if (info->physicsAsset == "env\\env_won_fv_gas-blocking-volume.hkx") {
|
||||
m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 390.496826f, 111.467964f, 600.821534f, true);
|
||||
m_dpEntity->SetScale(m_Scale);
|
||||
m_dpEntity->SetRotation(m_Rotation);
|
||||
m_Position.y -= (111.467964f * m_Scale) / 2;
|
||||
m_dpEntity->SetPosition(m_Position);
|
||||
dpWorld::Instance().AddEntity(m_dpEntity);
|
||||
} else {
|
||||
//LOG("This one is supposed to have %s", info->physicsAsset.c_str());
|
||||
// LOG_DEBUG("This one is supposed to have %s", info->physicsAsset.c_str());
|
||||
|
||||
//add fallback cube:
|
||||
m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 2.0f, 2.0f, 2.0f);
|
||||
m_dpEntity->SetScale(m_Scale);
|
||||
m_dpEntity->SetRotation(m_Rotation);
|
||||
m_dpEntity->SetPosition(m_Position);
|
||||
dpWorld::Instance().AddEntity(m_dpEntity);
|
||||
}
|
||||
|
||||
|
||||
m_dpEntity->SetScale(m_Scale);
|
||||
m_dpEntity->SetRotation(m_Rotation);
|
||||
m_dpEntity->SetPosition(m_Position);
|
||||
dpWorld::AddEntity(m_dpEntity);
|
||||
}
|
||||
}
|
||||
|
||||
PhantomPhysicsComponent::~PhantomPhysicsComponent() {
|
||||
if (m_dpEntity) {
|
||||
dpWorld::Instance().RemoveEntity(m_dpEntity);
|
||||
dpWorld::RemoveEntity(m_dpEntity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -300,7 +259,7 @@ void PhantomPhysicsComponent::CreatePhysics() {
|
||||
|
||||
m_dpEntity->SetPosition({ m_Position.x, m_Position.y - (height / 2), m_Position.z });
|
||||
|
||||
dpWorld::Instance().AddEntity(m_dpEntity);
|
||||
dpWorld::AddEntity(m_dpEntity);
|
||||
|
||||
m_HasCreatedPhysics = true;
|
||||
}
|
||||
|
||||
@@ -25,9 +25,9 @@ enum class ePhysicsEffectType : uint32_t ;
|
||||
* trigger gameplay events, for example the bus in Avant Gardens that moves around when the player touches its physics
|
||||
* body. Optionally this object can also have effects, like the fans in AG.
|
||||
*/
|
||||
class PhantomPhysicsComponent : public PhysicsComponent {
|
||||
class PhantomPhysicsComponent final : public PhysicsComponent {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::PHANTOM_PHYSICS;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::PHANTOM_PHYSICS;
|
||||
|
||||
PhantomPhysicsComponent(Entity* parent);
|
||||
~PhantomPhysicsComponent() override;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#include "PhysicsComponent.h"
|
||||
|
||||
PhysicsComponent::PhysicsComponent(Entity* parent) : Component(parent) {
|
||||
m_Position = NiPoint3::ZERO;
|
||||
m_Rotation = NiQuaternion::IDENTITY;
|
||||
m_Position = NiPoint3Constant::ZERO;
|
||||
m_Rotation = NiQuaternionConstant::IDENTITY;
|
||||
m_DirtyPosition = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
* Component that handles player forced movement
|
||||
*
|
||||
*/
|
||||
class PlayerForcedMovementComponent : public Component {
|
||||
class PlayerForcedMovementComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::PLAYER_FORCED_MOVEMENT;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::PLAYER_FORCED_MOVEMENT;
|
||||
|
||||
/**
|
||||
* Constructor for this component
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
* Represents an entity that can be controlled by some other entity, generally used by cars to indicate that some
|
||||
* player is controlling it.
|
||||
*/
|
||||
class PossessableComponent : public Component {
|
||||
class PossessableComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::POSSESSABLE;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::POSSESSABLE;
|
||||
|
||||
PossessableComponent(Entity* parentEntity, uint32_t componentId);
|
||||
|
||||
|
||||
@@ -16,9 +16,9 @@ enum class ePossessionType : uint8_t {
|
||||
/**
|
||||
* Represents an entity that can posess other entities. Generally used by players to drive a car.
|
||||
*/
|
||||
class PossessorComponent : public Component {
|
||||
class PossessorComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::POSSESSOR;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::POSSESSOR;
|
||||
|
||||
PossessorComponent(Entity* parent);
|
||||
~PossessorComponent() override;
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
#include "PropertyComponent.h"
|
||||
#include "GameMessages.h"
|
||||
#include "dZoneManager.h"
|
||||
|
||||
PropertyComponent::PropertyComponent(Entity* parent) : Component(parent) {
|
||||
m_PropertyName = parent->GetVar<std::string>(u"propertyName");
|
||||
m_PropertyState = new PropertyState();
|
||||
}
|
||||
|
||||
PropertyComponent::~PropertyComponent() = default;
|
||||
|
||||
@@ -1,34 +1,22 @@
|
||||
/*
|
||||
* Darkflame Universe
|
||||
* Copyright 2018
|
||||
* Copyright 2024
|
||||
*/
|
||||
|
||||
#ifndef PROPERTYCOMPONENT_H
|
||||
#define PROPERTYCOMPONENT_H
|
||||
|
||||
#include "BitStream.h"
|
||||
#include "Entity.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
struct PropertyState {
|
||||
LWOOBJID ownerID;
|
||||
LWOOBJID propertyID;
|
||||
bool rented;
|
||||
};
|
||||
|
||||
/**
|
||||
* This component is unused and has no functionality
|
||||
*/
|
||||
class PropertyComponent : public Component {
|
||||
class PropertyComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY;
|
||||
explicit PropertyComponent(Entity* parentEntity);
|
||||
~PropertyComponent() override;
|
||||
[[nodiscard]] PropertyState* GetPropertyState() const { return m_PropertyState; };
|
||||
private:
|
||||
PropertyState* m_PropertyState;
|
||||
std::string m_PropertyName;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY;
|
||||
explicit PropertyComponent(Entity* const parentEntity) noexcept : Component{ parentEntity } {}
|
||||
};
|
||||
|
||||
#endif // PROPERTYCOMPONENT_H
|
||||
#endif // !PROPERTYCOMPONENT_H
|
||||
|
||||
@@ -11,10 +11,10 @@
|
||||
/**
|
||||
* Represents the launch pad that's used to select and browse properties
|
||||
*/
|
||||
class PropertyEntranceComponent : public Component {
|
||||
class PropertyEntranceComponent final : public Component {
|
||||
public:
|
||||
explicit PropertyEntranceComponent(Entity* parent, uint32_t componentID);
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY_ENTRANCE;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY_ENTRANCE;
|
||||
|
||||
/**
|
||||
* Handles an OnUse request for some other entity, rendering the property browse menu
|
||||
|
||||
@@ -14,13 +14,13 @@
|
||||
#include "Item.h"
|
||||
#include "Database.h"
|
||||
#include "ObjectIDManager.h"
|
||||
#include "Player.h"
|
||||
#include "RocketLaunchpadControlComponent.h"
|
||||
#include "PropertyEntranceComponent.h"
|
||||
#include "InventoryComponent.h"
|
||||
#include "eMissionTaskType.h"
|
||||
#include "eObjectBits.h"
|
||||
#include "CharacterComponent.h"
|
||||
#include "PlayerManager.h"
|
||||
|
||||
#include <vector>
|
||||
#include "CppScripts.h"
|
||||
@@ -176,8 +176,6 @@ bool PropertyManagementComponent::Claim(const LWOOBJID playerId) {
|
||||
|
||||
auto* entity = Game::entityManager->GetEntity(playerId);
|
||||
|
||||
auto* user = entity->GetParentUser();
|
||||
|
||||
auto character = entity->GetCharacter();
|
||||
if (!character) return false;
|
||||
|
||||
@@ -227,7 +225,7 @@ void PropertyManagementComponent::OnStartBuilding() {
|
||||
|
||||
if (ownerEntity == nullptr) return;
|
||||
|
||||
const auto players = Player::GetAllPlayers();
|
||||
const auto players = PlayerManager::GetAllPlayers();
|
||||
|
||||
LWOMAPID zoneId = 1100;
|
||||
|
||||
@@ -296,7 +294,7 @@ void PropertyManagementComponent::UpdateModelPosition(const LWOOBJID id, const N
|
||||
|
||||
const auto modelLOT = item->GetLot();
|
||||
|
||||
if (rotation != NiQuaternion::IDENTITY) {
|
||||
if (rotation != NiQuaternionConstant::IDENTITY) {
|
||||
rotation = { rotation.w, rotation.z, rotation.y, rotation.x };
|
||||
}
|
||||
|
||||
@@ -480,7 +478,7 @@ void PropertyManagementComponent::DeleteModel(const LWOOBJID id, const int delet
|
||||
|
||||
GameMessages::SendGetModelsOnProperty(entity->GetObjectID(), GetModels(), UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
||||
GameMessages::SendPlaceModelResponse(entity->GetObjectID(), entity->GetSystemAddress(), NiPoint3::ZERO, LWOOBJID_EMPTY, 16, NiQuaternion::IDENTITY);
|
||||
GameMessages::SendPlaceModelResponse(entity->GetObjectID(), entity->GetSystemAddress(), NiPoint3Constant::ZERO, LWOOBJID_EMPTY, 16, NiQuaternionConstant::IDENTITY);
|
||||
|
||||
if (spawner != nullptr) {
|
||||
Game::zoneManager->RemoveSpawner(spawner->m_Info.spawnerID);
|
||||
@@ -533,7 +531,7 @@ void PropertyManagementComponent::DeleteModel(const LWOOBJID id, const int delet
|
||||
|
||||
GameMessages::SendGetModelsOnProperty(entity->GetObjectID(), GetModels(), UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
||||
GameMessages::SendPlaceModelResponse(entity->GetObjectID(), entity->GetSystemAddress(), NiPoint3::ZERO, LWOOBJID_EMPTY, 16, NiQuaternion::IDENTITY);
|
||||
GameMessages::SendPlaceModelResponse(entity->GetObjectID(), entity->GetSystemAddress(), NiPoint3Constant::ZERO, LWOOBJID_EMPTY, 16, NiQuaternionConstant::IDENTITY);
|
||||
|
||||
if (spawner != nullptr) {
|
||||
Game::zoneManager->RemoveSpawner(spawner->m_Info.spawnerID);
|
||||
|
||||
@@ -8,8 +8,7 @@
|
||||
/**
|
||||
* Information regarding which players may visit this property
|
||||
*/
|
||||
enum class PropertyPrivacyOption
|
||||
{
|
||||
enum class PropertyPrivacyOption {
|
||||
/**
|
||||
* Default, only you can visit your property
|
||||
*/
|
||||
@@ -29,10 +28,9 @@ enum class PropertyPrivacyOption
|
||||
/**
|
||||
* Main component that handles interactions with a property, generally the plaques you see on properties.
|
||||
*/
|
||||
class PropertyManagementComponent : public Component
|
||||
{
|
||||
class PropertyManagementComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY_MANAGEMENT;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY_MANAGEMENT;
|
||||
PropertyManagementComponent(Entity* parent);
|
||||
static PropertyManagementComponent* Instance();
|
||||
|
||||
|
||||
@@ -7,10 +7,9 @@
|
||||
/**
|
||||
* The property guard that stands on a property before it's claimed, allows entities to attempt claiming this property.
|
||||
*/
|
||||
class PropertyVendorComponent : public Component
|
||||
{
|
||||
class PropertyVendorComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY_VENDOR;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY_VENDOR;
|
||||
explicit PropertyVendorComponent(Entity* parent);
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,7 +18,7 @@ ProximityMonitorComponent::~ProximityMonitorComponent() {
|
||||
for (const auto& en : m_ProximitiesData) {
|
||||
if (!en.second) continue;
|
||||
|
||||
dpWorld::Instance().RemoveEntity(en.second);
|
||||
dpWorld::RemoveEntity(en.second);
|
||||
}
|
||||
|
||||
m_ProximitiesData.clear();
|
||||
@@ -28,12 +28,12 @@ void ProximityMonitorComponent::SetProximityRadius(float proxRadius, const std::
|
||||
dpEntity* en = new dpEntity(m_Parent->GetObjectID(), proxRadius);
|
||||
en->SetPosition(m_Parent->GetPosition());
|
||||
|
||||
dpWorld::Instance().AddEntity(en);
|
||||
dpWorld::AddEntity(en);
|
||||
m_ProximitiesData.insert(std::make_pair(name, en));
|
||||
}
|
||||
|
||||
void ProximityMonitorComponent::SetProximityRadius(dpEntity* entity, const std::string& name) {
|
||||
dpWorld::Instance().AddEntity(entity);
|
||||
dpWorld::AddEntity(entity);
|
||||
entity->SetPosition(m_Parent->GetPosition());
|
||||
m_ProximitiesData.insert(std::make_pair(name, entity));
|
||||
}
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
* Utility component for detecting how close entities are to named proximities for this entity. Allows you to store
|
||||
* proximity checks for multiple ojects.
|
||||
*/
|
||||
class ProximityMonitorComponent : public Component {
|
||||
class ProximityMonitorComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::PROXIMITY_MONITOR;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::PROXIMITY_MONITOR;
|
||||
|
||||
ProximityMonitorComponent(Entity* parentEntity, int smallRadius = -1, int largeRadius = -1);
|
||||
~ProximityMonitorComponent() override;
|
||||
|
||||
@@ -253,13 +253,13 @@ void QuickBuildComponent::OnUse(Entity* originator) {
|
||||
}
|
||||
|
||||
void QuickBuildComponent::SpawnActivator() {
|
||||
if (!m_SelfActivator || m_ActivatorPosition != NiPoint3::ZERO) {
|
||||
if (!m_SelfActivator || m_ActivatorPosition != NiPoint3Constant::ZERO) {
|
||||
if (!m_Activator) {
|
||||
EntityInfo info;
|
||||
|
||||
info.lot = 6604;
|
||||
info.spawnerID = m_Parent->GetObjectID();
|
||||
info.pos = m_ActivatorPosition == NiPoint3::ZERO ? m_Parent->GetPosition() : m_ActivatorPosition;
|
||||
info.pos = m_ActivatorPosition == NiPoint3Constant::ZERO ? m_Parent->GetPosition() : m_ActivatorPosition;
|
||||
|
||||
m_Activator = Game::entityManager->CreateEntity(info, nullptr, m_Parent);
|
||||
if (m_Activator) {
|
||||
|
||||
@@ -20,9 +20,9 @@ enum class eQuickBuildFailReason : uint32_t;
|
||||
* consists of an activator that shows a popup and then the actual entity that the bricks are built into. Note
|
||||
* that quick builds are also scripted activities so this shared some logic with the ScriptedActivityComponent.
|
||||
*/
|
||||
class QuickBuildComponent : public Component {
|
||||
class QuickBuildComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::QUICK_BUILD;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::QUICK_BUILD;
|
||||
|
||||
QuickBuildComponent(Entity* entity);
|
||||
~QuickBuildComponent() override;
|
||||
@@ -242,7 +242,7 @@ private:
|
||||
/**
|
||||
* The position that the quickbuild activator is spawned at
|
||||
*/
|
||||
NiPoint3 m_ActivatorPosition = NiPoint3::ZERO;
|
||||
NiPoint3 m_ActivatorPosition = NiPoint3Constant::ZERO;
|
||||
|
||||
/**
|
||||
* The entity that represents the quickbuild activator
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include "Item.h"
|
||||
#include "MissionComponent.h"
|
||||
#include "ModuleAssemblyComponent.h"
|
||||
#include "Player.h"
|
||||
#include "PossessableComponent.h"
|
||||
#include "PossessorComponent.h"
|
||||
#include "eRacingTaskParam.h"
|
||||
@@ -119,8 +118,8 @@ void RacingControlComponent::LoadPlayerVehicle(Entity* player,
|
||||
GeneralUtils::UTF16ToWTF8(m_PathName));
|
||||
|
||||
auto spawnPointEntities = Game::entityManager->GetEntitiesByLOT(4843);
|
||||
auto startPosition = NiPoint3::ZERO;
|
||||
auto startRotation = NiQuaternion::IDENTITY;
|
||||
auto startPosition = NiPoint3Constant::ZERO;
|
||||
auto startRotation = NiQuaternionConstant::IDENTITY;
|
||||
const std::string placementAsString = std::to_string(positionNumber);
|
||||
for (auto entity : spawnPointEntities) {
|
||||
if (!entity) continue;
|
||||
@@ -818,7 +817,7 @@ void RacingControlComponent::Update(float deltaTime) {
|
||||
|
||||
// Some offset up to make they don't fall through the terrain on a
|
||||
// respawn, seems to fix itself to the track anyhow
|
||||
player.respawnPosition = position + NiPoint3::UNIT_Y * 5;
|
||||
player.respawnPosition = position + NiPoint3Constant::UNIT_Y * 5;
|
||||
player.respawnRotation = vehicle->GetRotation();
|
||||
player.respawnIndex = respawnIndex;
|
||||
|
||||
|
||||
@@ -103,9 +103,9 @@ struct RacingPlayerInfo {
|
||||
/**
|
||||
* Component that's attached to a manager entity in each race zone that loads player vehicles, keep scores, etc.
|
||||
*/
|
||||
class RacingControlComponent : public Component {
|
||||
class RacingControlComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::RACING_CONTROL;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::RACING_CONTROL;
|
||||
|
||||
RacingControlComponent(Entity* parentEntity);
|
||||
~RacingControlComponent();
|
||||
|
||||
@@ -8,7 +8,7 @@ class Entity;
|
||||
|
||||
class RacingSoundTriggerComponent : public SoundTriggerComponent {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::RACING_SOUND_TRIGGER;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::RACING_SOUND_TRIGGER;
|
||||
RacingSoundTriggerComponent(Entity* parent) : SoundTriggerComponent(parent){};
|
||||
};
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
class RacingStatsComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::RACING_STATS;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::RACING_STATS;
|
||||
|
||||
RacingStatsComponent(Entity* parent) : Component(parent) {}
|
||||
};
|
||||
|
||||
@@ -15,7 +15,7 @@ public:
|
||||
explicit RailActivatorComponent(Entity* parent, int32_t componentID);
|
||||
~RailActivatorComponent() override;
|
||||
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::RAIL_ACTIVATOR;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::RAIL_ACTIVATOR;
|
||||
|
||||
/**
|
||||
* Handles the OnUse event from some entity, initiates the rail movement
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#include "RenderComponent.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <iomanip>
|
||||
|
||||
#include "Entity.h"
|
||||
@@ -14,8 +16,7 @@
|
||||
|
||||
std::unordered_map<int32_t, float> RenderComponent::m_DurationCache{};
|
||||
|
||||
RenderComponent::RenderComponent(Entity* parent, int32_t componentId): Component(parent) {
|
||||
m_Effects = std::vector<Effect*>();
|
||||
RenderComponent::RenderComponent(Entity* const parentEntity, const int32_t componentId) : Component{ parentEntity } {
|
||||
m_LastAnimationName = "";
|
||||
if (componentId == -1) return;
|
||||
|
||||
@@ -42,100 +43,51 @@ RenderComponent::RenderComponent(Entity* parent, int32_t componentId): Component
|
||||
result.finalize();
|
||||
}
|
||||
|
||||
RenderComponent::~RenderComponent() {
|
||||
for (Effect* eff : m_Effects) {
|
||||
if (eff) {
|
||||
delete eff;
|
||||
eff = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
m_Effects.clear();
|
||||
}
|
||||
|
||||
void RenderComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
|
||||
if (!bIsInitialUpdate) return;
|
||||
|
||||
outBitStream->Write<uint32_t>(m_Effects.size());
|
||||
|
||||
for (Effect* eff : m_Effects) {
|
||||
// we still need to write 0 as the size for name if it is a nullptr
|
||||
if (!eff) {
|
||||
outBitStream->Write<uint8_t>(0);
|
||||
continue;
|
||||
}
|
||||
|
||||
outBitStream->Write<uint8_t>(eff->name.size());
|
||||
for (auto& eff : m_Effects) {
|
||||
outBitStream->Write<uint8_t>(eff.name.size());
|
||||
// if there is no name, then we don't write anything else
|
||||
if (eff->name.empty()) continue;
|
||||
if (eff.name.empty()) continue;
|
||||
|
||||
for (const auto& value : eff->name) outBitStream->Write<uint8_t>(value);
|
||||
for (const auto& value : eff.name) outBitStream->Write<uint8_t>(value);
|
||||
|
||||
outBitStream->Write(eff->effectID);
|
||||
outBitStream->Write(eff.effectID);
|
||||
|
||||
outBitStream->Write<uint8_t>(eff->type.size());
|
||||
for (const auto& value : eff->type) outBitStream->Write<uint16_t>(value);
|
||||
outBitStream->Write<uint8_t>(eff.type.size());
|
||||
for (const auto& value : eff.type) outBitStream->Write<uint16_t>(value);
|
||||
|
||||
outBitStream->Write<float_t>(eff->priority);
|
||||
outBitStream->Write<int64_t>(eff->secondary);
|
||||
outBitStream->Write<float_t>(eff.priority);
|
||||
outBitStream->Write<int64_t>(eff.secondary);
|
||||
}
|
||||
}
|
||||
|
||||
Effect* RenderComponent::AddEffect(const int32_t effectId, const std::string& name, const std::u16string& type, const float priority) {
|
||||
auto* eff = new Effect();
|
||||
|
||||
eff->effectID = effectId;
|
||||
eff->name = name;
|
||||
eff->type = type;
|
||||
eff->priority = priority;
|
||||
m_Effects.push_back(eff);
|
||||
|
||||
return eff;
|
||||
Effect& RenderComponent::AddEffect(const int32_t effectId, const std::string& name, const std::u16string& type, const float priority) {
|
||||
return m_Effects.emplace_back(effectId, name, type, priority);
|
||||
}
|
||||
|
||||
void RenderComponent::RemoveEffect(const std::string& name) {
|
||||
uint32_t index = -1;
|
||||
if (m_Effects.empty()) return;
|
||||
|
||||
for (auto i = 0u; i < m_Effects.size(); ++i) {
|
||||
auto* eff = m_Effects[i];
|
||||
const auto effectToRemove = std::ranges::find_if(m_Effects, [&name](auto&& effect) { return effect.name == name; });
|
||||
if (effectToRemove == m_Effects.end()) return; // Return early if effect is not present
|
||||
|
||||
if (eff->name == name) {
|
||||
index = i;
|
||||
|
||||
delete eff;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_Effects.erase(m_Effects.begin() + index);
|
||||
const auto lastEffect = m_Effects.rbegin();
|
||||
*effectToRemove = std::move(*lastEffect); // Move-overwrite
|
||||
m_Effects.pop_back();
|
||||
}
|
||||
|
||||
void RenderComponent::Update(const float deltaTime) {
|
||||
std::vector<Effect*> dead;
|
||||
void RenderComponent::Update(const float deltaTime) {
|
||||
for (auto& effect : m_Effects) {
|
||||
if (effect.time == 0) continue; // Skip persistent effects
|
||||
|
||||
for (auto* effect : m_Effects) {
|
||||
if (effect->time == 0) {
|
||||
continue; // Skip persistent effects
|
||||
}
|
||||
const auto result = effect.time - deltaTime;
|
||||
if (result <= 0) continue;
|
||||
|
||||
const auto result = effect->time - deltaTime;
|
||||
|
||||
if (result <= 0) {
|
||||
dead.push_back(effect);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
effect->time = result;
|
||||
}
|
||||
|
||||
for (auto* effect : dead) {
|
||||
// StopEffect(effect->name);
|
||||
effect.time = result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,12 +96,12 @@ void RenderComponent::PlayEffect(const int32_t effectId, const std::u16string& e
|
||||
|
||||
GameMessages::SendPlayFXEffect(m_Parent, effectId, effectType, name, secondary, priority, scale, serialize);
|
||||
|
||||
auto* effect = AddEffect(effectId, name, effectType, priority);
|
||||
auto& effect = AddEffect(effectId, name, effectType, priority);
|
||||
|
||||
const auto& pair = m_DurationCache.find(effectId);
|
||||
|
||||
if (pair != m_DurationCache.end()) {
|
||||
effect->time = pair->second;
|
||||
effect.time = pair->second;
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -168,16 +120,16 @@ void RenderComponent::PlayEffect(const int32_t effectId, const std::u16string& e
|
||||
|
||||
m_DurationCache[effectId] = 0;
|
||||
|
||||
effect->time = 0; // Persistent effect
|
||||
effect.time = 0; // Persistent effect
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
effect->time = static_cast<float>(result.getFloatField(0));
|
||||
effect.time = static_cast<float>(result.getFloatField(0));
|
||||
|
||||
result.finalize();
|
||||
|
||||
m_DurationCache[effectId] = effect->time;
|
||||
m_DurationCache[effectId] = effect.time;
|
||||
}
|
||||
|
||||
void RenderComponent::StopEffect(const std::string& name, const bool killImmediate) {
|
||||
@@ -186,11 +138,6 @@ void RenderComponent::StopEffect(const std::string& name, const bool killImmedia
|
||||
RemoveEffect(name);
|
||||
}
|
||||
|
||||
std::vector<Effect*>& RenderComponent::GetEffects() {
|
||||
return m_Effects;
|
||||
}
|
||||
|
||||
|
||||
float RenderComponent::PlayAnimation(Entity* self, const std::u16string& animation, float priority, float scale) {
|
||||
if (!self) return 0.0f;
|
||||
return RenderComponent::PlayAnimation(self, GeneralUtils::UTF16ToWTF8(animation), priority, scale);
|
||||
|
||||
@@ -17,7 +17,12 @@ class Entity;
|
||||
* here.
|
||||
*/
|
||||
struct Effect {
|
||||
Effect() { priority = 1.0f; }
|
||||
explicit Effect(const int32_t effectID, const std::string& name, const std::u16string& type, const float priority = 1.0f) noexcept
|
||||
: effectID{ effectID }
|
||||
, name{ name }
|
||||
, type{ type }
|
||||
, priority{ priority } {
|
||||
}
|
||||
|
||||
/**
|
||||
* The ID of the effect
|
||||
@@ -54,12 +59,11 @@ struct Effect {
|
||||
* Determines that a component should be visibly rendered into the world, most entities have this. This component
|
||||
* also handles effects that play for entities.
|
||||
*/
|
||||
class RenderComponent : public Component {
|
||||
class RenderComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::RENDER;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::RENDER;
|
||||
|
||||
RenderComponent(Entity* entity, int32_t componentId = -1);
|
||||
~RenderComponent() override;
|
||||
RenderComponent(Entity* const parentEntity, const int32_t componentId = -1);
|
||||
|
||||
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override;
|
||||
void Update(float deltaTime) override;
|
||||
@@ -72,7 +76,7 @@ public:
|
||||
* @param priority the priority of the effect
|
||||
* @return if successful, the effect that was created
|
||||
*/
|
||||
Effect* AddEffect(int32_t effectId, const std::string& name, const std::u16string& type, const float priority);
|
||||
[[maybe_unused]] Effect& AddEffect(const int32_t effectId, const std::string& name, const std::u16string& type, const float priority);
|
||||
|
||||
/**
|
||||
* Removes an effect for this entity
|
||||
@@ -99,12 +103,6 @@ public:
|
||||
*/
|
||||
void StopEffect(const std::string& name, bool killImmediate = true);
|
||||
|
||||
/**
|
||||
* Returns the list of currently active effects
|
||||
* @return
|
||||
*/
|
||||
std::vector<Effect*>& GetEffects();
|
||||
|
||||
/**
|
||||
* Verifies that an animation can be played on this entity by checking
|
||||
* if it has the animation assigned to its group. If it does, the animation is echo'd
|
||||
@@ -125,10 +123,10 @@ public:
|
||||
|
||||
static float PlayAnimation(Entity* self, const std::u16string& animation, float priority = 0.0f, float scale = 1.0f);
|
||||
static float PlayAnimation(Entity* self, const std::string& animation, float priority = 0.0f, float scale = 1.0f);
|
||||
static float GetAnimationTime(Entity* self, const std::string& animation);
|
||||
static float GetAnimationTime(Entity* self, const std::u16string& animation);
|
||||
[[nodiscard]] static float GetAnimationTime(Entity* self, const std::string& animation);
|
||||
[[nodiscard]] static float GetAnimationTime(Entity* self, const std::u16string& animation);
|
||||
|
||||
const std::string& GetLastAnimationName() const { return m_LastAnimationName; };
|
||||
[[nodiscard]] const std::string& GetLastAnimationName() const { return m_LastAnimationName; };
|
||||
void SetLastAnimationName(const std::string& name) { m_LastAnimationName = name; };
|
||||
|
||||
private:
|
||||
@@ -136,7 +134,7 @@ private:
|
||||
/**
|
||||
* List of currently active effects
|
||||
*/
|
||||
std::vector<Effect*> m_Effects;
|
||||
std::vector<Effect> m_Effects;
|
||||
|
||||
std::vector<int32_t> m_animationGroupIds;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
*/
|
||||
class RigidbodyPhantomPhysicsComponent : public PhysicsComponent {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS;
|
||||
|
||||
RigidbodyPhantomPhysicsComponent(Entity* parent);
|
||||
|
||||
|
||||
@@ -16,9 +16,9 @@ class PreconditionExpression;
|
||||
/**
|
||||
* Component that handles rocket launchpads that can be interacted with to travel to other worlds.
|
||||
*/
|
||||
class RocketLaunchpadControlComponent : public Component {
|
||||
class RocketLaunchpadControlComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::ROCKET_LAUNCH;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::ROCKET_LAUNCH;
|
||||
|
||||
RocketLaunchpadControlComponent(Entity* parent, int rocketId);
|
||||
~RocketLaunchpadControlComponent() override;
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
|
||||
class Entity;
|
||||
|
||||
class ScriptedActivityComponent : public ActivityComponent {
|
||||
class ScriptedActivityComponent final : public ActivityComponent {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::SCRIPTED_ACTIVITY;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::SCRIPTED_ACTIVITY;
|
||||
ScriptedActivityComponent(Entity* parent, int activityID) : ActivityComponent(parent, activityID){};
|
||||
};
|
||||
|
||||
|
||||
@@ -71,9 +71,9 @@ struct StaticShootingGalleryParams {
|
||||
* A very ancient component that was used to guide shooting galleries, it's still kind of used but a lot of logic is
|
||||
* also in the related scripts.
|
||||
*/
|
||||
class ShootingGalleryComponent : public Component {
|
||||
class ShootingGalleryComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::SHOOTING_GALLERY;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::SHOOTING_GALLERY;
|
||||
|
||||
explicit ShootingGalleryComponent(Entity* parent);
|
||||
~ShootingGalleryComponent();
|
||||
|
||||
@@ -28,7 +28,7 @@ enum class eClimbableType : int32_t {
|
||||
*/
|
||||
class SimplePhysicsComponent : public PhysicsComponent {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::SIMPLE_PHYSICS;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::SIMPLE_PHYSICS;
|
||||
|
||||
SimplePhysicsComponent(Entity* parent, uint32_t componentID);
|
||||
~SimplePhysicsComponent() override;
|
||||
@@ -87,12 +87,12 @@ private:
|
||||
/**
|
||||
* The current velocity of the entity
|
||||
*/
|
||||
NiPoint3 m_Velocity = NiPoint3::ZERO;
|
||||
NiPoint3 m_Velocity = NiPoint3Constant::ZERO;
|
||||
|
||||
/**
|
||||
* The current angular velocity of the entity
|
||||
*/
|
||||
NiPoint3 m_AngularVelocity = NiPoint3::ZERO;
|
||||
NiPoint3 m_AngularVelocity = NiPoint3Constant::ZERO;
|
||||
|
||||
/**
|
||||
* Whether or not the velocity has changed
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Darkflame Universe
|
||||
* Copyright 2018
|
||||
* Copyright 2024
|
||||
*/
|
||||
|
||||
#ifndef SKILLCOMPONENT_H
|
||||
@@ -55,11 +55,11 @@ struct SkillExecutionResult {
|
||||
*
|
||||
* Skills are a built up by a tree of behaviors. See dGame/dBehaviors/ for a list of behaviors.
|
||||
*
|
||||
* This system is very conveluted and still has a lot of unknowns.
|
||||
* This system is very convoluted and still has a lot of unknowns.
|
||||
*/
|
||||
class SkillComponent : public Component {
|
||||
class SkillComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::SKILL;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::SKILL;
|
||||
|
||||
explicit SkillComponent(Entity* parent);
|
||||
~SkillComponent() override;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "dCommonVars.h"
|
||||
#include "Entity.h"
|
||||
#include "GUID.h"
|
||||
@@ -43,7 +44,7 @@ struct GUIDResults{
|
||||
void Serialize(RakNet::BitStream* outBitStream);
|
||||
};
|
||||
|
||||
struct MixerProgram{
|
||||
struct MixerProgram {
|
||||
std::string name;
|
||||
uint32_t result;
|
||||
|
||||
@@ -58,7 +59,7 @@ struct MixerProgram{
|
||||
|
||||
class SoundTriggerComponent : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::SOUND_TRIGGER;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::SOUND_TRIGGER;
|
||||
explicit SoundTriggerComponent(Entity* parent);
|
||||
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override;
|
||||
void ActivateMusicCue(const std::string& name, float bordemTime = -1.0);
|
||||
@@ -66,11 +67,11 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
std::vector<MusicCue> m_MusicCues = {};
|
||||
std::vector<MusicParameter> m_MusicParameters = {};
|
||||
std::vector<GUIDResults> m_2DAmbientSounds = {};
|
||||
std::vector<GUIDResults> m_3DAmbientSounds = {};
|
||||
std::vector<MixerProgram> m_MixerPrograms = {};
|
||||
std::vector<MusicCue> m_MusicCues;
|
||||
std::vector<MusicParameter> m_MusicParameters;
|
||||
std::vector<GUIDResults> m_2DAmbientSounds;
|
||||
std::vector<GUIDResults> m_3DAmbientSounds;
|
||||
std::vector<MixerProgram> m_MixerPrograms;
|
||||
|
||||
bool m_Dirty = false;
|
||||
};
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
/**
|
||||
* A component for switches in game, including pet triggered switches.
|
||||
*/
|
||||
class SwitchComponent : public Component {
|
||||
class SwitchComponent final : public Component {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::SWITCH;
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::SWITCH;
|
||||
|
||||
SwitchComponent(Entity* parent);
|
||||
~SwitchComponent() override;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user