Compare commits

..

14 Commits

Author SHA1 Message Date
d532a9b063 It works (kinda) now to actually implement things 2025-10-11 00:02:31 -05:00
5453d163a3 WIP 2025-10-06 19:15:55 -05:00
David Markowitz
62ac65c520 feat: Mission Component debug (#1901)
* feat: Mission Component debug

* Add player argument to inspect command

* Add completion details

* Remove unlocalized server string

done on client instead
2025-10-05 22:13:27 -05:00
HailStorm32
5d5bce53d0 feat: Add configurable restrictions for muted accounts (#1887)
* Add configurable restrictions for muted accounts

* switched to and updated GetRandomElement

* Update config option check

* implement cached config values for mute settings and update handlers

* Address review

* Update dGame/dComponents/PetComponent.cpp

Co-authored-by: David Markowitz <39972741+EmosewaMC@users.noreply.github.com>

* Update dGame/dComponents/PetComponent.cpp

Co-authored-by: David Markowitz <39972741+EmosewaMC@users.noreply.github.com>

* reduce if argument chain

---------

Co-authored-by: David Markowitz <39972741+EmosewaMC@users.noreply.github.com>
2025-10-05 22:09:43 -05:00
David Markowitz
5791c55a9e fix: the exploding script is the most amazing piece of code i have ev… (#1900)
* fix: the exploding script is the most amazing piece of code i have ever had the pleasure of working with and has been amazing to work on and translate from lua

hahahahahahahahahahwwwwwwwwwwwwwwww草

* Enhance hit detection with proximity object checks

Refactor hit handling to include proximity checks for destroyable entities.
2025-10-05 00:19:46 -07:00
David Markowitz
17d0c45382 fix: why oh why is the aggro radius apart of the enemy (#1899) 2025-10-04 20:45:42 -07:00
David Markowitz
7dbbef81ac fix: regenerated proxy items dont need new ids and fix equip item ids (#1897)
* fix: changed item ids not reflected in equipped items

* dont do it for proxy items
2025-10-04 18:42:34 -07:00
David Markowitz
06958cb9cd feat: hardcore limit % coins dropped on death (#1898)
* feat: hardcore limit % coins dropped on death

Update EntityManager.cpp

* fix log msg
2025-10-04 17:25:23 -07:00
David Markowitz
69b1a694a6 fix: ignore foreign key checks more (#1895)
fixes an issue if you delete users in an earlier build of dlu.
2025-10-04 13:57:16 -05:00
David Markowitz
b2609ff6cb fix: live accurate player flag missions and flag debugging (#1894)
* feat: Add component ID to root component object

* fix: live accurate player flag missions and flag debugging

Tested that the client reflects the correct server progression after a test map and manually setting a flag off.
tested that session flags correctly pick up on progression updates

* banana
2025-10-04 01:07:52 -05:00
David Markowitz
e8c0b3e6da feat: Add component ID to root component object (#1893) 2025-10-03 20:57:42 -05:00
David Markowitz
25418fd8b2 fix: exploding asset bugs (#1890) 2025-10-01 20:48:08 -05:00
David Markowitz
502c965d97 feat: script debug info (#1891) 2025-10-01 14:21:25 -05:00
David Markowitz
205c190c61 fix: proxy items not equipping on login (#1892)
tested that items now equip on login
2025-10-01 07:55:51 -05:00
139 changed files with 4049 additions and 395 deletions

View File

@@ -89,6 +89,7 @@ elseif(MSVC)
add_compile_options("/wd4267" "/utf-8" "/volatile:iso" "/Zc:inline")
elseif(WIN32)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
add_compile_definitions(NOMINMAX)
endif()
# Our output dir
@@ -253,6 +254,7 @@ include_directories(
"thirdparty/MD5"
"thirdparty/nlohmann"
"thirdparty/mongoose"
"thirdparty/inja"
)
# Add system specfic includes for Apple, Windows and Other Unix OS' (including Linux)
@@ -322,6 +324,7 @@ endif()
add_subdirectory(dWorldServer)
add_subdirectory(dAuthServer)
add_subdirectory(dChatServer)
add_subdirectory(dDashboardServer)
add_subdirectory(dMasterServer) # Add MasterServer last so it can rely on the other binaries
target_precompile_headers(

View File

@@ -26,12 +26,14 @@ void HandleHTTPPlayersRequest(HTTPReply& reply, std::string body) {
const json data = Game::playerContainer;
reply.status = data.empty() ? eHTTPStatusCode::NO_CONTENT : eHTTPStatusCode::OK;
reply.message = data.empty() ? "{\"error\":\"No Players Online\"}" : data.dump();
reply.contentType = ContentType::JSON;
}
void HandleHTTPTeamsRequest(HTTPReply& reply, std::string body) {
const json data = TeamContainer::GetTeamContainer();
reply.status = data.empty() ? eHTTPStatusCode::NO_CONTENT : eHTTPStatusCode::OK;
reply.message = data.empty() ? "{\"error\":\"No Teams Online\"}" : data.dump();
reply.contentType = ContentType::JSON;
}
void HandleHTTPAnnounceRequest(HTTPReply& reply, std::string body) {
@@ -39,6 +41,7 @@ void HandleHTTPAnnounceRequest(HTTPReply& reply, std::string body) {
if (!data) {
reply.status = eHTTPStatusCode::BAD_REQUEST;
reply.message = "{\"error\":\"Invalid JSON\"}";
reply.contentType = ContentType::JSON;
return;
}
@@ -47,6 +50,7 @@ void HandleHTTPAnnounceRequest(HTTPReply& reply, std::string body) {
if (!check.empty()) {
reply.status = eHTTPStatusCode::BAD_REQUEST;
reply.message = check;
reply.contentType = ContentType::JSON;
} else {
ChatPackets::Announcement announcement;
@@ -56,6 +60,7 @@ void HandleHTTPAnnounceRequest(HTTPReply& reply, std::string body) {
reply.status = eHTTPStatusCode::OK;
reply.message = "{\"status\":\"Announcement Sent\"}";
reply.contentType = ContentType::JSON;
}
}

View File

@@ -3,7 +3,7 @@
// C++
#include <charconv>
#include <cstdint>
#include <cmath>
#include <cmath>
#include <ctime>
#include <functional>
#include <optional>
@@ -19,6 +19,7 @@
#include "dPlatforms.h"
#include "Game.h"
#include "Logger.h"
#include "DluAssert.h"
#include <glm/ext/vector_float3.hpp>
@@ -305,7 +306,7 @@ namespace GeneralUtils {
template<typename Container>
inline Container::value_type GetRandomElement(const Container& container) {
DluAssert(!container.empty());
return container[GenerateRandomNumber<typename Container::value_type>(0, container.size() - 1)];
return container[GenerateRandomNumber<typename Container::size_type>(0, container.size() - 1)];
}
/**

View File

@@ -50,7 +50,10 @@ enum class eMissionState : int {
/**
* The mission has been completed before and has now been completed again. Used for daily missions.
*/
COMPLETE_READY_TO_COMPLETE = 12
COMPLETE_READY_TO_COMPLETE = 12,
// The mission is failed (don't know where this is used)
FAILED = 16,
};
#endif //!__MISSIONSTATE__H__

View File

@@ -0,0 +1,8 @@
set(DDASHBOARDSERVER_SOURCES
"DashboardWeb.cpp"
)
add_executable(DashboardServer "DashboardServer.cpp" "DashboardWeb.cpp")
target_link_libraries(DashboardServer ${COMMON_LIBRARIES} dServer dWeb)
target_include_directories(DashboardServer PRIVATE ${PROJECT_SOURCE_DIR}/dServer ${PROJECT_SOURCE_DIR}/dWeb)
add_compile_definitions(DashboardServer PRIVATE PROJECT_VERSION="\"${PROJECT_VERSION}\"")

View File

@@ -0,0 +1,182 @@
#include <iostream>
#include <string>
#include <chrono>
#include <thread>
//DLU Includes:
#include "dCommonVars.h"
#include "dServer.h"
#include "Logger.h"
#include "Database.h"
#include "dConfig.h"
#include "Diagnostics.h"
#include "AssetManager.h"
#include "BinaryPathFinder.h"
#include "ServiceType.h"
#include "StringifiedEnum.h"
#include "Game.h"
#include "Server.h"
//RakNet includes:
#include "RakNetDefines.h"
#include "MessageIdentifiers.h"
#include "DashboardWeb.h"
namespace Game {
Logger* logger = nullptr;
dServer* server = nullptr;
dConfig* config = nullptr;
AssetManager* assetManager = nullptr;
Game::signal_t lastSignal = 0;
std::mt19937 randomEngine;
}
int main(int argc, char** argv) {
constexpr uint32_t dashboardFramerate = mediumFramerate;
constexpr uint32_t dashboardFrameDelta = mediumFrameDelta;
Diagnostics::SetProcessName("Dashboard");
Diagnostics::SetProcessFileName(argv[0]);
Diagnostics::Initialize();
std::signal(SIGINT, Game::OnSignal);
std::signal(SIGTERM, Game::OnSignal);
Game::config = new dConfig("dashboardconfig.ini");
//Create all the objects we need to run our service:
Server::SetupLogger("DashboardServer");
if (!Game::logger) return EXIT_FAILURE;
Game::config->LogSettings();
//Read our config:
LOG("Starting Dashboard server...");
LOG("Version: %s", PROJECT_VERSION);
LOG("Compiled on: %s", __TIMESTAMP__);
try {
std::string clientPathStr = Game::config->GetValue("client_location");
if (clientPathStr.empty()) clientPathStr = "./res";
std::filesystem::path clientPath = std::filesystem::path(clientPathStr);
if (clientPath.is_relative()) {
clientPath = BinaryPathFinder::GetBinaryDir() / clientPath;
}
Game::assetManager = new AssetManager(clientPath);
} catch (std::runtime_error& ex) {
LOG("Got an error while setting up assets: %s", ex.what());
delete Game::logger;
delete Game::config;
return EXIT_FAILURE;
}
//Connect to the Database
try {
Database::Connect();
} catch (std::exception& ex) {
LOG("Got an error while connecting to the database: %s", ex.what());
Database::Destroy("DashboardServer");
delete Game::logger;
delete Game::config;
return EXIT_FAILURE;
}
// setup the chat api web server
const uint32_t web_server_port = GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("web_server_port")).value_or(80);
if (!Game::web.Startup("localhost", web_server_port)) {
// if we want the web server and it fails to start, exit
LOG("Failed to start web server, shutting down.");
Database::Destroy("DashboardServer");
delete Game::logger;
delete Game::config;
return EXIT_FAILURE;
}
DashboardWeb::RegisterRoutes();
//Find out the master's IP:
std::string masterIP;
uint32_t masterPort = 1000;
std::string masterPassword;
auto masterInfo = Database::Get()->GetMasterInfo();
if (masterInfo) {
masterIP = masterInfo->ip;
masterPort = masterInfo->port;
masterPassword = masterInfo->password;
}
//It's safe to pass 'localhost' here, as the IP is only used as the external IP.
std::string ourIP = "localhost";
const uint32_t maxClients = GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("max_clients")).value_or(999);
const uint32_t ourPort = GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("dashboard_server_port")).value_or(2006);
const auto externalIPString = Game::config->GetValue("external_ip");
if (!externalIPString.empty()) ourIP = externalIPString;
Game::server = new dServer(ourIP, ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServiceType::COMMON, Game::config, &Game::lastSignal, masterPassword);
Game::randomEngine = std::mt19937(time(0));
//Run it until server gets a kill message from Master:
auto t = std::chrono::high_resolution_clock::now();
Packet* packet = nullptr;
constexpr uint32_t logFlushTime = 30 * dashboardFramerate; // 30 seconds in frames
constexpr uint32_t sqlPingTime = 10 * 60 * dashboardFramerate; // 10 minutes in frames
uint32_t framesSinceLastFlush = 0;
uint32_t framesSinceMasterDisconnect = 0;
uint32_t framesSinceLastSQLPing = 0;
auto lastTime = std::chrono::high_resolution_clock::now();
Game::logger->Flush(); // once immediately before main loop
while (!Game::ShouldShutdown()) {
// Check if we're still connected to master:
if (!Game::server->GetIsConnectedToMaster()) {
framesSinceMasterDisconnect++;
if (framesSinceMasterDisconnect >= dashboardFramerate)
break; //Exit our loop, shut down.
} else framesSinceMasterDisconnect = 0;
const auto currentTime = std::chrono::high_resolution_clock::now();
const float deltaTime = std::chrono::duration<float>(currentTime - lastTime).count();
lastTime = currentTime;
// Check and handle web requests:
Game::web.ReceiveRequests();
//Push our log every 30s:
if (framesSinceLastFlush >= logFlushTime) {
Game::logger->Flush();
framesSinceLastFlush = 0;
} else framesSinceLastFlush++;
//Every 10 min we ping our sql server to keep it alive hopefully:
if (framesSinceLastSQLPing >= sqlPingTime) {
//Find out the master's IP for absolutely no reason:
std::string masterIP;
uint32_t masterPort;
auto masterInfo = Database::Get()->GetMasterInfo();
if (masterInfo) {
masterIP = masterInfo->ip;
masterPort = masterInfo->port;
}
framesSinceLastSQLPing = 0;
} else framesSinceLastSQLPing++;
//Sleep our thread since auth can afford to.
t += std::chrono::milliseconds(dashboardFrameDelta); //Chat can run at a lower "fps"
std::this_thread::sleep_until(t);
}
//Delete our objects here:
Database::Destroy("DashboardServer");
delete Game::server;
delete Game::logger;
delete Game::config;
return EXIT_SUCCESS;
}

View File

@@ -0,0 +1,59 @@
#include "DashboardWeb.h"
// thanks bill gates
#ifdef _WIN32
#undef min
#undef max
#endif
#include "inja.hpp"
#include "eHTTPMethod.h"
// simple home page with inja
void HandleHTTPHomeRequest(HTTPReply& reply, std::string body) {
try {
inja::Environment env;
env.set_trim_blocks(true);
env.set_lstrip_blocks(true);
nlohmann::json data;
data["title"] = "Darkflame Universe Dashboard";
data["header"] = "Welcome to the Darkflame Universe Dashboard";
data["message"] = "This is a simple dashboard page served using Inja templating engine.";
const std::string template_str = R"(
<!DOCTYPE html>
<html lang="en">
<head>
<title>{{ title }}</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<h1>{{ header }}</h1>
<p>{{ message }}</p>
</body>
</html>
)";
std::string rendered = env.render(template_str, data);
reply.message = rendered;
reply.status = eHTTPStatusCode::OK;
reply.contentType = ContentType::HTML;
} catch (const std::exception& e) {
reply.status = eHTTPStatusCode::INTERNAL_SERVER_ERROR;
reply.message = "Internal Server Error";
reply.contentType = ContentType::PLAIN;
}
}
namespace DashboardWeb {
void RegisterRoutes() {
Game::web.RegisterHTTPRoute({
.path = "/",
.method = eHTTPMethod::GET,
.handle = HandleHTTPHomeRequest
});
}
}

View File

@@ -0,0 +1,11 @@
#ifndef __DASHBOARDWEB_H__
#define __DASHBOARDWEB_H__
#include "Web.h"
namespace DashboardWeb {
void RegisterRoutes();
};
#endif // __DASHBOARDWEB_H__

View File

@@ -682,6 +682,9 @@ private:
* NOTE: quick as there's no DB lookups
*/
void DoQuickXMLDataParse();
public:
const decltype(m_PlayerFlags)& GetPlayerFlags() const { return m_PlayerFlags; }
const decltype(m_SessionFlags)& GetSessionFlags() const { return m_SessionFlags; }
};
#endif // CHARACTER_H

View File

@@ -199,7 +199,7 @@ void Entity::Initialize() {
const auto triggerInfo = GetVarAsString(u"trigger_id");
if (!triggerInfo.empty()) AddComponent<TriggerComponent>(triggerInfo);
if (!triggerInfo.empty()) AddComponent<TriggerComponent>(-1, triggerInfo);
/**
* Setup groups
@@ -234,11 +234,11 @@ void Entity::Initialize() {
AddComponent<SimplePhysicsComponent>(simplePhysicsComponentID);
AddComponent<ModelComponent>()->LoadBehaviors();
AddComponent<ModelComponent>(-1)->LoadBehaviors();
AddComponent<RenderComponent>();
AddComponent<RenderComponent>(-1);
auto* destroyableComponent = AddComponent<DestroyableComponent>();
auto* destroyableComponent = AddComponent<DestroyableComponent>(-1);
destroyableComponent->SetHealth(1);
destroyableComponent->SetMaxHealth(1.0f);
destroyableComponent->SetFaction(-1, true);
@@ -254,37 +254,42 @@ void Entity::Initialize() {
*/
if (m_Character && m_Character->GetParentUser()) {
AddComponent<MissionComponent>()->LoadFromXml(m_Character->GetXMLDoc());
AddComponent<MissionComponent>(-1)->LoadFromXml(m_Character->GetXMLDoc());
}
const uint32_t petComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PET);
if (petComponentId > 0) {
AddComponent<PetComponent>(petComponentId);
const auto petComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PET);
if (petComponentID > 0) {
AddComponent<PetComponent>(petComponentID);
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MINI_GAME_CONTROL) > 0) {
AddComponent<MiniGameControlComponent>();
const auto minigameControlID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MINI_GAME_CONTROL);
if (minigameControlID > 0) {
AddComponent<MiniGameControlComponent>(minigameControlID);
}
const uint32_t possessableComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::POSSESSABLE);
if (possessableComponentId > 0) {
AddComponent<PossessableComponent>(possessableComponentId);
const auto possessableComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::POSSESSABLE);
if (possessableComponentID > 0) {
AddComponent<PossessableComponent>(possessableComponentID);
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MODULE_ASSEMBLY) > 0) {
AddComponent<ModuleAssemblyComponent>();
const auto moduleAssemblyID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MODULE_ASSEMBLY);
if (moduleAssemblyID > 0) {
AddComponent<ModuleAssemblyComponent>(moduleAssemblyID);
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RACING_STATS) > 0) {
AddComponent<RacingStatsComponent>();
const auto racingStatsID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RACING_STATS);
if (racingStatsID > 0) {
AddComponent<RacingStatsComponent>(racingStatsID);
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::LUP_EXHIBIT, -1) >= 0) {
AddComponent<LUPExhibitComponent>();
const auto lupExhibitID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::LUP_EXHIBIT, -1);
if (lupExhibitID >= 0) {
AddComponent<LUPExhibitComponent>(lupExhibitID);
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RACING_CONTROL) > 0) {
AddComponent<RacingControlComponent>();
const auto racingControlID =compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RACING_CONTROL);
if (racingControlID > 0) {
AddComponent<RacingControlComponent>(racingControlID);
}
const auto propertyEntranceComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY_ENTRANCE);
@@ -292,7 +297,7 @@ void Entity::Initialize() {
AddComponent<PropertyEntranceComponent>(propertyEntranceComponentID);
}
const int32_t controllablePhysicsComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::CONTROLLABLE_PHYSICS);
const auto controllablePhysicsComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::CONTROLLABLE_PHYSICS);
if (controllablePhysicsComponentID > 0) {
auto* controllablePhysics = AddComponent<ControllablePhysicsComponent>(controllablePhysicsComponentID);
@@ -337,46 +342,48 @@ void Entity::Initialize() {
AddComponent<SimplePhysicsComponent>(simplePhysicsComponentID);
}
const int32_t rigidBodyPhantomPhysicsComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS);
const auto rigidBodyPhantomPhysicsComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS);
if (rigidBodyPhantomPhysicsComponentID > 0) {
AddComponent<RigidbodyPhantomPhysicsComponent>(rigidBodyPhantomPhysicsComponentID);
}
const int32_t phantomPhysicsComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PHANTOM_PHYSICS);
const auto phantomPhysicsComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PHANTOM_PHYSICS);
if (markedAsPhantom || phantomPhysicsComponentID > 0) {
AddComponent<PhantomPhysicsComponent>(phantomPhysicsComponentID)->SetPhysicsEffectActive(false);
}
const int32_t havokVehiclePhysicsComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::HAVOK_VEHICLE_PHYSICS);
const auto havokVehiclePhysicsComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::HAVOK_VEHICLE_PHYSICS);
if (havokVehiclePhysicsComponentID > 0) {
auto* havokVehiclePhysicsComponent = AddComponent<HavokVehiclePhysicsComponent>(havokVehiclePhysicsComponentID);
havokVehiclePhysicsComponent->SetPosition(m_DefaultPosition);
havokVehiclePhysicsComponent->SetRotation(m_DefaultRotation);
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SOUND_TRIGGER, -1) != -1) {
AddComponent<SoundTriggerComponent>();
} else if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RACING_SOUND_TRIGGER, -1) != -1) {
AddComponent<RacingSoundTriggerComponent>();
const auto soundTriggerID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SOUND_TRIGGER, -1);
const auto racingSoundTriggerID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RACING_SOUND_TRIGGER, -1);
if (soundTriggerID > -1) {
AddComponent<SoundTriggerComponent>(soundTriggerID);
} else if (racingSoundTriggerID > -1) {
AddComponent<RacingSoundTriggerComponent>(racingSoundTriggerID);
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BUFF) > 0) {
AddComponent<BuffComponent>();
const auto buffComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BUFF);
if (buffComponentID > 0) {
AddComponent<BuffComponent>(buffComponentID);
}
const int collectibleComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::COLLECTIBLE);
const auto collectibleComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::COLLECTIBLE);
if (collectibleComponentID > 0) {
AddComponent<CollectibleComponent>(GetVarAs<int32_t>(u"collectible_id"));
AddComponent<CollectibleComponent>(collectibleComponentID, GetVarAs<int32_t>(u"collectible_id"));
}
/**
* Multiple components require the destructible component.
*/
const int buffComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BUFF);
const int quickBuildComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::QUICK_BUILD);
const auto quickBuildComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::QUICK_BUILD);
int componentID = -1;
int32_t componentID = -1;
if (collectibleComponentID > 0) componentID = collectibleComponentID;
if (quickBuildComponentID > 0) componentID = quickBuildComponentID;
if (buffComponentID > 0) componentID = buffComponentID;
@@ -384,7 +391,7 @@ void Entity::Initialize() {
bool isSmashable = GetVarAs<int32_t>(u"is_smashable") != 0;
if (buffComponentID > 0 || collectibleComponentID > 0 || isSmashable) {
DestroyableComponent* comp = AddComponent<DestroyableComponent>();
DestroyableComponent* comp = AddComponent<DestroyableComponent>(componentID);
auto* const destCompTable = CDClientManager::GetTable<CDDestructibleComponentTable>();
std::vector<CDDestructibleComponent> destCompData = destCompTable->Query([componentID](const CDDestructibleComponent& entry) { return (entry.id == componentID); });
@@ -473,27 +480,30 @@ void Entity::Initialize() {
}
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::CHARACTER) > 0 || m_Character) {
const auto characterID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::CHARACTER);
if (characterID > 0 || m_Character) {
// Character Component always has a possessor, level, and forced movement components
AddComponent<PossessorComponent>();
AddComponent<PossessorComponent>(characterID);
// load in the xml for the level
AddComponent<LevelProgressionComponent>()->LoadFromXml(m_Character->GetXMLDoc());
AddComponent<LevelProgressionComponent>(characterID)->LoadFromXml(m_Character->GetXMLDoc());
AddComponent<PlayerForcedMovementComponent>();
AddComponent<PlayerForcedMovementComponent>(characterID);
auto& systemAddress = m_Character->GetParentUser() ? m_Character->GetParentUser()->GetSystemAddress() : UNASSIGNED_SYSTEM_ADDRESS;
AddComponent<CharacterComponent>(m_Character, systemAddress)->LoadFromXml(m_Character->GetXMLDoc());
AddComponent<CharacterComponent>(characterID, m_Character, systemAddress)->LoadFromXml(m_Character->GetXMLDoc());
AddComponent<GhostComponent>();
AddComponent<GhostComponent>(characterID);
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::INVENTORY) > 0 || m_Character) {
AddComponent<InventoryComponent>();
const auto inventoryID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::INVENTORY);
if (inventoryID > 0 || m_Character) {
AddComponent<InventoryComponent>(inventoryID);
}
// if this component exists, then we initialize it. it's value is always 0
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MULTI_ZONE_ENTRANCE, -1) != -1) {
AddComponent<MultiZoneEntranceComponent>();
const auto multiZoneEntranceID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MULTI_ZONE_ENTRANCE, -1);
if (multiZoneEntranceID > -1) {
AddComponent<MultiZoneEntranceComponent>(multiZoneEntranceID);
}
/**
@@ -545,7 +555,7 @@ void Entity::Initialize() {
}
if (!scriptName.empty() || client || m_Character || scriptComponentID >= 0) {
AddComponent<ScriptComponent>(scriptName, true, client && scriptName.empty());
AddComponent<ScriptComponent>(scriptComponentID, scriptName, true, client && scriptName.empty());
}
// ZoneControl script
@@ -554,26 +564,27 @@ void Entity::Initialize() {
const CDZoneTable* const zoneData = CDZoneTableTable::Query(zoneID.GetMapID());
if (zoneData != nullptr) {
int zoneScriptID = zoneData->scriptID;
const int32_t zoneScriptID = zoneData->scriptID;
CDScriptComponent zoneScriptData = scriptCompTable->GetByID(zoneScriptID);
AddComponent<ScriptComponent>(zoneScriptData.script_name, true);
AddComponent<ScriptComponent>(zoneScriptID, zoneScriptData.script_name, true, false);
}
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SKILL, -1) != -1 || m_Character) {
AddComponent<SkillComponent>();
const auto skillID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SKILL, -1);
if (skillID > -1 || m_Character) {
AddComponent<SkillComponent>(skillID);
}
const auto combatAiId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BASE_COMBAT_AI);
if (combatAiId > 0) {
AddComponent<BaseCombatAIComponent>(combatAiId);
const auto combatAiID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BASE_COMBAT_AI);
if (combatAiID > 0) {
AddComponent<BaseCombatAIComponent>(combatAiID);
}
if (const int componentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::QUICK_BUILD) > 0) {
auto* const quickBuildComponent = AddComponent<QuickBuildComponent>();
if (quickBuildComponentID > 0) {
auto* const quickBuildComponent = AddComponent<QuickBuildComponent>(quickBuildComponentID);
CDRebuildComponentTable* const rebCompTable = CDClientManager::GetTable<CDRebuildComponentTable>();
const std::vector<CDRebuildComponent> rebCompData = rebCompTable->Query([=](CDRebuildComponent entry) { return (entry.id == quickBuildComponentID); });
const std::vector<CDRebuildComponent> rebCompData = rebCompTable->Query([quickBuildComponentID](CDRebuildComponent entry) { return (entry.id == quickBuildComponentID); });
if (!rebCompData.empty()) {
quickBuildComponent->SetResetTime(rebCompData[0].reset_time);
@@ -618,53 +629,63 @@ void Entity::Initialize() {
}
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SWITCH, -1) != -1) {
AddComponent<SwitchComponent>();
const auto switchID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SWITCH, -1);
if (switchID > -1) {
AddComponent<SwitchComponent>(switchID);
}
if ((compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::VENDOR) > 0)) {
AddComponent<VendorComponent>();
} else if ((compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::DONATION_VENDOR, -1) != -1)) {
AddComponent<DonationVendorComponent>();
} else if ((compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ACHIEVEMENT_VENDOR, -1) != -1)) {
AddComponent<AchievementVendorComponent>();
const auto vendorID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::VENDOR);
const auto donationVendorID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::DONATION_VENDOR, -1);
const auto achievementVendorID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ACHIEVEMENT_VENDOR, -1);
if (vendorID > 0) {
AddComponent<VendorComponent>(vendorID);
} else if (donationVendorID > -1) {
AddComponent<DonationVendorComponent>(donationVendorID);
} else if (achievementVendorID > -1) {
AddComponent<AchievementVendorComponent>(achievementVendorID);
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY_VENDOR, -1) != -1) {
AddComponent<PropertyVendorComponent>();
const auto propertyVendorID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY_VENDOR, -1);
if (propertyVendorID > -1) {
AddComponent<PropertyVendorComponent>(propertyVendorID);
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY_MANAGEMENT, -1) != -1) {
AddComponent<PropertyManagementComponent>();
const auto propertyManagementID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY_MANAGEMENT, -1);
if (propertyManagementID > -1) {
AddComponent<PropertyManagementComponent>(propertyManagementID);
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BOUNCER, -1) != -1) { // you have to determine it like this because all bouncers have a componentID of 0
AddComponent<BouncerComponent>();
const auto bouncerID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BOUNCER, -1);
if (bouncerID > -1) { // you have to determine it like this because all bouncers have a componentID of 0
AddComponent<BouncerComponent>(bouncerID);
}
const int32_t renderComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RENDER);
if ((renderComponentId > 0 && m_TemplateID != 2365) || m_Character) {
AddComponent<RenderComponent>(renderComponentId);
const auto renderComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RENDER);
if ((renderComponentID > 0 && m_TemplateID != 2365) || m_Character) {
AddComponent<RenderComponent>(renderComponentID);
}
if ((compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MISSION_OFFER) > 0) || m_Character) {
AddComponent<MissionOfferComponent>(m_TemplateID);
const auto missionOfferComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MISSION_OFFER, -1);
if (missionOfferComponentID > -1 || m_Character) {
AddComponent<MissionOfferComponent>(missionOfferComponentID);
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BUILD_BORDER, -1) != -1) {
AddComponent<BuildBorderComponent>();
const auto buildBorderID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BUILD_BORDER, -1);
if (buildBorderID > -1) {
AddComponent<BuildBorderComponent>(buildBorderID);
}
// Scripted activity component
const int32_t scriptedActivityID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SCRIPTED_ACTIVITY, -1);
if (scriptedActivityID != -1) {
const auto scriptedActivityID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SCRIPTED_ACTIVITY, -1);
if (scriptedActivityID > -1) {
AddComponent<ScriptedActivityComponent>(scriptedActivityID);
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MODEL, -1) != -1 && !GetComponent<PetComponent>()) {
AddComponent<ModelComponent>()->LoadBehaviors();
const auto modelID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MODEL, -1);
if (modelID > -1 && !GetComponent<PetComponent>()) {
AddComponent<ModelComponent>(modelID)->LoadBehaviors();
if (!HasComponent(eReplicaComponentType::DESTROYABLE)) {
auto* const destroyableComponent = AddComponent<DestroyableComponent>();
auto* const destroyableComponent = AddComponent<DestroyableComponent>(-1);
destroyableComponent->SetHealth(1);
destroyableComponent->SetMaxHealth(1.0f);
destroyableComponent->SetFaction(-1, true);
@@ -672,9 +693,10 @@ void Entity::Initialize() {
}
}
PetComponent* petComponent;
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ITEM) > 0 && !TryGetComponent(eReplicaComponentType::PET, petComponent) && !HasComponent(eReplicaComponentType::MODEL)) {
AddComponent<ItemComponent>();
PetComponent* petComponent{};
const auto itemID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ITEM);
if (itemID > 0 && !TryGetComponent(eReplicaComponentType::PET, petComponent) && !HasComponent(eReplicaComponentType::MODEL)) {
AddComponent<ItemComponent>(itemID);
}
// Shooting gallery component
@@ -683,16 +705,17 @@ void Entity::Initialize() {
AddComponent<ShootingGalleryComponent>(shootingGalleryComponentID);
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY, -1) != -1) {
AddComponent<PropertyComponent>();
const auto propertyID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY, -1);
if (propertyID > -1) {
AddComponent<PropertyComponent>(propertyID);
}
const int rocketId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ROCKET_LAUNCH);
if ((rocketId > 0)) {
AddComponent<RocketLaunchpadControlComponent>(rocketId);
const auto rocketID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ROCKET_LAUNCH);
if ((rocketID > 0)) {
AddComponent<RocketLaunchpadControlComponent>(rocketID);
}
const int32_t railComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RAIL_ACTIVATOR);
const auto railComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RAIL_ACTIVATOR);
if (railComponentID > 0) {
AddComponent<RailActivatorComponent>(railComponentID);
}
@@ -722,9 +745,9 @@ void Entity::Initialize() {
}
}
AddComponent<MovementAIComponent>(moveInfo);
AddComponent<MovementAIComponent>(movementAIID, moveInfo);
}
} else if (petComponentId > 0 || combatAiId > 0 && GetComponent<BaseCombatAIComponent>()->GetTetherSpeed() > 0) {
} else if (petComponentID > 0 || combatAiID > 0 && GetComponent<BaseCombatAIComponent>()->GetTetherSpeed() > 0) {
MovementAIInfo moveInfo{
.movementType = "",
.wanderRadius = 16,
@@ -734,7 +757,7 @@ void Entity::Initialize() {
.wanderDelayMax = 5,
};
AddComponent<MovementAIComponent>(moveInfo);
AddComponent<MovementAIComponent>(-1, moveInfo);
}
const std::string pathName = GetVarAsString(u"attached_path");
@@ -744,10 +767,10 @@ void Entity::Initialize() {
if (path) {
// if we have a moving platform path, then we need a moving platform component
if (path->pathType == PathType::MovingPlatform) {
AddComponent<MovingPlatformComponent>(pathName);
AddComponent<MovingPlatformComponent>(-1, pathName);
} else if (path->pathType == PathType::Movement) {
auto* const movementAIcomponent = GetComponent<MovementAIComponent>();
if (movementAIcomponent && combatAiId == 0) {
if (movementAIcomponent && combatAiID == 0) {
movementAIcomponent->SetPath(pathName);
} else {
MovementAIInfo moveInfo{
@@ -759,24 +782,24 @@ void Entity::Initialize() {
.wanderDelayMax = 5,
};
AddComponent<MovementAIComponent>(moveInfo);
AddComponent<MovementAIComponent>(-1, moveInfo);
}
}
} else {
// else we still need to setup moving platform if it has a moving platform comp but no path
const int32_t movingPlatformComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MOVING_PLATFORM, -1);
if (movingPlatformComponentId >= 0) {
AddComponent<MovingPlatformComponent>(pathName);
const auto movingPlatformComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MOVING_PLATFORM, -1);
if (movingPlatformComponentID >= 0) {
AddComponent<MovingPlatformComponent>(movingPlatformComponentID, pathName);
}
}
const int proximityMonitorID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROXIMITY_MONITOR);
const auto proximityMonitorID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROXIMITY_MONITOR);
if (proximityMonitorID > 0) {
auto* const proxCompTable = CDClientManager::GetTable<CDProximityMonitorComponentTable>();
const auto proxCompData = proxCompTable->Query([proximityMonitorID](const CDProximityMonitorComponent& entry) { return (entry.id == proximityMonitorID); });
if (proxCompData.size() > 0) {
std::vector<std::string> proximityStr = GeneralUtils::SplitString(proxCompData[0].Proximities, ',');
AddComponent<ProximityMonitorComponent>(std::stoi(proximityStr[0]), std::stoi(proximityStr[1]));
AddComponent<ProximityMonitorComponent>(proximityMonitorID, std::stoi(proximityStr[0]), std::stoi(proximityStr[1]));
}
}
@@ -882,12 +905,13 @@ void Entity::Unsubscribe(LWOOBJID scriptObjId, const std::string& notificationNa
void Entity::SetProximityRadius(float proxRadius, std::string name) {
auto* proxMon = GetComponent<ProximityMonitorComponent>();
if (!proxMon) proxMon = AddComponent<ProximityMonitorComponent>();
if (!proxMon) proxMon = AddComponent<ProximityMonitorComponent>(-1);
proxMon->SetProximityRadius(proxRadius, name);
}
void Entity::SetProximityRadius(dpEntity* entity, std::string name) {
ProximityMonitorComponent* proxMon = AddComponent<ProximityMonitorComponent>();
auto* proxMon = GetComponent<ProximityMonitorComponent>();
if (!proxMon) proxMon = AddComponent<ProximityMonitorComponent>(-1);
proxMon->SetProximityRadius(entity, name);
}
@@ -2223,6 +2247,7 @@ bool Entity::MsgRequestServerObjectInfo(GameMessages::GameMsg& msg) {
response.Insert("objectID", std::to_string(m_ObjectID));
response.Insert("serverInfo", true);
GameMessages::GetObjectReportInfo info{};
info.bVerbose = requestInfo.bVerbose;
info.info = response.InsertArray("data");
auto& objectInfo = info.info->PushDebug("Object Details");
auto* table = CDClientManager::GetTable<CDObjectsTable>();
@@ -2236,14 +2261,14 @@ bool Entity::MsgRequestServerObjectInfo(GameMessages::GameMsg& msg) {
auto& componentDetails = objectInfo.PushDebug("Component Information");
for (const auto [id, component] : m_Components) {
componentDetails.PushDebug<AMFStringValue>(StringifiedEnum::ToString(id)) = "";
componentDetails.PushDebug(StringifiedEnum::ToString(id));
}
auto& configData = objectInfo.PushDebug("Config Data");
for (const auto config : m_Settings) {
configData.PushDebug<AMFStringValue>(GeneralUtils::UTF16ToWTF8(config->GetKey())) = config->GetValueAsString();
}
HandleMsg(info);
auto* client = Game::entityManager->GetEntity(requestInfo.clientId);

View File

@@ -87,6 +87,8 @@ void EntityManager::ReloadConfig() {
auto hcXpReduction = Game::config->GetValue("hardcore_uscore_reduction");
m_HardcoreUscoreReduction = hcXpReduction.empty() ? 1.0f : GeneralUtils::TryParse<float>(hcXpReduction).value_or(1.0f);
m_HardcoreMode = GetHardcoreDisabledWorlds().contains(Game::zoneManager->GetZoneID().GetMapID()) ? false : m_HardcoreMode;
auto hcCoinKeep = Game::config->GetValue("hardcore_coin_keep");
m_HardcoreCoinKeep = hcCoinKeep.empty() ? false : GeneralUtils::TryParse<float>(hcCoinKeep).value_or(0.0f);
}
void EntityManager::Initialize() {

View File

@@ -81,6 +81,7 @@ public:
const std::set<LOT>& GetHardcoreUscoreReducedLots() const { return m_HardcoreUscoreReducedLots; };
const std::set<LOT>& GetHardcoreUscoreExcludedEnemies() const { return m_HardcoreUscoreExcludedEnemies; };
const std::set<LWOMAPID>& GetHardcoreDisabledWorlds() const { return m_HardcoreDisabledWorlds; };
float GetHardcoreCoinKeep() const { return m_HardcoreCoinKeep; }
// Messaging
bool SendMessage(GameMessages::GameMsg& msg) const;
@@ -125,6 +126,7 @@ private:
std::set<LOT> m_HardcoreUscoreReducedLots{};
std::set<LOT> m_HardcoreUscoreExcludedEnemies{};
std::set<LWOMAPID> m_HardcoreDisabledWorlds{};
float m_HardcoreCoinKeep{};
};
#endif // ENTITYMANAGER_H

View File

@@ -30,6 +30,7 @@
#include "BitStreamUtils.h"
#include "CheatDetection.h"
#include "CharacterComponent.h"
#include "dConfig.h"
#include "eCharacterVersion.h"
UserManager* UserManager::m_Address = nullptr;
@@ -92,6 +93,23 @@ void UserManager::Initialize() {
StripCR(line);
m_PreapprovedNames.push_back(line);
}
// Initialize cached config values and register a handler to update them on config reload
// This avoids repeated lookups into dConfig at runtime.
if (Game::config) {
m_MuteAutoRejectNames = (Game::config->GetValue("mute_auto_reject_names") == "1");
m_MuteRestrictTrade = (Game::config->GetValue("mute_restrict_trade") == "1");
m_MuteRestrictMail = (Game::config->GetValue("mute_restrict_mail") == "1");
Game::config->AddConfigHandler([this]() {
this->m_MuteAutoRejectNames = (Game::config->GetValue("mute_auto_reject_names") == "1");
this->m_MuteRestrictTrade = (Game::config->GetValue("mute_restrict_trade") == "1");
this->m_MuteRestrictMail = (Game::config->GetValue("mute_restrict_mail") == "1");
});
}
else {
LOG("Warning: dConfig not initialized before UserManager. Cached config values will not be available.");
}
}
UserManager::~UserManager() {
@@ -301,7 +319,9 @@ void UserManager::CreateCharacter(const SystemAddress& sysAddr, Packet* packet)
inStream.Read(eyes);
inStream.Read(mouth);
const auto name = LUWStringName.GetAsString();
const bool autoRejectNames = this->GetMuteAutoRejectNames() && u->GetIsMuted();
const auto name = autoRejectNames ? "" : LUWStringName.GetAsString();
std::string predefinedName = GetPredefinedName(firstNameIndex, middleNameIndex, lastNameIndex);
LOT shirtLOT = FindCharShirtID(shirtColor, shirtStyle);
@@ -319,6 +339,10 @@ void UserManager::CreateCharacter(const SystemAddress& sysAddr, Packet* packet)
return;
}
if (autoRejectNames) {
LOG("AccountID: %i is muted, forcing use of predefined name", u->GetAccountID());
}
if (name.empty()) {
LOG("AccountID: %i is creating a character with predefined name: %s", u->GetAccountID(), predefinedName.c_str());
} else {
@@ -369,6 +393,7 @@ void UserManager::CreateCharacter(const SystemAddress& sysAddr, Packet* packet)
//Check to see if our name was pre-approved:
bool nameOk = IsNamePreapproved(name);
if (!nameOk && u->GetMaxGMLevel() > eGameMasterLevel::FORUM_MODERATOR) nameOk = true;
// If predefined name is invalid, change it to be their object id
@@ -448,9 +473,10 @@ void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet)
LUWString LUWStringName;
inStream.Read(LUWStringName);
const auto newName = LUWStringName.GetAsString();
auto newName = LUWStringName.GetAsString();
Character* character = nullptr;
const bool autoRejectNames = this->GetMuteAutoRejectNames() && u->GetIsMuted();
//Check if this user has this character:
bool ownsCharacter = CheatDetection::VerifyLwoobjidIsSender(
@@ -471,13 +497,30 @@ void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet)
if (!ownsCharacter || !character) {
WorldPackets::SendCharacterRenameResponse(sysAddr, eRenameResponse::UNKNOWN_ERROR);
} else if (ownsCharacter && character) {
if (autoRejectNames) {
// Create a random preapproved name (fallback to default if none available)
if (!m_FirstNames.empty() && !m_MiddleNames.empty() && !m_LastNames.empty()) {
std::string firstName = GeneralUtils::GetRandomElement(m_FirstNames);
std::string middleName = GeneralUtils::GetRandomElement(m_MiddleNames);
std::string lastName = GeneralUtils::GetRandomElement(m_LastNames);
newName = firstName + middleName + lastName;
} else {
newName = "character" + std::to_string(objectID);
}
}
if (newName == character->GetName()) {
WorldPackets::SendCharacterRenameResponse(sysAddr, eRenameResponse::NAME_UNAVAILABLE);
return;
}
if (!Database::Get()->GetCharacterInfo(newName)) {
if (IsNamePreapproved(newName)) {
if (autoRejectNames) {
Database::Get()->SetCharacterName(objectID, newName);
LOG("Character %s auto-renamed to preapproved name %s due to mute", character->GetName().c_str(), newName.c_str());
WorldPackets::SendCharacterRenameResponse(sysAddr, eRenameResponse::SUCCESS);
UserManager::RequestCharacterList(sysAddr);
} else if (IsNamePreapproved(newName)) {
Database::Get()->SetCharacterName(objectID, newName);
LOG("Character %s now known as %s", character->GetName().c_str(), newName.c_str());
WorldPackets::SendCharacterRenameResponse(sysAddr, eRenameResponse::SUCCESS);

View File

@@ -41,6 +41,11 @@ public:
size_t GetUserCount() const { return m_Users.size(); }
// Access cached config values
bool GetMuteAutoRejectNames() const { return m_MuteAutoRejectNames; }
bool GetMuteRestrictTrade() const { return m_MuteRestrictTrade; }
bool GetMuteRestrictMail() const { return m_MuteRestrictMail; }
private:
static UserManager* m_Address; //Singleton
std::map<SystemAddress, User*> m_Users;
@@ -50,6 +55,11 @@ private:
std::vector<std::string> m_MiddleNames;
std::vector<std::string> m_LastNames;
std::vector<std::string> m_PreapprovedNames;
// Cached config values that can change on config reload
bool m_MuteAutoRejectNames = false;
bool m_MuteRestrictTrade = false;
bool m_MuteRestrictMail = false;
};
#endif // USERMANAGER_H

View File

@@ -9,7 +9,7 @@
#include "UserManager.h"
#include "CDMissionsTable.h"
AchievementVendorComponent::AchievementVendorComponent(Entity* parent) : VendorComponent(parent) {
AchievementVendorComponent::AchievementVendorComponent(Entity* parent, const int32_t componentID) : VendorComponent(parent, componentID) {
RefreshInventory(true);
};

View File

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

View File

@@ -30,7 +30,7 @@
#include "CharacterComponent.h"
#include "Amf3.h"
ActivityComponent::ActivityComponent(Entity* parent, int32_t activityID) : Component(parent) {
ActivityComponent::ActivityComponent(Entity* parent, int32_t componentID) : Component(parent, componentID) {
using namespace GameMessages;
RegisterMsg<GetObjectReportInfo>(this, &ActivityComponent::OnGetObjectReportInfo);
/*
@@ -39,8 +39,8 @@ ActivityComponent::ActivityComponent(Entity* parent, int32_t activityID) : Compo
* if activityID is specified and if that column exists in the activities table, update the activity info with that data.
*/
m_ActivityID = activityID;
LoadActivityData(activityID);
m_ActivityID = componentID;
LoadActivityData(componentID);
if (m_Parent->HasVar(u"activityID")) {
m_ActivityID = parent->GetVar<int32_t>(u"activityID");
LoadActivityData(m_ActivityID);

View File

@@ -28,7 +28,7 @@
#include "CDPhysicsComponentTable.h"
#include "dNavMesh.h"
BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id) : Component(parent) {
BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
m_Target = LWOOBJID_EMPTY;
m_DirtyStateOrTarget = true;
m_State = AiState::spawn;
@@ -43,7 +43,7 @@ BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id)
//Grab the aggro information from BaseCombatAI:
auto componentQuery = CDClientDatabase::CreatePreppedStmt(
"SELECT aggroRadius, tetherSpeed, pursuitSpeed, softTetherRadius, hardTetherRadius FROM BaseCombatAIComponent WHERE id = ?;");
componentQuery.bind(1, static_cast<int>(id));
componentQuery.bind(1, static_cast<int>(componentID));
auto componentResult = componentQuery.execQuery();
@@ -111,12 +111,12 @@ BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id)
int32_t collisionGroup = (COLLISION_GROUP_DYNAMIC | COLLISION_GROUP_ENEMY);
CDComponentsRegistryTable* componentRegistryTable = CDClientManager::GetTable<CDComponentsRegistryTable>();
auto componentID = componentRegistryTable->GetByIDAndType(parent->GetLOT(), eReplicaComponentType::CONTROLLABLE_PHYSICS);
const auto controllablePhysicsID = componentRegistryTable->GetByIDAndType(parent->GetLOT(), eReplicaComponentType::CONTROLLABLE_PHYSICS);
CDPhysicsComponentTable* physicsComponentTable = CDClientManager::GetTable<CDPhysicsComponentTable>();
if (physicsComponentTable != nullptr) {
auto* info = physicsComponentTable->GetByID(componentID);
auto* info = physicsComponentTable->GetByID(controllablePhysicsID);
if (info != nullptr) {
collisionGroup = info->bStatic ? COLLISION_GROUP_NEUTRAL : info->collisionGroup;
}

View File

@@ -49,7 +49,7 @@ class BaseCombatAIComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::BASE_COMBAT_AI;
BaseCombatAIComponent(Entity* parentEntity, uint32_t id);
BaseCombatAIComponent(Entity* parentEntity, int32_t componentID);
~BaseCombatAIComponent() override;
void Update(float deltaTime) override;

View File

@@ -9,7 +9,7 @@
#include "BitStream.h"
#include "eTriggerEventType.h"
BouncerComponent::BouncerComponent(Entity* parent) : Component(parent) {
BouncerComponent::BouncerComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
m_PetEnabled = false;
m_PetBouncerEnabled = false;
m_PetSwitchLoaded = false;

View File

@@ -14,7 +14,7 @@ class BouncerComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::BOUNCER;
BouncerComponent(Entity* parentEntity);
BouncerComponent(Entity* parentEntity, const int32_t componentID);
~BouncerComponent() override;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;

View File

@@ -26,7 +26,7 @@ namespace {
};
}
BuffComponent::BuffComponent(Entity* parent) : Component(parent) {
BuffComponent::BuffComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
}
BuffComponent::~BuffComponent() {

View File

@@ -51,7 +51,7 @@ class BuffComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::BUFF;
explicit BuffComponent(Entity* parent);
explicit BuffComponent(Entity* parent, const int32_t componentID);
~BuffComponent();

View File

@@ -9,7 +9,7 @@
#include "Item.h"
#include "PropertyManagementComponent.h"
BuildBorderComponent::BuildBorderComponent(Entity* parent) : Component(parent) {
BuildBorderComponent::BuildBorderComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
}
BuildBorderComponent::~BuildBorderComponent() {

View File

@@ -18,7 +18,7 @@ class BuildBorderComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::BUILD_BORDER;
BuildBorderComponent(Entity* parent);
BuildBorderComponent(Entity* parent, const int32_t componentID);
~BuildBorderComponent() override;
/**

View File

@@ -25,7 +25,7 @@
#include "MessageType/Game.h"
#include <ctime>
CharacterComponent::CharacterComponent(Entity* parent, Character* character, const SystemAddress& systemAddress) : Component(parent) {
CharacterComponent::CharacterComponent(Entity* parent, const int32_t componentID, Character* character, const SystemAddress& systemAddress) : Component(parent, componentID) {
m_Character = character;
m_IsRacing = false;
@@ -70,7 +70,7 @@ bool CharacterComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
for (const auto zoneID : m_VisitedLevels) {
std::stringstream sstream;
sstream << "MapID: " << zoneID.GetMapID() << " CloneID: " << zoneID.GetCloneID();
vl.PushDebug<AMFStringValue>(sstream.str()) = "";
vl.PushDebug(sstream.str());
}
// visited locations
@@ -84,6 +84,30 @@ bool CharacterComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
cmptType.PushDebug<AMFIntValue>("Current Activity Type") = GeneralUtils::ToUnderlying(m_CurrentActivity);
cmptType.PushDebug<AMFDoubleValue>("Property Clone ID") = m_Character->GetPropertyCloneID();
auto& flagCmptType = reportInfo.info->PushDebug("Player Flag");
auto& allFlags = flagCmptType.PushDebug("All flags");
for (const auto& [id, flagChunk] : m_Character->GetPlayerFlags()) {
const auto base = id * 64;
auto flagChunkCopy = flagChunk;
for (int i = 0; i < 64; i++) {
if (static_cast<bool>(flagChunkCopy & 1)) {
const int32_t flagId = base + i;
std::stringstream stream;
stream << "Flag: " << flagId;
allFlags.PushDebug(stream.str());
}
flagChunkCopy >>= 1;
}
}
auto& sessionFlags = flagCmptType.PushDebug("Session Only Flags");
for (const auto flagId : m_Character->GetSessionFlags()) {
std::stringstream stream;
stream << "Flag: " << flagId;
sessionFlags.PushDebug(stream.str());
}
return true;
}
@@ -859,7 +883,7 @@ void CharacterComponent::SendToZone(LWOMAPID zoneId, LWOCLONEID cloneId) const {
character->SetZoneID(zoneID);
character->SetZoneInstance(zoneInstance);
character->SetZoneClone(zoneClone);
characterComponent->SetLastRocketConfig(u"");
characterComponent->AddVisitedLevel(LWOZONEID(zoneID, LWOINSTANCEID_INVALID, zoneClone));

View File

@@ -70,7 +70,7 @@ class CharacterComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::CHARACTER;
CharacterComponent(Entity* parent, Character* character, const SystemAddress& systemAddress);
CharacterComponent(Entity* parent, const int32_t componentID, Character* character, const SystemAddress& systemAddress);
~CharacterComponent() override;
void LoadFromXml(const tinyxml2::XMLDocument& doc) override;

View File

@@ -7,7 +7,7 @@
class CollectibleComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::COLLECTIBLE;
CollectibleComponent(Entity* parentEntity, int32_t collectibleId) : Component(parentEntity), m_CollectibleId(collectibleId) {}
CollectibleComponent(Entity* parentEntity, const int32_t componentID, const int32_t collectibleId) : Component(parentEntity, componentID), m_CollectibleId(collectibleId) {}
int16_t GetCollectibleId() const { return m_CollectibleId; }
void Serialize(RakNet::BitStream& outBitStream, bool isConstruction) override;

View File

@@ -19,7 +19,7 @@ class Entity;
*/
class Component {
public:
Component(Entity* parent) : m_Parent{ parent } {}
Component(Entity* parent, const int32_t componentID) : m_Parent{ parent }, m_ComponentID{componentID} {}
virtual ~Component() = default;
/**
@@ -28,6 +28,8 @@ public:
*/
Entity* GetParent() const { return m_Parent; }
[[nodiscard]] int32_t GetComponentID() const noexcept { return m_ComponentID; }
/**
* Updates the component in the game loop
* @param deltaTime time passed since last update
@@ -70,4 +72,11 @@ protected:
* The entity that owns this component
*/
Entity* m_Parent;
// The component ID, this should never be changed after initialization
// This is used in various different ways
// 1. To identify which entry this component is in its corresponding table
// 2. To mark that an Entity should have the component with no database entry (it will be 0 in this case)
// 3. The component exists implicitly due to design (CollectibleComponent always has a DestructibleComponent accompanying it). In this case the ID will be -1.
const int32_t m_ComponentID;
};

View File

@@ -17,7 +17,7 @@
#include "StringifiedEnum.h"
#include "Amf3.h"
ControllablePhysicsComponent::ControllablePhysicsComponent(Entity* entity, int32_t componentId) : PhysicsComponent(entity, componentId) {
ControllablePhysicsComponent::ControllablePhysicsComponent(Entity* entity, const int32_t componentID) : PhysicsComponent(entity, componentID) {
RegisterMsg(MessageType::Game::GET_OBJECT_REPORT_INFO, this, &ControllablePhysicsComponent::OnGetObjectReportInfo);
m_Velocity = {};

View File

@@ -25,7 +25,7 @@ class ControllablePhysicsComponent : public PhysicsComponent {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::CONTROLLABLE_PHYSICS;
ControllablePhysicsComponent(Entity* entity, int32_t componentId);
ControllablePhysicsComponent(Entity* entity, const int32_t componentID);
~ControllablePhysicsComponent() override;
void Update(float deltaTime) override;

View File

@@ -44,7 +44,7 @@
Implementation<bool, const Entity*> DestroyableComponent::IsEnemyImplentation;
Implementation<bool, const Entity*> DestroyableComponent::IsFriendImplentation;
DestroyableComponent::DestroyableComponent(Entity* parent) : Component(parent) {
DestroyableComponent::DestroyableComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
using namespace GameMessages;
m_iArmor = 0;
m_fMaxArmor = 0.0f;
@@ -786,7 +786,7 @@ void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType
}
} else {
//Check if this zone allows coin drops
if (Game::zoneManager->GetPlayerLoseCoinOnDeath()) {
if (Game::zoneManager->GetPlayerLoseCoinOnDeath() && !Game::entityManager->GetHardcoreMode()) {
auto* character = m_Parent->GetCharacter();
uint64_t coinsTotal = character->GetCoins();
const uint64_t minCoinsToLose = Game::zoneManager->GetWorldConfig().coinsLostOnDeathMin;
@@ -1012,13 +1012,23 @@ void DestroyableComponent::DoHardcoreModeDrops(const LWOOBJID source) {
//get character:
auto* chars = m_Parent->GetCharacter();
if (chars) {
auto coins = chars->GetCoins();
auto oldCoins = chars->GetCoins();
// Floor this so there arent coins generated from rounding
auto coins = static_cast<uint64_t>(oldCoins * Game::entityManager->GetHardcoreCoinKeep());
auto coinsToDrop = oldCoins - coins;
LOG("Player had %llu coins, will lose %i coins to have %i", oldCoins, coinsToDrop, coins);
//lose all coins:
chars->SetCoins(0, eLootSourceType::NONE);
chars->SetCoins(coins, eLootSourceType::NONE);
//drop all coins:
GameMessages::SendDropClientLoot(m_Parent, source, LOT_NULL, coins, m_Parent->GetPosition());
constexpr auto MAX_TO_DROP_PER_GM = 100'000;
while (coinsToDrop > MAX_TO_DROP_PER_GM) {
LOG("Dropping 100,000, %llu left", coinsToDrop);
GameMessages::SendDropClientLoot(m_Parent, source, LOT_NULL, MAX_TO_DROP_PER_GM, m_Parent->GetPosition());
coinsToDrop -= MAX_TO_DROP_PER_GM;
}
GameMessages::SendDropClientLoot(m_Parent, source, LOT_NULL, coinsToDrop, m_Parent->GetPosition());
}
return;
}

View File

@@ -26,7 +26,7 @@ class DestroyableComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::DESTROYABLE;
DestroyableComponent(Entity* parentEntity);
DestroyableComponent(Entity* parentEntity, const int32_t componentID);
~DestroyableComponent() override;
void Update(float deltaTime) override;

View File

@@ -1,7 +1,7 @@
#include "DonationVendorComponent.h"
#include "Database.h"
DonationVendorComponent::DonationVendorComponent(Entity* parent) : VendorComponent(parent) {
DonationVendorComponent::DonationVendorComponent(Entity* parent, const int32_t componentID) : VendorComponent(parent, componentID) {
//LoadConfigData
m_PercentComplete = 0.0;
m_TotalDonated = 0;

View File

@@ -9,7 +9,7 @@ class Entity;
class DonationVendorComponent final : public VendorComponent {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::DONATION_VENDOR;
DonationVendorComponent(Entity* parent);
DonationVendorComponent(Entity* parent, const int32_t componentID);
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
uint32_t GetActivityID() {return m_ActivityId;};
void SubmitDonation(uint32_t count);

View File

@@ -1,6 +1,6 @@
#include "GhostComponent.h"
GhostComponent::GhostComponent(Entity* parent) : Component(parent) {
GhostComponent::GhostComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
m_GhostReferencePoint = NiPoint3Constant::ZERO;
m_GhostOverridePoint = NiPoint3Constant::ZERO;
m_GhostOverride = false;

View File

@@ -10,7 +10,7 @@ class NiPoint3;
class GhostComponent final : public Component {
public:
static inline const eReplicaComponentType ComponentType = eReplicaComponentType::GHOST;
GhostComponent(Entity* parent);
GhostComponent(Entity* parent, const int32_t componentID);
~GhostComponent() override;
void SetGhostOverride(bool value) { m_GhostOverride = value; };

View File

@@ -2,7 +2,7 @@
#include "EntityManager.h"
#include "Amf3.h"
HavokVehiclePhysicsComponent::HavokVehiclePhysicsComponent(Entity* parent, int32_t componentId) : PhysicsComponent(parent, componentId) {
HavokVehiclePhysicsComponent::HavokVehiclePhysicsComponent(Entity* parent, const int32_t componentID) : PhysicsComponent(parent, componentID) {
RegisterMsg(MessageType::Game::GET_OBJECT_REPORT_INFO, this, &HavokVehiclePhysicsComponent::OnGetObjectReportInfo);
m_Velocity = NiPoint3Constant::ZERO;

View File

@@ -13,7 +13,7 @@ class HavokVehiclePhysicsComponent : public PhysicsComponent {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::HAVOK_VEHICLE_PHYSICS;
HavokVehiclePhysicsComponent(Entity* parentEntity, int32_t componentId);
HavokVehiclePhysicsComponent(Entity* parentEntity, const int32_t componentID);
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;

View File

@@ -42,7 +42,7 @@
#include <ranges>
InventoryComponent::InventoryComponent(Entity* parent) : Component(parent) {
InventoryComponent::InventoryComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
this->m_Dirty = true;
this->m_Equipped = {};
this->m_Pushed = {};

View File

@@ -67,7 +67,7 @@ public:
static constexpr uint32_t MaximumGroupCount = 50;
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::INVENTORY;
InventoryComponent(Entity* parent);
InventoryComponent(Entity* parent, const int32_t componentID);
void Update(float deltaTime) override;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;

View File

@@ -8,7 +8,7 @@ class ItemComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::ITEM;
ItemComponent(Entity* entity) : Component(entity) {}
ItemComponent(Entity* entity, const int32_t componentID) : Component(entity, componentID) {}
void Serialize(RakNet::BitStream& bitStream, bool isConstruction) override;
};

View File

@@ -16,7 +16,7 @@ class LUPExhibitComponent final : public Component
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::LUP_EXHIBIT;
LUPExhibitComponent(Entity* parent) : Component(parent) {};
LUPExhibitComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {};
void Update(float deltaTime) override;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
void NextLUPExhibit();

View File

@@ -6,7 +6,7 @@
#include "CDRewardsTable.h"
LevelProgressionComponent::LevelProgressionComponent(Entity* parent) : Component(parent) {
LevelProgressionComponent::LevelProgressionComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
m_Parent = parent;
m_Level = 1;
m_SpeedBase = 500.0f;

View File

@@ -19,7 +19,7 @@ public:
* Constructor for this component
* @param parent parent that contains this component
*/
LevelProgressionComponent(Entity* parent);
LevelProgressionComponent(Entity* parent, const int32_t componentID);
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;

View File

@@ -8,7 +8,7 @@ class MiniGameControlComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::MINI_GAME_CONTROL;
MiniGameControlComponent(Entity* parent) : Component(parent) {}
MiniGameControlComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {}
void Serialize(RakNet::BitStream& outBitStream, bool isConstruction);
};

View File

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

View File

@@ -26,8 +26,11 @@
std::unordered_map<AchievementCacheKey, std::vector<uint32_t>> MissionComponent::m_AchievementCache = {};
//! Initializer
MissionComponent::MissionComponent(Entity* parent) : Component(parent) {
MissionComponent::MissionComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
using namespace GameMessages;
m_LastUsedMissionOrderUID = Game::zoneManager->GetUniqueMissionIdStartingValue();
RegisterMsg<GetObjectReportInfo>(this, &MissionComponent::OnGetObjectReportInfo);
}
//! Destructor
@@ -622,3 +625,111 @@ void MissionComponent::ResetMission(const int32_t missionId) {
m_Missions.erase(missionId);
GameMessages::SendResetMissions(m_Parent, m_Parent->GetSystemAddress(), missionId);
}
void PushMissions(const std::map<uint32_t, Mission*>& missions, AMFArrayValue& V, bool verbose) {
for (const auto& [id, mission] : missions) {
std::stringstream ss;
if (!mission) {
ss << "Mission ID: " << id;
V.PushDebug(ss.str());
} else if (!verbose) {
ss << "%[Missions_" << id << "_name]" << ", Mission ID";
V.PushDebug<AMFIntValue>(ss.str()) = id;
} else {
ss << "%[Missions_" << id << "_name]" << ", Mission ID: " << id;
auto& missionV = V.PushDebug(ss.str());
auto& missionInformation = missionV.PushDebug("Mission Information");
if (mission->IsComplete()) {
missionInformation.PushDebug<AMFStringValue>("Time mission last completed") = std::to_string(mission->GetTimestamp());
missionInformation.PushDebug<AMFIntValue>("Number of times completed") = mission->GetCompletions();
}
// Expensive to network this especially when its read from the client anyways
// missionInformation.PushDebug("Description").PushDebug("None");
// missionInformation.PushDebug("Text").PushDebug("None");
auto& statusInfo = missionInformation.PushDebug("Mission statuses for local player");
if (mission->IsAvalible()) statusInfo.PushDebug("Available");
if (mission->IsActive()) statusInfo.PushDebug("Active");
if (mission->IsReadyToComplete()) statusInfo.PushDebug("Ready To Complete");
if (mission->IsComplete()) statusInfo.PushDebug("Completed");
if (mission->IsFailed()) statusInfo.PushDebug("Failed");
const auto& clientInfo = mission->GetClientInfo();
statusInfo.PushDebug<AMFBoolValue>("Is an achievement mission") = mission->IsAchievement();
statusInfo.PushDebug<AMFBoolValue>("Is an timed mission") = clientInfo.time_limit > 0;
auto& taskInfo = statusInfo.PushDebug("Task Info");
taskInfo.PushDebug<AMFIntValue>("Number of tasks in this mission") = mission->GetTasks().size();
int32_t i = 0;
for (const auto* task : mission->GetTasks()) {
auto& thisTask = taskInfo.PushDebug("Task " + std::to_string(i));
// Expensive to network this especially when its read from the client anyways
// thisTask.PushDebug("Description").PushDebug("%[MissionTasks_" + taskUidStr + "_description]");
thisTask.PushDebug<AMFIntValue>("Number done") = std::min(task->GetProgress(), static_cast<uint32_t>(task->GetClientInfo().targetValue));
thisTask.PushDebug<AMFIntValue>("Number total needed") = task->GetClientInfo().targetValue;
thisTask.PushDebug<AMFIntValue>("Task Type") = task->GetClientInfo().taskType;
i++;
}
// auto& chatText = missionInformation.PushDebug("Chat Text for Mission States");
// Expensive to network this especially when its read from the client anyways
// chatText.PushDebug("Available Text").PushDebug("%[MissionText_" + idStr + "_chat_state_1]");
// chatText.PushDebug("Active Text").PushDebug("%[MissionText_" + idStr + "_chat_state_2]");
// chatText.PushDebug("Ready-to-Complete Text").PushDebug("%[MissionText_" + idStr + "_chat_state_3]");
// chatText.PushDebug("Complete Text").PushDebug("%[MissionText_" + idStr + "_chat_state_4]");
if (clientInfo.time_limit > 0) {
missionInformation.PushDebug<AMFIntValue>("Time Limit") = clientInfo.time_limit;
missionInformation.PushDebug<AMFDoubleValue>("Time Remaining") = 0;
}
if (clientInfo.offer_objectID != -1) {
missionInformation.PushDebug<AMFIntValue>("Offer Object LOT") = clientInfo.offer_objectID;
}
if (clientInfo.target_objectID != -1) {
missionInformation.PushDebug<AMFIntValue>("Complete Object LOT") = clientInfo.target_objectID;
}
if (!clientInfo.prereqMissionID.empty()) {
missionInformation.PushDebug<AMFStringValue>("Requirement Mission IDs") = clientInfo.prereqMissionID;
}
missionInformation.PushDebug<AMFBoolValue>("Is Repeatable") = clientInfo.repeatable;
const bool hasNoOfferer = clientInfo.offer_objectID == -1 || clientInfo.offer_objectID == 0;
const bool hasNoCompleter = clientInfo.target_objectID == -1 || clientInfo.target_objectID == 0;
missionInformation.PushDebug<AMFBoolValue>("Is Achievement") = hasNoOfferer && hasNoCompleter;
}
}
}
bool MissionComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
auto& reportMsg = static_cast<GameMessages::GetObjectReportInfo&>(msg);
auto& missionInfo = reportMsg.info->PushDebug("Mission (Laggy)");
missionInfo.PushDebug<AMFIntValue>("Component ID") = GetComponentID();
// Sort the missions so they are easier to parse and present to the end user
std::map<uint32_t, Mission*> achievements;
std::map<uint32_t, Mission*> missions;
std::map<uint32_t, Mission*> doneMissions;
for (const auto [id, mission] : m_Missions) {
if (!mission) continue;
else if (mission->IsComplete()) doneMissions[id] = mission;
else if (mission->IsAchievement()) achievements[id] = mission;
else if (mission->IsMission()) missions[id] = mission;
}
// None of these should be empty, but if they are dont print the field
if (!achievements.empty() || !missions.empty()) {
auto& incompleteMissions = missionInfo.PushDebug("Incomplete Missions");
PushMissions(achievements, incompleteMissions, reportMsg.bVerbose);
PushMissions(missions, incompleteMissions, reportMsg.bVerbose);
}
if (!doneMissions.empty()) {
auto& completeMissions = missionInfo.PushDebug("Completed Missions");
PushMissions(doneMissions, completeMissions, reportMsg.bVerbose);
}
return true;
}

View File

@@ -28,7 +28,7 @@ class MissionComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::MISSION;
explicit MissionComponent(Entity* parent);
explicit MissionComponent(Entity* parent, const int32_t componentID);
~MissionComponent() override;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate, unsigned int& flags);
void LoadFromXml(const tinyxml2::XMLDocument& doc) override;
@@ -171,6 +171,7 @@ public:
void ResetMission(const int32_t missionId);
private:
bool OnGetObjectReportInfo(GameMessages::GameMsg& msg);
/**
* All the missions owned by this entity, mapped by mission ID
*/

View File

@@ -39,19 +39,13 @@ bool OfferedMission::GetAcceptsMission() const {
//------------------------ MissionOfferComponent below ------------------------
MissionOfferComponent::MissionOfferComponent(Entity* parent, const LOT parentLot) : Component(parent) {
auto* compRegistryTable = CDClientManager::GetTable<CDComponentsRegistryTable>();
auto value = compRegistryTable->GetByIDAndType(parentLot, eReplicaComponentType::MISSION_OFFER, -1);
if (value != -1) {
const uint32_t componentId = value;
MissionOfferComponent::MissionOfferComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
if (componentID != -1) {
// Now lookup the missions in the MissionNPCComponent table
auto* missionNpcComponentTable = CDClientManager::GetTable<CDMissionNPCComponentTable>();
auto missions = missionNpcComponentTable->Query([=](const CDMissionNPCComponent& entry) {
return entry.id == static_cast<unsigned>(componentId);
auto missions = missionNpcComponentTable->Query([componentID](const CDMissionNPCComponent& entry) {
return entry.id == static_cast<unsigned>(componentID);
});
for (auto& mission : missions) {

View File

@@ -63,7 +63,7 @@ class MissionOfferComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::MISSION_OFFER;
MissionOfferComponent(Entity* parent, LOT parentLot);
MissionOfferComponent(Entity* parent, const int32_t componentID);
/**
* Handles the OnUse event triggered by some entity, determines which missions to show based on what they may

View File

@@ -14,7 +14,7 @@
#include "Database.h"
#include "DluAssert.h"
ModelComponent::ModelComponent(Entity* parent) : Component(parent) {
ModelComponent::ModelComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
using namespace GameMessages;
m_OriginalPosition = m_Parent->GetDefaultPosition();
m_OriginalRotation = m_Parent->GetDefaultRotation();

View File

@@ -27,7 +27,7 @@ class ModelComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::MODEL;
ModelComponent(Entity* parent);
ModelComponent(Entity* parent, const int32_t componentID);
void LoadBehaviors();
void Update(float deltaTime) override;

View File

@@ -1,6 +1,6 @@
#include "ModuleAssemblyComponent.h"
ModuleAssemblyComponent::ModuleAssemblyComponent(Entity* parent) : Component(parent) {
ModuleAssemblyComponent::ModuleAssemblyComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
m_SubKey = LWOOBJID_EMPTY;
m_UseOptionalParts = false;
m_AssemblyPartsLOTs = u"";

View File

@@ -14,7 +14,7 @@ class ModuleAssemblyComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::MODULE_ASSEMBLY;
ModuleAssemblyComponent(Entity* parent);
ModuleAssemblyComponent(Entity* parent, const int32_t componentID);
~ModuleAssemblyComponent() override;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;

View File

@@ -26,7 +26,7 @@ namespace {
std::map<LOT, float> m_PhysicsSpeedCache;
}
MovementAIComponent::MovementAIComponent(Entity* parent, MovementAIInfo info) : Component(parent) {
MovementAIComponent::MovementAIComponent(Entity* parent, const int32_t componentID, MovementAIInfo info) : Component(parent, componentID) {
m_Info = info;
m_AtFinalWaypoint = true;

View File

@@ -62,7 +62,7 @@ class MovementAIComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::MOVEMENT_AI;
MovementAIComponent(Entity* parentEntity, MovementAIInfo info);
MovementAIComponent(Entity* parentEntity, const int32_t componentID, MovementAIInfo info);
void SetPath(const std::string pathName);

View File

@@ -55,7 +55,7 @@ void MoverSubComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsIniti
//------------- MovingPlatformComponent below --------------
MovingPlatformComponent::MovingPlatformComponent(Entity* parent, const std::string& pathName) : Component(parent) {
MovingPlatformComponent::MovingPlatformComponent(Entity* parent, const int32_t componentID, const std::string& pathName) : Component(parent, componentID) {
m_MoverSubComponentType = eMoverSubComponentType::mover;
m_MoverSubComponent = new MoverSubComponent(m_Parent->GetDefaultPosition());
m_PathName = GeneralUtils::ASCIIToUTF16(pathName);

View File

@@ -108,7 +108,7 @@ class MovingPlatformComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::MOVING_PLATFORM;
MovingPlatformComponent(Entity* parent, const std::string& pathName);
MovingPlatformComponent(Entity* parent, const int32_t componentID, const std::string& pathName);
~MovingPlatformComponent() override;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;

View File

@@ -3,7 +3,7 @@
#include "InventoryComponent.h"
#include "CharacterComponent.h"
MultiZoneEntranceComponent::MultiZoneEntranceComponent(Entity* parent) : Component(parent) {
MultiZoneEntranceComponent::MultiZoneEntranceComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
m_Parent = parent;
std::string zoneString = GeneralUtils::UTF16ToWTF8(m_Parent->GetVar<std::u16string>(u"MultiZoneIDs"));
std::stringstream ss(zoneString);

View File

@@ -16,7 +16,7 @@ public:
* Constructor for this component, builds the m_LUPWorlds vector
* @param parent parent that contains this component
*/
MultiZoneEntranceComponent(Entity* parent);
MultiZoneEntranceComponent(Entity* parent, const int32_t componentID);
~MultiZoneEntranceComponent() override;
/**

View File

@@ -10,9 +10,11 @@
#include "InventoryComponent.h"
#include "Item.h"
#include "MissionComponent.h"
#include "User.h"
#include "SwitchComponent.h"
#include "DestroyableComponent.h"
#include "dpWorld.h"
#include "UserManager.h"
#include "PetDigServer.h"
#include "ObjectIDManager.h"
#include "eUnequippableActiveType.h"
@@ -21,6 +23,7 @@
#include "eUseItemResponse.h"
#include "ePlayerFlag.h"
#include "GeneralUtils.h"
#include "Game.h"
#include "dConfig.h"
#include "dChatFilter.h"
@@ -43,9 +46,8 @@ std::unordered_map<LWOOBJID, LWOOBJID> PetComponent::activePets{};
* while the faction ones could be checked using their respective missions.
*/
PetComponent::PetComponent(Entity* parentEntity, uint32_t componentId) : Component{ parentEntity } {
m_PetInfo = CDClientManager::GetTable<CDPetComponentTable>()->GetByID(componentId); // TODO: Make reference when safe
m_ComponentId = componentId;
PetComponent::PetComponent(Entity* parentEntity, const int32_t componentID) : Component{ parentEntity, componentID } {
m_PetInfo = CDClientManager::GetTable<CDPetComponentTable>()->GetByID(componentID); // TODO: Make reference when safe
m_Interaction = LWOOBJID_EMPTY;
m_Owner = LWOOBJID_EMPTY;
@@ -537,7 +539,7 @@ void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) {
// Triggers the catch a pet missions
constexpr auto PET_FLAG_BASE = 800;
tamer->GetCharacter()->SetPlayerFlag(PET_FLAG_BASE + m_ComponentId, true);
tamer->GetCharacter()->SetPlayerFlag(PET_FLAG_BASE + m_ComponentID, true);
auto* missionComponent = tamer->GetComponent<MissionComponent>();
@@ -554,18 +556,29 @@ void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) {
}
void PetComponent::RequestSetPetName(std::u16string name) {
const bool autoRejectNames = UserManager::Instance()->GetMuteAutoRejectNames();
if (m_Tamer == LWOOBJID_EMPTY) {
if (m_Owner != LWOOBJID_EMPTY) {
auto* owner = GetOwner();
m_ModerationStatus = 1; // Pending
m_Name = "";
// If auto reject names is on, and the user is muted, force use of predefined name
if (autoRejectNames && owner && owner->GetCharacter() && owner->GetCharacter()->GetParentUser()->GetIsMuted()) {
m_ModerationStatus = 2; // Approved
std::string forcedName = "Pet";
Database::Get()->SetPetNameModerationStatus(m_DatabaseId, IPetNames::Info{ forcedName, static_cast<int32_t>(m_ModerationStatus) });
GameMessages::SendSetPetName(m_Owner, GeneralUtils::UTF8ToUTF16(m_Name), m_DatabaseId, owner->GetSystemAddress());
GameMessages::SendSetPetNameModerated(m_Owner, m_DatabaseId, m_ModerationStatus, owner->GetSystemAddress());
} else {
m_ModerationStatus = 1; // Pending
m_Name = "";
//Save our pet's new name to the db:
SetPetNameForModeration(GeneralUtils::UTF16ToWTF8(name));
//Save our pet's new name to the db:
SetPetNameForModeration(GeneralUtils::UTF16ToWTF8(name));
GameMessages::SendSetPetName(m_Owner, GeneralUtils::UTF8ToUTF16(m_Name), m_DatabaseId, owner->GetSystemAddress());
GameMessages::SendSetPetNameModerated(m_Owner, m_DatabaseId, m_ModerationStatus, owner->GetSystemAddress());
GameMessages::SendSetPetName(m_Owner, GeneralUtils::UTF8ToUTF16(m_Name), m_DatabaseId, owner->GetSystemAddress());
GameMessages::SendSetPetNameModerated(m_Owner, m_DatabaseId, m_ModerationStatus, owner->GetSystemAddress());
}
}
return;
@@ -587,11 +600,21 @@ void PetComponent::RequestSetPetName(std::u16string name) {
return;
}
m_ModerationStatus = 1; // Pending
m_Name = "";
// If auto reject names is on, and the user is muted, force use of predefined name ELSE proceed with normal name check
if (autoRejectNames && tamer->GetCharacter() && tamer->GetCharacter()->GetParentUser()->GetIsMuted()) {
m_ModerationStatus = 2; // Approved
m_Name = "";
std::string forcedName = "Pet";
//Save our pet's new name to the db:
SetPetNameForModeration(GeneralUtils::UTF16ToWTF8(name));
Database::Get()->SetPetNameModerationStatus(m_DatabaseId, IPetNames::Info{ forcedName, static_cast<int32_t>(m_ModerationStatus) });
LOG("AccountID: %i is muted, forcing use of predefined pet name", tamer->GetCharacter()->GetParentUser()->GetAccountID());
} else {
m_ModerationStatus = 1; // Pending
m_Name = "";
//Save our pet's new name to the db:
SetPetNameForModeration(GeneralUtils::UTF16ToWTF8(name));
}
Game::entityManager->SerializeEntity(m_Parent);

View File

@@ -18,7 +18,7 @@ class PetComponent final : public Component
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::PET;
explicit PetComponent(Entity* parentEntity, uint32_t componentId);
explicit PetComponent(Entity* parentEntity, const int32_t componentID);
~PetComponent() override;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
@@ -250,11 +250,6 @@ private:
*/
static std::unordered_map<LWOOBJID, LWOOBJID> currentActivities;
/**
* The ID of the component in the pet component table
*/
uint32_t m_ComponentId;
/**
* The ID of the model that was built to complete the taming minigame for this pet
*/

View File

@@ -28,7 +28,7 @@
#include "dpShapeBox.h"
#include "dpShapeSphere.h"
PhantomPhysicsComponent::PhantomPhysicsComponent(Entity* parent, int32_t componentId) : PhysicsComponent(parent, componentId) {
PhantomPhysicsComponent::PhantomPhysicsComponent(Entity* parent, const int32_t componentID) : PhysicsComponent(parent, componentID) {
RegisterMsg(MessageType::Game::GET_OBJECT_REPORT_INFO, this, &PhantomPhysicsComponent::OnGetObjectReportInfo);
m_Position = m_Parent->GetDefaultPosition();

View File

@@ -28,7 +28,7 @@ class PhantomPhysicsComponent final : public PhysicsComponent {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::PHANTOM_PHYSICS;
PhantomPhysicsComponent(Entity* parent, int32_t componentId);
PhantomPhysicsComponent(Entity* parent, const int32_t componentID);
~PhantomPhysicsComponent() override;
void Update(float deltaTime) override;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;

View File

@@ -15,7 +15,7 @@
#include "EntityInfo.h"
#include "Amf3.h"
PhysicsComponent::PhysicsComponent(Entity* parent, int32_t componentId) : Component(parent) {
PhysicsComponent::PhysicsComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
m_Position = NiPoint3Constant::ZERO;
m_Rotation = QuatUtils::IDENTITY;
m_DirtyPosition = false;
@@ -23,7 +23,7 @@ PhysicsComponent::PhysicsComponent(Entity* parent, int32_t componentId) : Compon
CDPhysicsComponentTable* physicsComponentTable = CDClientManager::GetTable<CDPhysicsComponentTable>();
if (physicsComponentTable) {
auto* info = physicsComponentTable->GetByID(componentId);
auto* info = physicsComponentTable->GetByID(componentID);
if (info) {
m_CollisionGroup = info->collisionGroup;
}

View File

@@ -19,7 +19,7 @@ class dpEntity;
class PhysicsComponent : public Component {
public:
PhysicsComponent(Entity* parent, int32_t componentId);
PhysicsComponent(Entity* parent, const int32_t componentID);
virtual ~PhysicsComponent() = default;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;

View File

@@ -1,6 +1,6 @@
#include "PlayerForcedMovementComponent.h"
PlayerForcedMovementComponent::PlayerForcedMovementComponent(Entity* parent) : Component(parent) {
PlayerForcedMovementComponent::PlayerForcedMovementComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
m_Parent = parent;
}

View File

@@ -16,7 +16,7 @@ public:
* Constructor for this component
* @param parent parent that contains this component
*/
PlayerForcedMovementComponent(Entity* parent);
PlayerForcedMovementComponent(Entity* parent, const int32_t componentID);
~PlayerForcedMovementComponent() override;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;

View File

@@ -4,7 +4,7 @@
#include "Inventory.h"
#include "Item.h"
PossessableComponent::PossessableComponent(Entity* parent, uint32_t componentId) : Component(parent) {
PossessableComponent::PossessableComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
m_Possessor = LWOOBJID_EMPTY;
CDItemComponent item = Inventory::FindItemComponent(m_Parent->GetLOT());
m_AnimationFlag = static_cast<eAnimationFlags>(item.animationFlag);
@@ -12,7 +12,7 @@ PossessableComponent::PossessableComponent(Entity* parent, uint32_t componentId)
// Get the possession Type from the CDClient
auto query = CDClientDatabase::CreatePreppedStmt("SELECT possessionType, depossessOnHit FROM PossessableComponent WHERE id = ?;");
query.bind(1, static_cast<int>(componentId));
query.bind(1, static_cast<int>(componentID));
auto result = query.execQuery();

View File

@@ -16,15 +16,10 @@ class PossessableComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::POSSESSABLE;
PossessableComponent(Entity* parentEntity, uint32_t componentId);
PossessableComponent(Entity* parentEntity, const int32_t componentID);
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
/**
* @brief mounts the Entity
*/
void Mount();
/**
* @brief dismounts the Entity
*/

View File

@@ -7,7 +7,7 @@
#include "eControlScheme.h"
#include "eStateChangeType.h"
PossessorComponent::PossessorComponent(Entity* parent) : Component(parent) {
PossessorComponent::PossessorComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
m_Possessable = LWOOBJID_EMPTY;
}

View File

@@ -20,7 +20,7 @@ class PossessorComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::POSSESSOR;
PossessorComponent(Entity* parent);
PossessorComponent(Entity* parent, const int32_t componentID);
~PossessorComponent() override;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;

View File

@@ -16,7 +16,7 @@
class PropertyComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY;
explicit PropertyComponent(Entity* const parentEntity) noexcept : Component{ parentEntity } {}
explicit PropertyComponent(Entity* const parentEntity, const int32_t componentID) noexcept : Component{ parentEntity, componentID } {}
};
#endif // !PROPERTYCOMPONENT_H

View File

@@ -17,7 +17,7 @@
#include "ePropertySortType.h"
#include "User.h"
PropertyEntranceComponent::PropertyEntranceComponent(Entity* parent, uint32_t componentID) : Component(parent) {
PropertyEntranceComponent::PropertyEntranceComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
this->propertyQueries = {};
auto table = CDClientManager::GetTable<CDPropertyEntranceComponentTable>();

View File

@@ -13,7 +13,7 @@
*/
class PropertyEntranceComponent final : public Component {
public:
explicit PropertyEntranceComponent(Entity* parent, uint32_t componentID);
explicit PropertyEntranceComponent(Entity* parent, const int32_t componentID);
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY_ENTRANCE;
/**

View File

@@ -30,7 +30,7 @@
PropertyManagementComponent* PropertyManagementComponent::instance = nullptr;
PropertyManagementComponent::PropertyManagementComponent(Entity* parent) : Component(parent) {
PropertyManagementComponent::PropertyManagementComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
this->owner = LWOOBJID_EMPTY;
this->templateId = 0;
this->propertyId = LWOOBJID_EMPTY;

View File

@@ -31,7 +31,7 @@ enum class PropertyPrivacyOption {
class PropertyManagementComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY_MANAGEMENT;
PropertyManagementComponent(Entity* parent);
PropertyManagementComponent(Entity* parent, const int32_t componentID);
static PropertyManagementComponent* Instance();
/**

View File

@@ -10,7 +10,7 @@
#include "PropertyManagementComponent.h"
#include "UserManager.h"
PropertyVendorComponent::PropertyVendorComponent(Entity* parent) : Component(parent) {
PropertyVendorComponent::PropertyVendorComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
}
void PropertyVendorComponent::OnUse(Entity* originator) {

View File

@@ -10,7 +10,7 @@
class PropertyVendorComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY_VENDOR;
explicit PropertyVendorComponent(Entity* parent);
explicit PropertyVendorComponent(Entity* parent, const int32_t componentID);
/**
* Handles a use event from some entity, if the property is cleared this allows the entity to claim it

View File

@@ -7,7 +7,7 @@
const std::unordered_set<LWOOBJID> ProximityMonitorComponent::m_EmptyObjectSet = {};
ProximityMonitorComponent::ProximityMonitorComponent(Entity* parent, int radiusSmall, int radiusLarge) : Component(parent) {
ProximityMonitorComponent::ProximityMonitorComponent(Entity* parent, const int32_t componentID, int radiusSmall, int radiusLarge) : Component(parent, componentID) {
if (radiusSmall != -1 && radiusLarge != -1) {
SetProximityRadius(radiusSmall, "rocketSmall");
SetProximityRadius(radiusLarge, "rocketLarge");

View File

@@ -23,7 +23,7 @@ class ProximityMonitorComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::PROXIMITY_MONITOR;
ProximityMonitorComponent(Entity* parentEntity, int smallRadius = -1, int largeRadius = -1);
ProximityMonitorComponent(Entity* parentEntity, const int32_t componentID, int smallRadius = -1, int largeRadius = -1);
~ProximityMonitorComponent() override;
void Update(float deltaTime) override;

View File

@@ -23,7 +23,7 @@
#include "CppScripts.h"
QuickBuildComponent::QuickBuildComponent(Entity* const entity) : Component{ entity } {
QuickBuildComponent::QuickBuildComponent(Entity* const entity, const int32_t componentID) : Component{ entity, componentID } {
std::u16string checkPreconditions = entity->GetVar<std::u16string>(u"CheckPrecondition");
if (!checkPreconditions.empty()) {

View File

@@ -24,7 +24,7 @@ class QuickBuildComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::QUICK_BUILD;
QuickBuildComponent(Entity* const entity);
QuickBuildComponent(Entity* const entity, const int32_t componentID);
~QuickBuildComponent() override;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;

View File

@@ -32,8 +32,8 @@
#define M_PI 3.14159265358979323846264338327950288
#endif
RacingControlComponent::RacingControlComponent(Entity* parent)
: Component(parent) {
RacingControlComponent::RacingControlComponent(Entity* parent, const int32_t componentID)
: Component(parent, componentID) {
m_PathName = u"MainPath";
m_NumberOfLaps = 3;
m_RemainingLaps = m_NumberOfLaps;

View File

@@ -108,7 +108,7 @@ class RacingControlComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::RACING_CONTROL;
RacingControlComponent(Entity* parentEntity);
RacingControlComponent(Entity* parentEntity, const int32_t componentID);
~RacingControlComponent();
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;

View File

@@ -9,7 +9,7 @@ class Entity;
class RacingSoundTriggerComponent : public SoundTriggerComponent {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::RACING_SOUND_TRIGGER;
RacingSoundTriggerComponent(Entity* parent) : SoundTriggerComponent(parent){};
RacingSoundTriggerComponent(Entity* parent, const int32_t componentID) : SoundTriggerComponent(parent, componentID){};
};
#endif //!__RACINGSOUNDTRIGGERCOMPONENT__H__

View File

@@ -8,7 +8,7 @@ class RacingStatsComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::RACING_STATS;
RacingStatsComponent(Entity* parent) : Component(parent) {}
RacingStatsComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {}
};
#endif //!__RACINGSTATSCOMPONENT__H__

View File

@@ -11,9 +11,8 @@
#include "EntityManager.h"
#include "eStateChangeType.h"
RailActivatorComponent::RailActivatorComponent(Entity* parent, int32_t componentID) : Component(parent) {
m_ComponentID = componentID;
const auto tableData = CDClientManager::GetTable<CDRailActivatorComponentTable>()->GetEntryByID(componentID);;
RailActivatorComponent::RailActivatorComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
const auto tableData = CDClientManager::GetTable<CDRailActivatorComponentTable>()->GetEntryByID(componentID);
m_Path = parent->GetVar<std::u16string>(u"rail_path");
m_PathDirection = parent->GetVar<bool>(u"rail_path_direction");

View File

@@ -12,7 +12,7 @@
*/
class RailActivatorComponent final : public Component {
public:
explicit RailActivatorComponent(Entity* parent, int32_t componentID);
explicit RailActivatorComponent(Entity* parent, const int32_t componentID);
~RailActivatorComponent() override;
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::RAIL_ACTIVATOR;
@@ -37,12 +37,6 @@ public:
*/
void OnCancelRailMovement(Entity* originator);
private:
/**
* The ID of this component in the components database
*/
int32_t m_ComponentID;
/**
* The entities that are currently traversing the rail
*/

View File

@@ -16,12 +16,12 @@
std::unordered_map<int32_t, float> RenderComponent::m_DurationCache{};
RenderComponent::RenderComponent(Entity* const parentEntity, const int32_t componentId) : Component{ parentEntity } {
RenderComponent::RenderComponent(Entity* const parentEntity, const int32_t componentID) : Component{ parentEntity, componentID } {
m_LastAnimationName = "";
if (componentId == -1) return;
if (componentID == -1) return;
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM RenderComponent WHERE id = ?;");
query.bind(1, componentId);
query.bind(1, componentID);
auto result = query.execQuery();
if (!result.eof()) {

View File

@@ -63,7 +63,7 @@ class RenderComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::RENDER;
RenderComponent(Entity* const parentEntity, const int32_t componentId = -1);
RenderComponent(Entity* const parentEntity, const int32_t componentID);
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
void Update(float deltaTime) override;

View File

@@ -13,7 +13,7 @@
#include "EntityInfo.h"
#include "Amf3.h"
RigidbodyPhantomPhysicsComponent::RigidbodyPhantomPhysicsComponent(Entity* parent, int32_t componentId) : PhysicsComponent(parent, componentId) {
RigidbodyPhantomPhysicsComponent::RigidbodyPhantomPhysicsComponent(Entity* parent, const int32_t componentID) : PhysicsComponent(parent, componentID) {
RegisterMsg(MessageType::Game::GET_OBJECT_REPORT_INFO, this, &RigidbodyPhantomPhysicsComponent::OnGetObjectReportInfo);
m_Position = m_Parent->GetDefaultPosition();

View File

@@ -21,7 +21,7 @@ class RigidbodyPhantomPhysicsComponent : public PhysicsComponent {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS;
RigidbodyPhantomPhysicsComponent(Entity* parent, int32_t componentId);
RigidbodyPhantomPhysicsComponent(Entity* parent, const int32_t componentID);
void Update(const float deltaTime) override;

View File

@@ -20,10 +20,10 @@
#include "ServiceType.h"
#include "MessageType/Master.h"
RocketLaunchpadControlComponent::RocketLaunchpadControlComponent(Entity* parent, int rocketId) : Component(parent) {
RocketLaunchpadControlComponent::RocketLaunchpadControlComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
auto query = CDClientDatabase::CreatePreppedStmt(
"SELECT targetZone, defaultZoneID, targetScene, altLandingPrecondition, altLandingSpawnPointName FROM RocketLaunchpadControlComponent WHERE id = ?;");
query.bind(1, rocketId);
query.bind(1, componentID);
auto result = query.execQuery();

View File

@@ -20,7 +20,7 @@ class RocketLaunchpadControlComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::ROCKET_LAUNCH;
RocketLaunchpadControlComponent(Entity* parent, int rocketId);
RocketLaunchpadControlComponent(Entity* parent, const int32_t componentID);
~RocketLaunchpadControlComponent() override;
/**

View File

@@ -8,9 +8,8 @@
#include "GameMessages.h"
#include "Amf3.h"
ScriptComponent::ScriptComponent(Entity* parent, const std::string& scriptName, bool serialized, bool client) : Component(parent) {
ScriptComponent::ScriptComponent(Entity* parent, const int32_t componentID, const std::string& scriptName, bool serialized, bool client) : Component(parent, componentID) {
using namespace GameMessages;
m_Serialized = serialized;
m_Client = client;
m_ScriptName = scriptName;

View File

@@ -21,7 +21,7 @@ class ScriptComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::SCRIPT;
ScriptComponent(Entity* parent, const std::string& scriptName, bool serialized, bool client = false);
ScriptComponent(Entity* parent, const int32_t componentID, const std::string& scriptName, bool serialized, bool client = false);
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;

View File

@@ -9,7 +9,7 @@ class Entity;
class ScriptedActivityComponent final : public ActivityComponent {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::SCRIPTED_ACTIVITY;
ScriptedActivityComponent(Entity* parent, int activityID) : ActivityComponent(parent, activityID){};
ScriptedActivityComponent(Entity* parent, const int32_t componentID) : ActivityComponent(parent, componentID){};
};
#endif //!__SCRIPTEDACTIVITYCOMPONENT__H__

View File

@@ -2,7 +2,7 @@
#include "EntityManager.h"
#include "ScriptedActivityComponent.h"
ShootingGalleryComponent::ShootingGalleryComponent(Entity* parent, int32_t activityID) : ActivityComponent(parent, activityID) {
ShootingGalleryComponent::ShootingGalleryComponent(Entity* parent, const int32_t componentID) : ActivityComponent(parent, componentID) {
}
void ShootingGalleryComponent::SetStaticParams(const StaticShootingGalleryParams& params) {

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