diff --git a/CMakeLists.txt b/CMakeLists.txt index cd657772..74408df8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,7 +51,7 @@ set(RECASTNAVIGATION_EXAMPLES OFF CACHE BOOL "" FORCE) # Disabled no-register # Disabled unknown pragmas because Linux doesn't understand Windows pragmas. if(UNIX) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17 -O2 -Wuninitialized -fPIC") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wuninitialized -fPIC") add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=0 _GLIBCXX_USE_CXX17_ABI=0) if(NOT APPLE) diff --git a/dCommon/dEnums/ePetAbilityType.h b/dCommon/dEnums/ePetAbilityType.h new file mode 100644 index 00000000..0cc6d6bd --- /dev/null +++ b/dCommon/dEnums/ePetAbilityType.h @@ -0,0 +1,13 @@ +#ifndef __EPETABILITYTYPE__H__ +#define __EPETABILITYTYPE__H__ + +#include + +enum class ePetAbilityType : uint32_t { + Invalid, + GoToObject, + JumpOnObject, + DigAtPosition +}; + +#endif //!__EPETABILITYTYPE__H__ diff --git a/dDatabase/CDClientDatabase/CDClientDatabase.cpp b/dDatabase/CDClientDatabase/CDClientDatabase.cpp index 4c2df1d2..886030a1 100644 --- a/dDatabase/CDClientDatabase/CDClientDatabase.cpp +++ b/dDatabase/CDClientDatabase/CDClientDatabase.cpp @@ -4,9 +4,13 @@ // Static Variables static CppSQLite3DB* conn = new CppSQLite3DB(); +// Status Variables +bool CDClientDatabase::isConnected = false; + //! Opens a connection with the CDClient void CDClientDatabase::Connect(const std::string& filename) { conn->open(filename.c_str()); + isConnected = true; } //! Queries the CDClient diff --git a/dDatabase/CDClientDatabase/CDClientDatabase.h b/dDatabase/CDClientDatabase/CDClientDatabase.h index 7f42918d..fa58906c 100644 --- a/dDatabase/CDClientDatabase/CDClientDatabase.h +++ b/dDatabase/CDClientDatabase/CDClientDatabase.h @@ -15,6 +15,10 @@ //! The CDClient Database namespace namespace CDClientDatabase { + /** + * Boolean defining the connection status of CDClient + */ + extern bool isConnected; //! Opens a connection with the CDClient /*! diff --git a/dDatabase/CDClientDatabase/CDClientManager.cpp b/dDatabase/CDClientDatabase/CDClientManager.cpp index 74c5c975..f270d849 100644 --- a/dDatabase/CDClientDatabase/CDClientManager.cpp +++ b/dDatabase/CDClientDatabase/CDClientManager.cpp @@ -3,6 +3,7 @@ #include "CDAnimationsTable.h" #include "CDBehaviorParameterTable.h" #include "CDBehaviorTemplateTable.h" +#include "CDClientDatabase.h" #include "CDComponentsRegistryTable.h" #include "CDCurrencyTableTable.h" #include "CDDestructibleComponentTable.h" @@ -39,6 +40,8 @@ #include "CDRailActivatorComponent.h" #include "CDRewardCodesTable.h" +#include + #ifndef CDCLIENT_CACHE_ALL // Uncomment this to cache the full cdclient database into memory. This will make the server load faster, but will use more memory. // A vanilla CDClient takes about 46MB of memory + the regular world data. @@ -51,7 +54,16 @@ #define CDCLIENT_DONT_CACHE_TABLE(x) #endif -CDClientManager::CDClientManager() { +class CDClientConnectionException : public std::exception { +public: + virtual const char* what() const throw() { + return "CDClientDatabase is not connected!"; + } +}; + +void CDClientManager::LoadValuesFromDatabase() { + if (!CDClientDatabase::isConnected) throw CDClientConnectionException(); + CDActivityRewardsTable::Instance().LoadValuesFromDatabase(); CDActivitiesTable::Instance().LoadValuesFromDatabase(); CDCLIENT_DONT_CACHE_TABLE(CDAnimationsTable::Instance().LoadValuesFromDatabase()); @@ -79,6 +91,7 @@ CDClientManager::CDClientManager() { CDCLIENT_DONT_CACHE_TABLE(CDObjectsTable::Instance().LoadValuesFromDatabase()); CDPhysicsComponentTable::Instance().LoadValuesFromDatabase(); CDPackageComponentTable::Instance().LoadValuesFromDatabase(); + CDPetComponentTable::Instance().LoadValuesFromDatabase(); CDProximityMonitorComponentTable::Instance().LoadValuesFromDatabase(); CDPropertyEntranceComponentTable::Instance().LoadValuesFromDatabase(); CDPropertyTemplateTable::Instance().LoadValuesFromDatabase(); @@ -92,3 +105,9 @@ CDClientManager::CDClientManager() { CDVendorComponentTable::Instance().LoadValuesFromDatabase(); CDZoneTableTable::Instance().LoadValuesFromDatabase(); } + +void CDClientManager::LoadValuesFromDefaults() { + LOG("Loading default CDClient tables!"); + + CDPetComponentTable::Instance().LoadValuesFromDefaults(); +} diff --git a/dDatabase/CDClientDatabase/CDClientManager.h b/dDatabase/CDClientDatabase/CDClientManager.h index 74069ff4..ae628a36 100644 --- a/dDatabase/CDClientDatabase/CDClientManager.h +++ b/dDatabase/CDClientDatabase/CDClientManager.h @@ -11,7 +11,10 @@ */ class CDClientManager : public Singleton { public: - CDClientManager(); + CDClientManager() = default; + + void LoadValuesFromDatabase(); + void LoadValuesFromDefaults(); /** * Fetch a table from CDClient diff --git a/dDatabase/CDClientDatabase/CDClientTables/CDPetComponentTable.cpp b/dDatabase/CDClientDatabase/CDClientTables/CDPetComponentTable.cpp new file mode 100644 index 00000000..c3dd5d50 --- /dev/null +++ b/dDatabase/CDClientDatabase/CDClientTables/CDPetComponentTable.cpp @@ -0,0 +1,61 @@ +#include "CDPetComponentTable.h" + +namespace { + // Default entries for fallback + CDPetComponent defaultEntry{ + .id = 0, + UNUSED_ENTRY(.minTameUpdateTime = 60.0f,) + UNUSED_ENTRY(.maxTameUpdateTime = 300.0f,) + UNUSED_ENTRY(.percentTameChance = 101.0f,) + UNUSED_ENTRY(.tameability = 100.0f,) + UNUSED_ENTRY(.elementType = 1,) + .walkSpeed = 2.5f, + .runSpeed = 5.0f, + .sprintSpeed = 10.0f, + UNUSED_ENTRY(.idleTimeMin = 60.0f,) + UNUSED_ENTRY(.idleTimeMax = 300.0f,) + UNUSED_ENTRY(.petForm = 0,) + .imaginationDrainRate = 60.0f, + UNUSED_ENTRY(.AudioMetaEventSet = "",) + UNUSED_ENTRY(.buffIDs = "",) + }; +} + +void CDPetComponentTable::LoadValuesFromDatabase() { + auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PetComponent"); + while (!tableData.eof()) { + const uint32_t componentID = tableData.getIntField("id", defaultEntry.id); + + auto& entry = m_Entries[componentID]; + entry.id = componentID; + UNUSED_COLUMN(entry.minTameUpdateTime = tableData.getFloatField("minTameUpdateTime", defaultEntry.minTameUpdateTime)); + UNUSED_COLUMN(entry.maxTameUpdateTime = tableData.getFloatField("maxTameUpdateTime", defaultEntry.maxTameUpdateTime)); + UNUSED_COLUMN(entry.percentTameChance = tableData.getFloatField("percentTameChance", defaultEntry.percentTameChance)); + UNUSED_COLUMN(entry.tameability = tableData.getFloatField("tamability", defaultEntry.tameability)); // Mispelled as "tamability" in CDClient + UNUSED_COLUMN(entry.elementType = tableData.getIntField("elementType", defaultEntry.elementType)); + entry.walkSpeed = static_cast(tableData.getFloatField("walkSpeed", defaultEntry.walkSpeed)); + entry.runSpeed = static_cast(tableData.getFloatField("runSpeed", defaultEntry.runSpeed)); + entry.sprintSpeed = static_cast(tableData.getFloatField("sprintSpeed", defaultEntry.sprintSpeed)); + UNUSED_COLUMN(entry.idleTimeMin = tableData.getFloatField("idleTimeMin", defaultEntry.idleTimeMin)); + UNUSED_COLUMN(entry.idleTimeMax = tableData.getFloatField("idleTimeMax", defaultEntry.idleTimeMax)); + UNUSED_COLUMN(entry.petForm = tableData.getIntField("petForm", defaultEntry.petForm)); + entry.imaginationDrainRate = static_cast(tableData.getFloatField("imaginationDrainRate", defaultEntry.imaginationDrainRate)); + UNUSED_COLUMN(entry.AudioMetaEventSet = tableData.getStringField("AudioMetaEventSet", defaultEntry.AudioMetaEventSet)); + UNUSED_COLUMN(entry.buffIDs = tableData.getStringField("buffIDs", defaultEntry.buffIDs)); + + tableData.nextRow(); + } +} + +void CDPetComponentTable::LoadValuesFromDefaults() { + m_Entries.insert(std::make_pair(defaultEntry.id, defaultEntry)); +} + +CDPetComponent& CDPetComponentTable::GetByID(const uint32_t componentID) { + auto itr = m_Entries.find(componentID); + if (itr == m_Entries.end()) { + LOG("Unable to load pet component (ID %i) values from database! Using default values instead.", componentID); + return defaultEntry; + } + return itr->second; +} diff --git a/dDatabase/CDClientDatabase/CDClientTables/CDPetComponentTable.h b/dDatabase/CDClientDatabase/CDClientTables/CDPetComponentTable.h new file mode 100644 index 00000000..fa54e457 --- /dev/null +++ b/dDatabase/CDClientDatabase/CDClientTables/CDPetComponentTable.h @@ -0,0 +1,45 @@ +#pragma once +#include "CDTable.h" +#include +#include + +struct CDPetComponent { + uint32_t id; + UNUSED_COLUMN(float minTameUpdateTime;) + UNUSED_COLUMN(float maxTameUpdateTime;) + UNUSED_COLUMN(float percentTameChance;) + UNUSED_COLUMN(float tameability;) // Mispelled as "tamability" in CDClient + UNUSED_COLUMN(uint32_t elementType;) + float walkSpeed; + float runSpeed; + float sprintSpeed; + UNUSED_COLUMN(float idleTimeMin;) + UNUSED_COLUMN(float idleTimeMax;) + UNUSED_COLUMN(uint32_t petForm;) + float imaginationDrainRate; + UNUSED_COLUMN(std::string AudioMetaEventSet;) + UNUSED_COLUMN(std::string buffIDs;) +}; + +class CDPetComponentTable : public CDTable { +public: + + /** + * Load values from the CD client database + */ + void LoadValuesFromDatabase(); + + /** + * Load the default values into memory instead of attempting to connect to the CD client database + */ + void LoadValuesFromDefaults(); + + /** + * Gets the pet component table corresponding to the pet component ID + * @returns A reference to the corresponding table, or the default if one could not be found + */ + CDPetComponent& GetByID(const uint32_t componentID); + +private: + std::map m_Entries; +}; diff --git a/dDatabase/CDClientDatabase/CDClientTables/CDTable.h b/dDatabase/CDClientDatabase/CDClientTables/CDTable.h index 0a8f29ad..ab965127 100644 --- a/dDatabase/CDClientDatabase/CDClientTables/CDTable.h +++ b/dDatabase/CDClientDatabase/CDClientTables/CDTable.h @@ -23,6 +23,9 @@ // Enable this to skip some unused columns in some tables #define UNUSED_COLUMN(v) +// Use this to skip unused defaults for unused entries in some tables +#define UNUSED_ENTRY(v, x) + #pragma warning (disable : 4244) //Disable double to float conversion warnings #pragma warning (disable : 4715) //Disable "not all control paths return a value" diff --git a/dDatabase/CDClientDatabase/CDClientTables/CMakeLists.txt b/dDatabase/CDClientDatabase/CDClientTables/CMakeLists.txt index b2551efa..af401db2 100644 --- a/dDatabase/CDClientDatabase/CDClientTables/CMakeLists.txt +++ b/dDatabase/CDClientDatabase/CDClientTables/CMakeLists.txt @@ -23,6 +23,7 @@ set(DDATABASE_CDCLIENTDATABASE_CDCLIENTTABLES_SOURCES "CDActivitiesTable.cpp" "CDMovementAIComponentTable.cpp" "CDObjectSkillsTable.cpp" "CDObjectsTable.cpp" + "CDPetComponentTable.cpp" "CDPackageComponentTable.cpp" "CDPhysicsComponentTable.cpp" "CDPropertyEntranceComponentTable.cpp" diff --git a/dGame/dComponents/BaseCombatAIComponent.cpp b/dGame/dComponents/BaseCombatAIComponent.cpp index 4e969ced..9cc92c26 100644 --- a/dGame/dComponents/BaseCombatAIComponent.cpp +++ b/dGame/dComponents/BaseCombatAIComponent.cpp @@ -34,7 +34,6 @@ BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id): m_MovementAI = nullptr; m_Disabled = false; m_SkillEntries = {}; - m_MovementAI = nullptr; m_SoftTimer = 5.0f; //Grab the aggro information from BaseCombatAI: diff --git a/dGame/dComponents/PetComponent.cpp b/dGame/dComponents/PetComponent.cpp index 902edffe..bddfd009 100644 --- a/dGame/dComponents/PetComponent.cpp +++ b/dGame/dComponents/PetComponent.cpp @@ -69,7 +69,8 @@ std::map PetComponent::petFlags = { { 13067, 838 }, // Skeleton dragon }; -PetComponent::PetComponent(Entity* parent, uint32_t componentId): Component(parent) { +PetComponent::PetComponent(Entity* parentEntity, uint32_t componentId) : Component{ parentEntity } { + m_PetInfo = CDClientManager::Instance().GetTable()->GetByID(componentId); // TODO: Make reference when safe m_ComponentId = componentId; m_Interaction = LWOOBJID_EMPTY; @@ -81,31 +82,17 @@ PetComponent::PetComponent(Entity* parent, uint32_t componentId): Component(pare m_TimerAway = 0; m_DatabaseId = LWOOBJID_EMPTY; m_Status = 67108866; // Tamable - m_Ability = PetAbilityType::Invalid; + m_Ability = ePetAbilityType::Invalid; m_StartPosition = NiPoint3::ZERO; m_MovementAI = nullptr; m_TresureTime = 0; m_Preconditions = nullptr; - std::string checkPreconditions = GeneralUtils::UTF16ToWTF8(parent->GetVar(u"CheckPrecondition")); + std::string checkPreconditions = GeneralUtils::UTF16ToWTF8(parentEntity->GetVar(u"CheckPrecondition")); if (!checkPreconditions.empty()) { SetPreconditions(checkPreconditions); } - // Get the imagination drain rate from the CDClient - auto query = CDClientDatabase::CreatePreppedStmt("SELECT imaginationDrainRate FROM PetComponent WHERE id = ?;"); - - query.bind(1, static_cast(componentId)); - - auto result = query.execQuery(); - - // Should a result not exist for this pet default to 60 seconds. - if (!result.eof() && !result.fieldIsNull(0)) { - imaginationDrainRate = result.getFloatField(0, 60.0f); - } else { - imaginationDrainRate = 60.0f; - } - result.finalize(); } void PetComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { @@ -114,7 +101,7 @@ void PetComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpd outBitStream->Write1(); // Always serialize as dirty for now outBitStream->Write(m_Status); - outBitStream->Write(tamed ? m_Ability : PetAbilityType::Invalid); // Something with the overhead icon? + outBitStream->Write(tamed ? m_Ability : ePetAbilityType::Invalid); // Something with the overhead icon? const bool interacting = m_Interaction != LWOOBJID_EMPTY; @@ -835,11 +822,11 @@ void PetComponent::Wander() { return; } - m_MovementAI->SetMaxSpeed(info.wanderSpeed); + m_MovementAI->SetMaxSpeed(m_PetInfo.sprintSpeed); m_MovementAI->SetDestination(destination); - m_Timer += (m_MovementAI->GetParent()->GetPosition().x - destination.x) / info.wanderSpeed; + m_Timer += (m_MovementAI->GetParent()->GetPosition().x - destination.x) / m_PetInfo.sprintSpeed; } void PetComponent::Activate(Item* item, bool registerPet, bool fromTaming) { @@ -905,8 +892,6 @@ void PetComponent::Activate(Item* item, bool registerPet, bool fromTaming) { GameMessages::SendRegisterPetDBID(m_Owner, m_DatabaseId, owner->GetSystemAddress()); } - - GameMessages::SendShowPetActionButton(m_Owner, 3, true, owner->GetSystemAddress()); } void PetComponent::AddDrainImaginationTimer(Item* item, bool fromTaming) { @@ -928,22 +913,22 @@ void PetComponent::AddDrainImaginationTimer(Item* item, bool fromTaming) { if (!fromTaming) playerDestroyableComponent->Imagine(-1); // Set this to a variable so when this is called back from the player the timer doesn't fire off. - m_Parent->AddCallbackTimer(imaginationDrainRate, [playerDestroyableComponent, this, item]() { + m_Parent->AddCallbackTimer(m_PetInfo.imaginationDrainRate, [playerDestroyableComponent, this, item]() { if (!playerDestroyableComponent) { LOG("No petComponent and/or no playerDestroyableComponent"); return; } - // If we are out of imagination despawn the pet. - if (playerDestroyableComponent->GetImagination() == 0) { - this->Deactivate(); - auto playerEntity = playerDestroyableComponent->GetParent(); - if (!playerEntity) return; + // If we are out of imagination despawn the pet. + if (playerDestroyableComponent->GetImagination() == 0) { + this->Deactivate(); + auto playerEntity = playerDestroyableComponent->GetParent(); + if (!playerEntity) return; - GameMessages::SendUseItemRequirementsResponse(playerEntity->GetObjectID(), playerEntity->GetSystemAddress(), eUseItemResponse::NoImaginationForPet); - } + GameMessages::SendUseItemRequirementsResponse(playerEntity->GetObjectID(), playerEntity->GetSystemAddress(), eUseItemResponse::NoImaginationForPet); + } - this->AddDrainImaginationTimer(item); + this->AddDrainImaginationTimer(item); }); } @@ -966,7 +951,7 @@ void PetComponent::Deactivate() { GameMessages::SendRegisterPetDBID(m_Owner, LWOOBJID_EMPTY, owner->GetSystemAddress()); - GameMessages::SendShowPetActionButton(m_Owner, 0, false, owner->GetSystemAddress()); + GameMessages::SendShowPetActionButton(m_Owner, ePetAbilityType::Invalid, false, owner->GetSystemAddress()); } void PetComponent::Release() { @@ -985,12 +970,9 @@ void PetComponent::Release() { item->SetCount(0, false, false); } -void PetComponent::Command(NiPoint3 position, LWOOBJID source, int32_t commandType, int32_t typeId, bool overrideObey) { +void PetComponent::Command(const NiPoint3& position, const LWOOBJID source, const int32_t commandType, const int32_t typeId, const bool overrideObey) { auto* owner = GetOwner(); - - if (owner == nullptr) { - return; - } + if (!owner) return; if (commandType == 1) { // Emotes @@ -1030,7 +1012,7 @@ uint32_t PetComponent::GetStatus() const { return m_Status; } -PetAbilityType PetComponent::GetAbility() const { +ePetAbilityType PetComponent::GetAbility() const { return m_Ability; } @@ -1042,7 +1024,7 @@ void PetComponent::SetStatus(uint32_t value) { m_Status = value; } -void PetComponent::SetAbility(PetAbilityType value) { +void PetComponent::SetAbility(ePetAbilityType value) { m_Ability = value; } @@ -1098,7 +1080,7 @@ void PetComponent::SetPetNameForModeration(const std::string& petName) { } //Save to db: - Database::Get()->SetPetNameModerationStatus(m_DatabaseId, IPetNames::Info{petName, approved}); + Database::Get()->SetPetNameModerationStatus(m_DatabaseId, IPetNames::Info{ petName, approved }); } void PetComponent::LoadPetNameFromModeration() { diff --git a/dGame/dComponents/PetComponent.h b/dGame/dComponents/PetComponent.h index ca4b5a74..24ee157b 100644 --- a/dGame/dComponents/PetComponent.h +++ b/dGame/dComponents/PetComponent.h @@ -1,18 +1,13 @@ -#pragma once +#ifndef PETCOMPONENT_H +#define PETCOMPONENT_H #include "Entity.h" #include "MovementAIComponent.h" #include "Component.h" #include "Preconditions.h" +#include "ePetAbilityType.h" #include "eReplicaComponentType.h" - -enum class PetAbilityType : uint32_t -{ - Invalid, - GoToObject, - JumpOnObject, - DigAtPosition -}; +#include "CDPetComponentTable.h" /** * Represents an entity that is a pet. This pet can be tamed and consequently follows the tamer around, allowing it @@ -103,7 +98,7 @@ public: * @param typeId extra information about the command, e.g. the emote to play * @param overrideObey unused */ - void Command(NiPoint3 position, LWOOBJID source, int32_t commandType, int32_t typeId, bool overrideObey); + void Command(const NiPoint3& position, const LWOOBJID source, const int32_t commandType, const int32_t typeId, const bool overrideObey); /** * Returns the ID of the owner of this pet (if any) @@ -158,13 +153,13 @@ public: * Returns an ability the pet may perform, currently unused * @return an ability the pet may perform */ - PetAbilityType GetAbility() const; + ePetAbilityType GetAbility() const; /** * Sets the ability of the pet, currently unused * @param value the ability to set */ - void SetAbility(PetAbilityType value); + void SetAbility(ePetAbilityType value); /** * Sets preconditions for the pet that need to be met before it can be tamed @@ -323,7 +318,7 @@ private: /** * A currently active ability, mostly unused */ - PetAbilityType m_Ability; + ePetAbilityType m_Ability; /** * The time an entity has left to complete the minigame @@ -357,7 +352,10 @@ private: PreconditionExpression* m_Preconditions; /** - * The rate at which imagination is drained from the user for having the pet out. + * Pet information loaded from the CDClientDatabase + * TODO: Switch to a reference when safe to do so */ - float imaginationDrainRate; + CDPetComponent m_PetInfo; }; + +#endif // !PETCOMPONENT_H diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index 4041fded..03468884 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -94,6 +94,7 @@ #include "eReplicaComponentType.h" #include "eClientMessageType.h" #include "eGameMessageType.h" +#include "ePetAbilityType.h" #include "ActivityManager.h" #include "CDComponentsRegistryTable.h" @@ -3516,14 +3517,14 @@ void GameMessages::SendClientExitTamingMinigame(LWOOBJID objectId, bool bVolunta SEND_PACKET; } -void GameMessages::SendShowPetActionButton(LWOOBJID objectId, int32_t buttonLabel, bool bShow, const SystemAddress& sysAddr) { +void GameMessages::SendShowPetActionButton(const LWOOBJID objectId, const ePetAbilityType petAbility, const bool bShow, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; bitStream.Write(objectId); bitStream.Write(eGameMessageType::SHOW_PET_ACTION_BUTTON); - bitStream.Write(buttonLabel); + bitStream.Write(petAbility); bitStream.Write(bShow); if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST; diff --git a/dGame/dGameMessages/GameMessages.h b/dGame/dGameMessages/GameMessages.h index 6d29a394..9c8d183e 100644 --- a/dGame/dGameMessages/GameMessages.h +++ b/dGame/dGameMessages/GameMessages.h @@ -32,6 +32,7 @@ enum class eObjectWorldState : uint32_t; enum class eTerminateType : uint32_t; enum class eControlScheme : uint32_t; enum class eStateChangeType : uint32_t; +enum class ePetAbilityType : uint32_t; enum class ePetTamingNotifyType : uint32_t; enum class eUseItemResponse : uint32_t; enum class eQuickBuildFailReason : uint32_t; @@ -386,7 +387,7 @@ namespace GameMessages { void SendClientExitTamingMinigame(LWOOBJID objectId, bool bVoluntaryExit, const SystemAddress& sysAddr); - void SendShowPetActionButton(LWOOBJID objectId, int32_t buttonLabel, bool bShow, const SystemAddress& sysAddr); + void SendShowPetActionButton(const LWOOBJID objectId, const ePetAbilityType petAbility, const bool bShow, const SystemAddress& sysAddr); void SendPlayEmote(LWOOBJID objectId, int32_t emoteID, LWOOBJID target, const SystemAddress& sysAddr); diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index 046908ff..fc5baf85 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -180,7 +180,7 @@ int main(int argc, char** argv) { return EXIT_FAILURE; } - CDClientManager::Instance(); + CDClientManager::Instance().LoadValuesFromDatabase(); Diagnostics::SetProduceMemoryDump(Game::config->GetValue("generate_dump") == "1"); diff --git a/tests/dGameTests/GameDependencies.h b/tests/dGameTests/GameDependencies.h index 096dcb13..8aefaa3d 100644 --- a/tests/dGameTests/GameDependencies.h +++ b/tests/dGameTests/GameDependencies.h @@ -4,6 +4,7 @@ #include "Game.h" #include "Logger.h" #include "dServer.h" +#include "CDClientManager.h" #include "EntityInfo.h" #include "EntityManager.h" #include "dConfig.h" @@ -33,6 +34,9 @@ protected: Game::server = new dServerMock(); Game::config = new dConfig("worldconfig.ini"); Game::entityManager = new EntityManager(); + + // Create a CDClientManager instance and load from defaults + CDClientManager::Instance().LoadValuesFromDefaults(); } void TearDownDependencies() { diff --git a/tests/dGameTests/dComponentsTests/CMakeLists.txt b/tests/dGameTests/dComponentsTests/CMakeLists.txt index e38f7a53..374095af 100644 --- a/tests/dGameTests/dComponentsTests/CMakeLists.txt +++ b/tests/dGameTests/dComponentsTests/CMakeLists.txt @@ -1,5 +1,6 @@ set(DCOMPONENTS_TESTS "DestroyableComponentTests.cpp" + "PetComponentTests.cpp" "SimplePhysicsComponentTests.cpp" ) diff --git a/tests/dGameTests/dComponentsTests/PetComponentTests.cpp b/tests/dGameTests/dComponentsTests/PetComponentTests.cpp new file mode 100644 index 00000000..75ce4ec8 --- /dev/null +++ b/tests/dGameTests/dComponentsTests/PetComponentTests.cpp @@ -0,0 +1,43 @@ +#include "GameDependencies.h" +#include + +#include "BitStream.h" +#include "PetComponent.h" +#include "Entity.h" +#include "eReplicaComponentType.h" +#include "ePetAbilityType.h" +#include "eStateChangeType.h" + +class PetTest : public GameDependenciesTest { +protected: + Entity* baseEntity; + PetComponent* petComponent; + CBITSTREAM + + void SetUp() override { + SetUpDependencies(); + + // Set up entity and pet component + baseEntity = new Entity(15, GameDependenciesTest::info); + petComponent = baseEntity->AddComponent(1); + + // Initialize some values to be not default + + } + + void TearDown() override { + delete baseEntity; + TearDownDependencies(); + } +}; + +TEST_F(PetTest, PlacementNewAddComponentTest) { + // Test adding component + ASSERT_NE(petComponent, nullptr); + baseEntity->AddComponent(1); + ASSERT_NE(baseEntity->GetComponent(), nullptr); + + // Test getting initial status + ASSERT_EQ(petComponent->GetParent()->GetObjectID(), 15); + ASSERT_EQ(petComponent->GetAbility(), ePetAbilityType::Invalid); +}