mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-11-14 07:47:13 +00:00
feat(component): the exhibit component (32) the client's loader leaves dead
1.10.64's DoObjectComponentLoad has an EXHIBIT case that makes nothing; DLU makes ExhibitComponent there, built like LWOExhibitComponent on the spawner component: its ExhibitComponent row (model offset and size) and the exhibit_* level keys. It sends nothing in a construction (the client's Deserialize is empty), so the 12 exhibit LOTs keep their bytes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -99,6 +99,7 @@
|
||||
#include "PetCreatorComponent.h"
|
||||
#include "HFLightDirectionGadgetComponent.h"
|
||||
#include "SpawnerComponent.h"
|
||||
#include "ExhibitComponent.h"
|
||||
#include "PathfindingComponent.h"
|
||||
#include "PhysicsSystemComponent.h"
|
||||
#include "VehiclePhysicsComponent.h"
|
||||
@@ -911,6 +912,13 @@ void Entity::DoObjectComponentLoad(ObjectLoadState& state) {
|
||||
if (id > -1 && !HasComponent(eReplicaComponentType::PLAYER_FORCED_MOVEMENT)) AddComponent<PlayerForcedMovementComponent>(id);
|
||||
break;
|
||||
}
|
||||
case eReplicaComponentType::EXHIBIT: {
|
||||
// 1.10.64's loader has this case but makes nothing (dead code; showcases were cut); DLU makes the exhibit,
|
||||
// which sends nothing in a construction, so unchanged clients are unaffected
|
||||
const auto id = state.GetComponentID(eReplicaComponentType::EXHIBIT, -1);
|
||||
if (id > -1) AddComponent<ExhibitComponent>(id);
|
||||
break;
|
||||
}
|
||||
case eReplicaComponentType::ROCKET_LANDING: {
|
||||
// LWORocketAnimationControlComponent: the client makes it from the registry
|
||||
const auto id = state.GetComponentID(eReplicaComponentType::ROCKET_LANDING, -1);
|
||||
|
||||
@@ -42,6 +42,7 @@ set(DGAME_DCOMPONENTS_SOURCES
|
||||
"Physics/SimplePhysicsComponent.cpp"
|
||||
"SkillComponent.cpp"
|
||||
"Sound/SoundTriggerComponent.cpp"
|
||||
"ExhibitComponent.cpp"
|
||||
"SpawnerComponent.cpp"
|
||||
"SwitchComponent.cpp"
|
||||
"TriggerComponent.cpp"
|
||||
|
||||
51
dGame/dComponents/ExhibitComponent.cpp
Normal file
51
dGame/dComponents/ExhibitComponent.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
#include "ExhibitComponent.h"
|
||||
|
||||
#include "CDClientDatabase.h"
|
||||
#include "Entity.h"
|
||||
#include "Logger.h"
|
||||
|
||||
// LWOExhibitComponent::LoadDataFromTemplate 0x00c9ce40: the ExhibitComponent row
|
||||
void ExhibitComponent::LoadDataFromTemplate() {
|
||||
auto query = CDClientDatabase::CreatePreppedStmt(
|
||||
"SELECT offsetX, offsetY, offsetZ, width, height, length, fReputationSizeMultiplier, fImaginationCost FROM ExhibitComponent WHERE id = ?;");
|
||||
query.bind(1, m_ComponentID);
|
||||
auto result = query.execQuery();
|
||||
if (result.eof()) {
|
||||
LOG("Object LOT %i couldn't find ExhibitComponent %i in database", m_Parent->GetLOT(), m_ComponentID);
|
||||
return;
|
||||
}
|
||||
m_Offset = NiPoint3(result.getFloatField(0), result.getFloatField(1), result.getFloatField(2));
|
||||
m_Size = NiPoint3(result.getFloatField(3), result.getFloatField(4), result.getFloatField(5)) * 0.8f;
|
||||
m_ReputationSizeMultiplier = result.getFloatField(6);
|
||||
m_ImaginationCost = result.getFloatField(7);
|
||||
}
|
||||
|
||||
// LWOExhibitComponent::LoadConfigData 0x00c9c950: the spawn component's config, then the exhibit_* keys
|
||||
void ExhibitComponent::LoadConfigData() {
|
||||
SpawnerComponent::LoadConfigData();
|
||||
const auto text = [this](const std::u16string& key, const size_t max) {
|
||||
auto value = m_Parent->GetVar<std::u16string>(key);
|
||||
if (value.size() > max) value.resize(max);
|
||||
return value;
|
||||
};
|
||||
m_ResetTime = m_Parent->GetVar<uint32_t>(u"exhibit_reset_time");
|
||||
m_InstanceName = text(u"exhibit_instance_name", 32);
|
||||
m_VotingAllowed = m_Parent->GetVar<bool>(u"exhibit_voting_allowed");
|
||||
m_AllowUnmoderated = m_Parent->GetVar<bool>(u"exhibit_allow_unmoderated");
|
||||
m_AcceptsDroppedModels = m_Parent->GetVar<bool>(u"exhibit_accepts_dropped_models");
|
||||
m_RequiredNumberOfBricks = m_Parent->GetVar<uint32_t>(u"exhibit_required_number_of_bricks");
|
||||
m_MustUseBrickLots = text(u"exhibit_must_use_brick_lots", 250);
|
||||
m_MustNotUseBrickLots = text(u"exhibit_must_not_use_brick_lots", 250);
|
||||
m_MustUseBehaviorLots = text(u"exhibit_must_use_behavior_lots", 250);
|
||||
m_MustNotUseBehaviorLots = text(u"exhibit_must_not_use_behavior_lots", 250);
|
||||
m_InstanceDescription = text(u"exhibit_instance_description", 250);
|
||||
m_IncludeModelsMine = m_Parent->GetVar<bool>(u"exhibit_include_models_mine");
|
||||
m_IncludeModelsBffs = m_Parent->GetVar<bool>(u"exhibit_include_models_bffs");
|
||||
m_IncludeModelsFriends = m_Parent->GetVar<bool>(u"exhibit_include_models_friends");
|
||||
m_IncludeModelsGuild = m_Parent->GetVar<bool>(u"exhibit_include_models_guild");
|
||||
m_IncludeModelsPublic = m_Parent->GetVar<bool>(u"exhibit_include_models_public");
|
||||
m_DisplayRangeByRank = m_Parent->GetVar<uint32_t>(u"exhibit_display_range_by_rank");
|
||||
m_TargetTopModelsInstance = text(u"exhibit_target_top_models_instance", 32);
|
||||
m_IsAnimatedPedestal = m_Parent->GetVar<bool>(u"exhibit_is_animated_pedestal");
|
||||
m_AnimatedPedestalActiveBone = m_Parent->GetVar<uint32_t>(u"exhibit_animated_ped_active_bone");
|
||||
}
|
||||
59
dGame/dComponents/ExhibitComponent.h
Normal file
59
dGame/dComponents/ExhibitComponent.h
Normal file
@@ -0,0 +1,59 @@
|
||||
#ifndef EXHIBITCOMPONENT_H
|
||||
#define EXHIBITCOMPONENT_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "NiPoint3.h"
|
||||
#include "SpawnerComponent.h"
|
||||
|
||||
/**
|
||||
* An exhibit (showcase pedestal, 32), as the client's LWOExhibitComponent: a spawn component that shows a player's
|
||||
* model. The client sends and reads nothing for it in a construction (its Deserialize is empty); it spawns the shown
|
||||
* model itself from the exhibit messages. 1.10.64's loader has the case but makes nothing (dead code); DLU makes it.
|
||||
*/
|
||||
class ExhibitComponent final : public SpawnerComponent {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::EXHIBIT;
|
||||
|
||||
ExhibitComponent(Entity* parent, const int32_t componentID) : SpawnerComponent(parent, componentID) {}
|
||||
|
||||
void LoadDataFromTemplate() override;
|
||||
void LoadConfigData() override;
|
||||
|
||||
const NiPoint3& GetOffset() const { return m_Offset; }
|
||||
const NiPoint3& GetSize() const { return m_Size; }
|
||||
const std::u16string& GetInstanceName() const { return m_InstanceName; }
|
||||
bool GetVotingAllowed() const { return m_VotingAllowed; }
|
||||
|
||||
private:
|
||||
// The ExhibitComponent row: where the model sits on the pedestal and how big it may be (the client scales the
|
||||
// row's size by 0.8)
|
||||
NiPoint3 m_Offset{};
|
||||
NiPoint3 m_Size{};
|
||||
float m_ReputationSizeMultiplier = 1.0f;
|
||||
float m_ImaginationCost = 0.0f;
|
||||
|
||||
// The level config (LWOExhibitComponent::LoadConfigData 0x00c9c950)
|
||||
uint32_t m_ResetTime = 0;
|
||||
std::u16string m_InstanceName; // at most 32 characters
|
||||
bool m_VotingAllowed = false;
|
||||
bool m_AllowUnmoderated = false;
|
||||
bool m_AcceptsDroppedModels = false;
|
||||
uint32_t m_RequiredNumberOfBricks = 0;
|
||||
std::u16string m_MustUseBrickLots; // at most 250 characters each
|
||||
std::u16string m_MustNotUseBrickLots;
|
||||
std::u16string m_MustUseBehaviorLots;
|
||||
std::u16string m_MustNotUseBehaviorLots;
|
||||
std::u16string m_InstanceDescription;
|
||||
bool m_IncludeModelsMine = false;
|
||||
bool m_IncludeModelsBffs = false;
|
||||
bool m_IncludeModelsFriends = false;
|
||||
bool m_IncludeModelsGuild = false;
|
||||
bool m_IncludeModelsPublic = false;
|
||||
uint32_t m_DisplayRangeByRank = 0;
|
||||
std::u16string m_TargetTopModelsInstance; // at most 32 characters
|
||||
bool m_IsAnimatedPedestal = false;
|
||||
uint32_t m_AnimatedPedestalActiveBone = 0;
|
||||
};
|
||||
|
||||
#endif // EXHIBITCOMPONENT_H
|
||||
@@ -12,7 +12,7 @@ class Spawner;
|
||||
* The spawner component (10) of a spawner object (LOT 176), made from the registry as the client makes it. It owns the
|
||||
* spawner (its nodes, what it spawned and its timers); the zone manager indexes spawners by the object's ID.
|
||||
*/
|
||||
class SpawnerComponent final : public Component {
|
||||
class SpawnerComponent : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::SPAWNER;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user