#include "RenderComponent.h" #include #include #include #include "Entity.h" #include "PacketUtils.h" #include "CDClientManager.h" #include "GameMessages.h" #include "Game.h" #include "dLogger.h" std::unordered_map RenderComponent::m_DurationCache{}; RenderComponent::RenderComponent(Entity* parent) : Component(parent) { m_Effects = std::vector(); return; /* auto* table = CDClientManager::Instance().GetTable(); const auto entry = table->GetByIDAndType(parent->GetLOT(), eReplicaComponentType::RENDER); std::stringstream query; query << "SELECT effect1, effect2, effect3, effect4, effect5, effect6 FROM RenderComponent WHERE id = " << std::to_string(entry) << ";"; auto result = CDClientDatabase::ExecuteQuery(query.str()); if (result.eof()) { return; } for (auto i = 0; i < 6; ++i) { if (result.fieldIsNull(i)) { continue; } const auto id = result.getIntField(i); if (id <= 0) { continue; } query.clear(); query << "SELECT effectType, effectName FROM BehaviorEffect WHERE effectID = " << std::to_string(id) << ";"; auto effectResult = CDClientDatabase::ExecuteQuery(query.str()); while (!effectResult.eof()) { const auto type = effectResult.fieldIsNull(0) ? "" : std::string(effectResult.getStringField(0)); const auto name = effectResult.fieldIsNull(1) ? "" : std::string(effectResult.getStringField(1)); auto* effect = new Effect(); effect->name = name; effect->type = GeneralUtils::ASCIIToUTF16(type); effect->scale = 1; effect->effectID = id; effect->secondary = LWOOBJID_EMPTY; m_Effects.push_back(effect); effectResult.nextRow(); } } result.finalize(); */ } RenderComponent::~RenderComponent() { for (Effect* eff : m_Effects) { if (eff) { delete eff; eff = nullptr; } } m_Effects.clear(); } void RenderComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { if (!bIsInitialUpdate) return; outBitStream->Write(m_Effects.size()); for (Effect* eff : m_Effects) { // Check that the effect is non-null assert(eff); outBitStream->Write(eff->name.size()); for (const auto& value : eff->name) outBitStream->Write(value); outBitStream->Write(eff->effectID); outBitStream->Write(eff->type.size()); for (const auto& value : eff->type) outBitStream->Write(value); outBitStream->Write(eff->scale); outBitStream->Write(eff->secondary); } } Effect* RenderComponent::AddEffect(const int32_t effectId, const std::string& name, const std::u16string& type) { auto* eff = new Effect(); eff->effectID = effectId; eff->name = name; eff->type = type; m_Effects.push_back(eff); return eff; } void RenderComponent::RemoveEffect(const std::string& name) { uint32_t index = -1; for (auto i = 0u; i < m_Effects.size(); ++i) { auto* eff = m_Effects[i]; if (eff->name == name) { index = i; delete eff; break; } } if (index == -1) { return; } m_Effects.erase(m_Effects.begin() + index); } void RenderComponent::Update(const float deltaTime) { std::vector dead; for (auto* effect : m_Effects) { if (effect->time == 0) { continue; // Skip persistent effects } const auto result = effect->time - deltaTime; if (result <= 0) { dead.push_back(effect); continue; } effect->time = result; } for (auto* effect : dead) { // StopEffect(effect->name); } } void RenderComponent::PlayEffect(const int32_t effectId, const std::u16string& effectType, const std::string& name, const LWOOBJID secondary, const float priority, const float scale, const bool serialize) { RemoveEffect(name); GameMessages::SendPlayFXEffect(m_Parent, effectId, effectType, name, secondary, priority, scale, serialize); auto* effect = AddEffect(effectId, name, effectType); const auto& pair = m_DurationCache.find(effectId); if (pair != m_DurationCache.end()) { effect->time = pair->second; return; } const std::string effectType_str = GeneralUtils::UTF16ToWTF8(effectType); auto query = CDClientDatabase::CreatePreppedStmt( "SELECT animation_length FROM Animations WHERE animation_type IN (SELECT animationName FROM BehaviorEffect WHERE effectID = ? AND effectType = ?);"); query.bind(1, effectId); query.bind(2, effectType_str.c_str()); auto result = query.execQuery(); if (result.eof() || result.fieldIsNull(0)) { result.finalize(); m_DurationCache[effectId] = 0; effect->time = 0; // Persistent effect return; } effect->time = static_cast(result.getFloatField(0)); result.finalize(); m_DurationCache[effectId] = effect->time; } void RenderComponent::StopEffect(const std::string& name, const bool killImmediate) { GameMessages::SendStopFXEffect(m_Parent, killImmediate, name); RemoveEffect(name); } std::vector& RenderComponent::GetEffects() { return m_Effects; }