diff --git a/dCommon/DluAssert.h b/dCommon/DluAssert.h new file mode 100644 index 00000000..c54dd54e --- /dev/null +++ b/dCommon/DluAssert.h @@ -0,0 +1,12 @@ +#ifndef __DLUASSERT__H__ +#define __DLUASSERT__H__ + +#include + +#ifdef _DEBUG +# define DluAssert(expression) assert(expression) +#else +# define DluAssert(expression) +#endif + +#endif //!__DLUASSERT__H__ diff --git a/dDatabase/CDClientDatabase.h b/dDatabase/CDClientDatabase.h index 96f67d64..59f69b7d 100644 --- a/dDatabase/CDClientDatabase.h +++ b/dDatabase/CDClientDatabase.h @@ -16,9 +16,6 @@ // Enable this to cache all entries in each table for fast access, comes with more memory cost //#define CDCLIENT_CACHE_ALL - // Enable this to skip some unused columns in some tables -#define UNUSED(v) - /*! \file CDClientDatabase.hpp \brief An interface between the CDClient.sqlite file and the server diff --git a/dDatabase/CDClientManager.cpp b/dDatabase/CDClientManager.cpp index eeea686f..9df6ff31 100644 --- a/dDatabase/CDClientManager.cpp +++ b/dDatabase/CDClientManager.cpp @@ -40,7 +40,7 @@ CDClientManager::CDClientManager() { CDActivityRewardsTable::Instance(); - UNUSED(CDAnimationsTable::Instance()); + CDAnimationsTable::Instance(); CDBehaviorParameterTable::Instance(); CDBehaviorTemplateTable::Instance(); CDComponentsRegistryTable::Instance(); diff --git a/dDatabase/CDClientManager.h b/dDatabase/CDClientManager.h index 1754fe99..74069ff4 100644 --- a/dDatabase/CDClientManager.h +++ b/dDatabase/CDClientManager.h @@ -4,6 +4,8 @@ #include "Singleton.h" +#define UNUSED_TABLE(v) + /** * Initialize the CDClient tables so they are all loaded into memory. */ diff --git a/dDatabase/Tables/CDAnimationsTable.cpp b/dDatabase/Tables/CDAnimationsTable.cpp index e1227f39..76ce0e5a 100644 --- a/dDatabase/Tables/CDAnimationsTable.cpp +++ b/dDatabase/Tables/CDAnimationsTable.cpp @@ -1,56 +1,83 @@ #include "CDAnimationsTable.h" +#include "GeneralUtils.h" +#include "Game.h" -CDAnimationsTable::CDAnimationsTable(void) { +bool CDAnimationsTable::CacheData(CppSQLite3Statement& queryToCache) { + auto tableData = queryToCache.execQuery(); + // If we received a bad lookup, cache it anyways so we do not run the query again. + if (tableData.eof()) return false; - // First, get the size of the table - unsigned int size = 0; - auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM Animations"); - while (!tableSize.eof()) { - size = tableSize.getIntField(0, 0); + do { + std::string animation_type = tableData.getStringField("animation_type", ""); + DluAssert(!animation_type.empty()); + AnimationGroupID animationGroupID = tableData.getIntField("animationGroupID", -1); + DluAssert(animationGroupID != -1); - tableSize.nextRow(); - } - - tableSize.finalize(); - - // Reserve the size - this->entries.reserve(size); - - // Now get the data - auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Animations"); - while (!tableData.eof()) { - CDAnimations entry; - entry.animationGroupID = tableData.getIntField("animationGroupID", -1); - entry.animation_type = tableData.getStringField("animation_type", ""); + CDAnimation entry; entry.animation_name = tableData.getStringField("animation_name", ""); - entry.chance_to_play = tableData.getFloatField("chance_to_play", -1.0f); - entry.min_loops = tableData.getIntField("min_loops", -1); - entry.max_loops = tableData.getIntField("max_loops", -1); - entry.animation_length = tableData.getFloatField("animation_length", -1.0f); - entry.hideEquip = tableData.getIntField("hideEquip", -1) == 1 ? true : false; - entry.ignoreUpperBody = tableData.getIntField("ignoreUpperBody", -1) == 1 ? true : false; - entry.restartable = tableData.getIntField("restartable", -1) == 1 ? true : false; - entry.face_animation_name = tableData.getStringField("face_animation_name", ""); - entry.priority = tableData.getFloatField("priority", -1.0f); - entry.blendTime = tableData.getFloatField("blendTime", -1.0f); + entry.chance_to_play = tableData.getFloatField("chance_to_play", 1.0f); + UNUSED_COLUMN(entry.min_loops = tableData.getIntField("min_loops", 0);) + UNUSED_COLUMN(entry.max_loops = tableData.getIntField("max_loops", 0);) + entry.animation_length = tableData.getFloatField("animation_length", 0.0f); + UNUSED_COLUMN(entry.hideEquip = tableData.getIntField("hideEquip", 0) == 1;) + UNUSED_COLUMN(entry.ignoreUpperBody = tableData.getIntField("ignoreUpperBody", 0) == 1;) + UNUSED_COLUMN(entry.restartable = tableData.getIntField("restartable", 0) == 1;) + UNUSED_COLUMN(entry.face_animation_name = tableData.getStringField("face_animation_name", "");) + UNUSED_COLUMN(entry.priority = tableData.getFloatField("priority", 0.0f);) + UNUSED_COLUMN(entry.blendTime = tableData.getFloatField("blendTime", 0.0f);) - this->entries.push_back(entry); + this->animations[CDAnimationKey(animation_type, animationGroupID)].push_back(entry); tableData.nextRow(); - } + } while (!tableData.eof()); tableData.finalize(); + + return true; } -std::vector CDAnimationsTable::Query(std::function predicate) { - - std::vector data = cpplinq::from(this->entries) - >> cpplinq::where(predicate) - >> cpplinq::to_vector(); - - return data; +void CDAnimationsTable::CacheAnimations(const CDAnimationKey animationKey) { + auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM Animations WHERE animationGroupID = ? and animation_type = ?"); + query.bind(1, static_cast(animationKey.second)); + query.bind(2, animationKey.first.c_str()); + // If we received a bad lookup, cache it anyways so we do not run the query again. + if (!CacheData(query)) { + this->animations[animationKey]; + } } -std::vector CDAnimationsTable::GetEntries(void) const { - return this->entries; +void CDAnimationsTable::CacheAnimationGroup(AnimationGroupID animationGroupID) { + auto animationEntryCached = this->animations.find(CDAnimationKey("", animationGroupID)); + if (animationEntryCached != this->animations.end()) { + return; + } + + auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM Animations WHERE animationGroupID = ?"); + query.bind(1, static_cast(animationGroupID)); + + // Cache the query so we don't run the query again. + CacheData(query); + this->animations[CDAnimationKey("", animationGroupID)]; } +CDAnimationLookupResult CDAnimationsTable::GetAnimation(const AnimationID& animationType, const std::string& previousAnimationName, const AnimationGroupID animationGroupID) { + CDAnimationKey animationKey(animationType, animationGroupID); + auto animationEntryCached = this->animations.find(animationKey); + if (animationEntryCached == this->animations.end()) { + this->CacheAnimations(animationKey); + } + + auto animationEntry = this->animations.find(animationKey); + // If we have only one animation, return it regardless of the chance to play. + if (animationEntry->second.size() == 1) { + return CDAnimationLookupResult(animationEntry->second.front()); + } + auto randomAnimation = GeneralUtils::GenerateRandomNumber(0, 1); + + for (auto& animationEntry : animationEntry->second) { + randomAnimation -= animationEntry.chance_to_play; + // This is how the client gets the random animation. + if (animationEntry.animation_name != previousAnimationName && randomAnimation <= 0.0f) return CDAnimationLookupResult(animationEntry); + } + + return CDAnimationLookupResult(); +} diff --git a/dDatabase/Tables/CDAnimationsTable.h b/dDatabase/Tables/CDAnimationsTable.h index 43400abf..65f54d98 100644 --- a/dDatabase/Tables/CDAnimationsTable.h +++ b/dDatabase/Tables/CDAnimationsTable.h @@ -1,33 +1,66 @@ #pragma once -// Custom Classes #include "CDTable.h" +#include -struct CDAnimations { - unsigned int animationGroupID; //!< The animation group ID - std::string animation_type; //!< The animation type +struct CDAnimation { + // unsigned int animationGroupID; + // std::string animation_type; + // The above two are a pair to represent a primary key in the map. std::string animation_name; //!< The animation name float chance_to_play; //!< The chance to play the animation - unsigned int min_loops; //!< The minimum number of loops - unsigned int max_loops; //!< The maximum number of loops + UNUSED_COLUMN(unsigned int min_loops;) //!< The minimum number of loops + UNUSED_COLUMN(unsigned int max_loops;) //!< The maximum number of loops float animation_length; //!< The animation length - bool hideEquip; //!< Whether or not to hide the equip - bool ignoreUpperBody; //!< Whether or not to ignore the upper body - bool restartable; //!< Whether or not the animation is restartable - std::string face_animation_name; //!< The face animation name - float priority; //!< The priority - float blendTime; //!< The blend time + UNUSED_COLUMN(bool hideEquip;) //!< Whether or not to hide the equip + UNUSED_COLUMN(bool ignoreUpperBody;) //!< Whether or not to ignore the upper body + UNUSED_COLUMN(bool restartable;) //!< Whether or not the animation is restartable + UNUSED_COLUMN(std::string face_animation_name;) //!< The face animation name + UNUSED_COLUMN(float priority;) //!< The priority + UNUSED_COLUMN(float blendTime;) //!< The blend time }; +typedef LookupResult CDAnimationLookupResult; class CDAnimationsTable : public CDTable { -private: - std::vector entries; - + typedef int32_t AnimationGroupID; + typedef std::string AnimationID; + typedef std::pair CDAnimationKey; public: - CDAnimationsTable(); - // Queries the table with a custom "where" clause - std::vector Query(std::function predicate); + /** + * Given an animationType and the previousAnimationName played, return the next animationType to play. + * If there are more than 1 animationTypes that can be played, one is selected at random but also does not allow + * the previousAnimationName to be played twice. + * + * @param animationType The animationID to lookup + * @param previousAnimationName The previously played animation + * @param animationGroupID The animationGroupID to lookup + * @return CDAnimationLookupResult + */ + [[nodiscard]] CDAnimationLookupResult GetAnimation(const AnimationID& animationType, const std::string& previousAnimationName, const AnimationGroupID animationGroupID); - std::vector GetEntries(void) const; + /** + * Cache a full AnimationGroup by its ID. + */ + void CacheAnimationGroup(AnimationGroupID animationGroupID); +private: + + /** + * Cache all animations given a premade key + */ + void CacheAnimations(const CDAnimationKey animationKey); + + /** + * Run the query responsible for caching the data. + * @param queryToCache + * @return true + * @return false + */ + bool CacheData(CppSQLite3Statement& queryToCache); + + /** + * Each animation is key'd by its animationName and its animationGroupID. Each + * animation has a possible list of animations. This is because there can be animations have a percent chance to play so one is selected at random. + */ + std::map> animations; }; diff --git a/dDatabase/Tables/CDTable.h b/dDatabase/Tables/CDTable.h index fca16eb8..e4c11fb9 100644 --- a/dDatabase/Tables/CDTable.h +++ b/dDatabase/Tables/CDTable.h @@ -2,6 +2,7 @@ #include "CDClientDatabase.h" #include "Singleton.h" +#include "DluAssert.h" #include #include @@ -15,6 +16,12 @@ #endif #include "cpplinq.hpp" +// Used for legacy +#define UNUSED(x) + +// Enable this to skip some unused columns in some tables +#define UNUSED_COLUMN(v) + #pragma warning (disable : 4244) //Disable double to float conversion warnings #pragma warning (disable : 4715) //Disable "not all control paths return a value" @@ -23,3 +30,15 @@ class CDTable : public Singleton { protected: virtual ~CDTable() = default; }; + +template +class LookupResult { + typedef std::pair DataType; +public: + LookupResult() { m_data.first = T(); m_data.second = false; }; + LookupResult(T& data) { m_data.first = data; m_data.second = true; }; + inline const T& Data() { return m_data.first; }; + inline const bool& FoundData() { return m_data.second; }; +private: + DataType m_data; +}; diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index 68ab0c7a..6de6ba62 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -595,8 +595,9 @@ void Entity::Initialize() { m_Components.insert(std::make_pair(eReplicaComponentType::BOUNCER, comp)); } - if ((compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RENDER) > 0 && m_TemplateID != 2365) || m_Character) { - RenderComponent* render = new RenderComponent(this); + int32_t renderComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RENDER); + if ((renderComponentId > 0 && m_TemplateID != 2365) || m_Character) { + RenderComponent* render = new RenderComponent(this, renderComponentId); m_Components.insert(std::make_pair(eReplicaComponentType::RENDER, render)); } diff --git a/dGame/dComponents/PetComponent.cpp b/dGame/dComponents/PetComponent.cpp index 774aa92b..c37ce6a0 100644 --- a/dGame/dComponents/PetComponent.cpp +++ b/dGame/dComponents/PetComponent.cpp @@ -26,6 +26,7 @@ #include "Database.h" #include "EntityInfo.h" #include "eMissionTaskType.h" +#include "RenderComponent.h" #include "eObjectBits.h" #include "eGameMasterLevel.h" @@ -530,7 +531,7 @@ void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) { } GameMessages::SendPlayFXEffect(tamer, -1, u"petceleb", "", LWOOBJID_EMPTY, 1, 1, true); - GameMessages::SendPlayAnimation(tamer, u"rebuild-celebrate"); + RenderComponent::PlayAnimation(tamer, u"rebuild-celebrate"); EntityInfo info{}; info.lot = cached->second.puzzleModelLot; diff --git a/dGame/dComponents/RailActivatorComponent.cpp b/dGame/dComponents/RailActivatorComponent.cpp index e4091046..8e13c37f 100644 --- a/dGame/dComponents/RailActivatorComponent.cpp +++ b/dGame/dComponents/RailActivatorComponent.cpp @@ -7,6 +7,8 @@ #include "RebuildComponent.h" #include "Game.h" #include "dLogger.h" +#include "RenderComponent.h" +#include "EntityManager.h" #include "eStateChangeType.h" RailActivatorComponent::RailActivatorComponent(Entity* parent, int32_t componentID) : Component(parent) { @@ -57,23 +59,10 @@ void RailActivatorComponent::OnUse(Entity* originator) { GameMessages::SendPlayFXEffect(originator->GetObjectID(), m_StartEffect.first, m_StartEffect.second, std::to_string(m_StartEffect.first)); } - + + float animationLength = 0.5f; if (!m_StartAnimation.empty()) { - GameMessages::SendPlayAnimation(originator, m_StartAnimation); - } - - float animationLength; - - if (m_StartAnimation == u"whirlwind-rail-up-earth") { - animationLength = 1.5f; - } else if (m_StartAnimation == u"whirlwind-rail-up-lightning") { - animationLength = 0.5f; - } else if (m_StartAnimation == u"whirlwind-rail-up-ice") { - animationLength = 0.5f; - } else if (m_StartAnimation == u"whirlwind-rail-up-fire") { - animationLength = 0.5f; - } else { - animationLength = 0.5f; + animationLength = RenderComponent::PlayAnimation(originator, m_StartAnimation); } const auto originatorID = originator->GetObjectID(); @@ -112,7 +101,7 @@ void RailActivatorComponent::OnRailMovementReady(Entity* originator) const { } if (!m_LoopAnimation.empty()) { - GameMessages::SendPlayAnimation(originator, m_LoopAnimation); + RenderComponent::PlayAnimation(originator, m_LoopAnimation); } GameMessages::SendSetRailMovement(originator->GetObjectID(), m_PathDirection, m_Path, m_PathStart, @@ -147,7 +136,7 @@ void RailActivatorComponent::OnCancelRailMovement(Entity* originator) { } if (!m_StopAnimation.empty()) { - GameMessages::SendPlayAnimation(originator, m_StopAnimation); + RenderComponent::PlayAnimation(originator, m_StopAnimation); } // Remove the player after they've signalled they're done railing diff --git a/dGame/dComponents/RebuildComponent.cpp b/dGame/dComponents/RebuildComponent.cpp index acd84a64..39c8fe8d 100644 --- a/dGame/dComponents/RebuildComponent.cpp +++ b/dGame/dComponents/RebuildComponent.cpp @@ -20,6 +20,7 @@ #include "Preconditions.h" #include "Loot.h" #include "TeamManager.h" +#include "RenderComponent.h" #include "CppScripts.h" @@ -517,7 +518,7 @@ void RebuildComponent::CompleteRebuild(Entity* user) { character->SetPlayerFlag(flagNumber, true); } } - GameMessages::SendPlayAnimation(user, u"rebuild-celebrate", 1.09f); + RenderComponent::PlayAnimation(user, u"rebuild-celebrate", 1.09f); } void RebuildComponent::ResetRebuild(bool failed) { @@ -527,7 +528,7 @@ void RebuildComponent::ResetRebuild(bool failed) { GameMessages::SendEnableRebuild(m_Parent, false, false, failed, eQuickBuildFailReason::NOT_GIVEN, m_ResetTime, builder->GetObjectID()); if (failed) { - GameMessages::SendPlayAnimation(builder, u"rebuild-fail"); + RenderComponent::PlayAnimation(builder, u"rebuild-fail"); } } diff --git a/dGame/dComponents/RenderComponent.cpp b/dGame/dComponents/RenderComponent.cpp index ee42acba..94f5fb5d 100644 --- a/dGame/dComponents/RenderComponent.cpp +++ b/dGame/dComponents/RenderComponent.cpp @@ -11,72 +11,36 @@ #include "GameMessages.h" #include "Game.h" #include "dLogger.h" +#include "CDAnimationsTable.h" std::unordered_map RenderComponent::m_DurationCache{}; -RenderComponent::RenderComponent(Entity* parent) : Component(parent) { +RenderComponent::RenderComponent(Entity* parent, int32_t componentId): Component(parent) { m_Effects = std::vector(); + m_LastAnimationName = ""; + if (componentId == -1) return; - return; + auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM RenderComponent WHERE id = ?;"); + query.bind(1, componentId); + auto result = query.execQuery(); - /* - 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(); + if (!result.eof()) { + auto animationGroupIDs = std::string(result.getStringField("animationGroupIDs", "")); + if (!animationGroupIDs.empty()) { + auto* animationsTable = CDClientManager::Instance().GetTable(); + auto groupIdsSplit = GeneralUtils::SplitString(animationGroupIDs, ','); + for (auto& groupId : groupIdsSplit) { + int32_t groupIdInt; + if (!GeneralUtils::TryParse(groupId, groupIdInt)) { + Game::logger->Log("RenderComponent", "bad animation group Id %s", groupId.c_str()); + continue; + } + m_animationGroupIds.push_back(groupIdInt); + animationsTable->CacheAnimationGroup(groupIdInt); + } } } - result.finalize(); - */ } RenderComponent::~RenderComponent() { @@ -224,3 +188,45 @@ void RenderComponent::StopEffect(const std::string& name, const bool killImmedia std::vector& RenderComponent::GetEffects() { return m_Effects; } + + +float RenderComponent::PlayAnimation(Entity* self, const std::u16string& animation, float priority, float scale) { + if (!self) return 0.0f; + return RenderComponent::PlayAnimation(self, GeneralUtils::UTF16ToWTF8(animation), priority, scale); +} + +float RenderComponent::PlayAnimation(Entity* self, const std::string& animation, float priority, float scale) { + if (!self) return 0.0f; + return RenderComponent::DoAnimation(self, animation, true, priority, scale); +} + +float RenderComponent::GetAnimationTime(Entity* self, const std::u16string& animation) { + if (!self) return 0.0f; + return RenderComponent::GetAnimationTime(self, GeneralUtils::UTF16ToWTF8(animation)); +} + +float RenderComponent::GetAnimationTime(Entity* self, const std::string& animation) { + if (!self) return 0.0f; + return RenderComponent::DoAnimation(self, animation, false); +} + + +float RenderComponent::DoAnimation(Entity* self, const std::string& animation, bool sendAnimation, float priority, float scale) { + float returnlength = 0.0f; + if (!self) return returnlength; + auto* renderComponent = self->GetComponent(); + if (!renderComponent) return returnlength; + + auto* animationsTable = CDClientManager::Instance().GetTable(); + for (auto& groupId : renderComponent->m_animationGroupIds) { + auto animationGroup = animationsTable->GetAnimation(animation, renderComponent->GetLastAnimationName(), groupId); + if (animationGroup.FoundData()) { + auto data = animationGroup.Data(); + renderComponent->SetLastAnimationName(data.animation_name); + returnlength = data.animation_length; + } + } + if (sendAnimation) GameMessages::SendPlayAnimation(self, GeneralUtils::ASCIIToUTF16(animation), priority, scale); + if (returnlength == 0.0f) Game::logger->Log("RenderComponent", "WARNING: Unable to find animation %s for lot %i in any group.", animation.c_str(), self->GetLOT()); + return returnlength; +} diff --git a/dGame/dComponents/RenderComponent.h b/dGame/dComponents/RenderComponent.h index e09ec22d..cdf32160 100644 --- a/dGame/dComponents/RenderComponent.h +++ b/dGame/dComponents/RenderComponent.h @@ -58,7 +58,7 @@ class RenderComponent : public Component { public: static const eReplicaComponentType ComponentType = eReplicaComponentType::RENDER; - RenderComponent(Entity* entity); + RenderComponent(Entity* entity, int32_t componentId = -1); ~RenderComponent() override; void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); @@ -104,6 +104,32 @@ public: */ std::vector& GetEffects(); + /** + * Verifies that an animation can be played on this entity by checking + * if it has the animation assigned to its group. If it does, the animation is echo'd + * down to all clients to be played and the duration of the played animation is returned. + * If the animation did not exist or the function was called in an invalid state, 0 is returned. + * + * The logic here matches the exact client logic. + * + * @param self The entity that wants to play an animation + * @param animation The animation_type (animationID in the client) to be played. + * @param sendAnimation Whether or not to echo the animation down to all clients. + * @param priority The priority of the animation. Only used if sendAnimation is true. + * @param scale The scale of the animation. Only used if sendAnimation is true. + * + * @return The duration of the animation that was played. + */ + static float DoAnimation(Entity* self, const std::string& animation, bool sendAnimation, float priority = 0.0f, float scale = 1.0f); + + static float PlayAnimation(Entity* self, const std::u16string& animation, float priority = 0.0f, float scale = 1.0f); + static float PlayAnimation(Entity* self, const std::string& animation, float priority = 0.0f, float scale = 1.0f); + static float GetAnimationTime(Entity* self, const std::string& animation); + static float GetAnimationTime(Entity* self, const std::u16string& animation); + + const std::string& GetLastAnimationName() const { return m_LastAnimationName; }; + void SetLastAnimationName(const std::string& name) { m_LastAnimationName = name; }; + private: /** @@ -111,6 +137,11 @@ private: */ std::vector m_Effects; + std::vector m_animationGroupIds; + + // The last animationName that was played + std::string m_LastAnimationName; + /** * Cache of queries that look for the length of each effect, indexed by effect ID */ diff --git a/dGame/dComponents/SwitchComponent.cpp b/dGame/dComponents/SwitchComponent.cpp index c59559c2..b393bbef 100644 --- a/dGame/dComponents/SwitchComponent.cpp +++ b/dGame/dComponents/SwitchComponent.cpp @@ -1,6 +1,7 @@ #include "SwitchComponent.h" #include "EntityManager.h" #include "eTriggerEventType.h" +#include "RenderComponent.h" std::vector SwitchComponent::petSwitches; @@ -59,7 +60,7 @@ void SwitchComponent::EntityEnter(Entity* entity) { if (m_PetBouncer != nullptr) { GameMessages::SendPlayFXEffect(m_Parent->GetObjectID(), 2602, u"pettriggeractive", "BounceEffect", LWOOBJID_EMPTY, 1, 1, true); - GameMessages::SendPlayAnimation(m_Parent, u"engaged", 0, 1); + RenderComponent::PlayAnimation(m_Parent, u"engaged"); m_PetBouncer->SetPetBouncerEnabled(true); } else { EntityManager::Instance()->SerializeEntity(m_Parent); diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index be57bce3..c178f6c7 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -70,6 +70,7 @@ #include "PetComponent.h" #include "ModuleAssemblyComponent.h" #include "VehiclePhysicsComponent.h" +#include "RenderComponent.h" #include "PossessableComponent.h" #include "PossessorComponent.h" #include "RacingControlComponent.h" @@ -5125,7 +5126,7 @@ void GameMessages::HandlePlayEmote(RakNet::BitStream* inStream, Entity* entity) if (emote) sAnimationName = emote->animationName; } - GameMessages::SendPlayAnimation(entity, GeneralUtils::ASCIIToUTF16(sAnimationName)); + RenderComponent::PlayAnimation(entity, sAnimationName); } void GameMessages::HandleModularBuildConvertModel(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { diff --git a/dGame/dUtilities/SlashCommandHandler.cpp b/dGame/dUtilities/SlashCommandHandler.cpp index e8915d27..b65bf723 100644 --- a/dGame/dUtilities/SlashCommandHandler.cpp +++ b/dGame/dUtilities/SlashCommandHandler.cpp @@ -77,6 +77,7 @@ #include "eObjectBits.h" #include "eGameMasterLevel.h" #include "eReplicaComponentType.h" +#include "RenderComponent.h" #include "eControlScheme.h" #include "eConnectionType.h" #include "eChatInternalMessageType.h" @@ -411,11 +412,11 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit if ((chatCommand == "playanimation" || chatCommand == "playanim") && args.size() == 1 && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) { std::u16string anim = GeneralUtils::ASCIIToUTF16(args[0], args[0].size()); - GameMessages::SendPlayAnimation(entity, anim); + RenderComponent::PlayAnimation(entity, anim); auto* possessorComponent = entity->GetComponent(); if (possessorComponent) { auto* possessedComponent = EntityManager::Instance()->GetEntity(possessorComponent->GetPossessable()); - if (possessedComponent) GameMessages::SendPlayAnimation(possessedComponent, anim); + if (possessedComponent) RenderComponent::PlayAnimation(possessedComponent, anim); } } @@ -1947,7 +1948,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit EntityManager::Instance()->SerializeEntity(closest); } else if (args[1] == "-a" && args.size() >= 3) { - GameMessages::SendPlayAnimation(closest, GeneralUtils::UTF8ToUTF16(args[2])); + RenderComponent::PlayAnimation(closest, args.at(2)); } else if (args[1] == "-s") { for (auto* entry : closest->GetSettings()) { ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::UTF8ToUTF16(entry->GetString())); diff --git a/dMasterServer/MasterServer.cpp b/dMasterServer/MasterServer.cpp index 7af235a4..ce237eac 100644 --- a/dMasterServer/MasterServer.cpp +++ b/dMasterServer/MasterServer.cpp @@ -50,6 +50,7 @@ namespace Game { dConfig* config = nullptr; AssetManager* assetManager = nullptr; bool shouldShutdown = false; + std::mt19937 randomEngine; } //namespace Game bool shutdownSequenceStarted = false; @@ -291,6 +292,7 @@ int main(int argc, char** argv) { return EXIT_SUCCESS; } + Game::randomEngine = std::mt19937(time(0)); uint32_t maxClients = 999; uint32_t ourPort = 1000; if (Game::config->GetValue("max_clients") != "") maxClients = std::stoi(Game::config->GetValue("max_clients")); diff --git a/dScripts/02_server/DLU/DLUVanityNPC.cpp b/dScripts/02_server/DLU/DLUVanityNPC.cpp index e3db2353..ba2c6604 100644 --- a/dScripts/02_server/DLU/DLUVanityNPC.cpp +++ b/dScripts/02_server/DLU/DLUVanityNPC.cpp @@ -2,6 +2,7 @@ #include "GameMessages.h" #include "dServer.h" #include "VanityUtilities.h" +#include "RenderComponent.h" void DLUVanityNPC::OnStartup(Entity* self) { m_NPC = VanityUtilities::GetNPC("averysumner - Destroyer of Worlds"); @@ -17,7 +18,7 @@ void DLUVanityNPC::OnStartup(Entity* self) { void DLUVanityNPC::OnTimerDone(Entity* self, std::string timerName) { if (timerName == "setupTeleport") { - GameMessages::SendPlayAnimation(self, u"interact"); + RenderComponent::PlayAnimation(self, u"interact"); GameMessages::SendPlayFXEffect(self->GetObjectID(), 6478, u"teleportBeam", "teleportBeam"); GameMessages::SendPlayFXEffect(self->GetObjectID(), 6478, u"teleportRings", "teleportRings"); diff --git a/dScripts/02_server/Enemy/AG/BossSpiderQueenEnemyServer.cpp b/dScripts/02_server/Enemy/AG/BossSpiderQueenEnemyServer.cpp index a3b9cc3f..a51af03a 100644 --- a/dScripts/02_server/Enemy/AG/BossSpiderQueenEnemyServer.cpp +++ b/dScripts/02_server/Enemy/AG/BossSpiderQueenEnemyServer.cpp @@ -14,6 +14,7 @@ #include "GameMessages.h" #include "SkillComponent.h" #include "eReplicaComponentType.h" +#include "RenderComponent.h" #include @@ -616,11 +617,11 @@ float BossSpiderQueenEnemyServer::PlayAnimAndReturnTime(Entity* self, const std: //TODO: Get the actual animation time // Get the anim time - float animTimer = defaultAnimPause; //self:GetAnimationTime{animationID = animID}.time + float animTimer = RenderComponent::GetAnimationTime(self, animID); // If we have an animation play it if (animTimer > 0) { - GameMessages::SendPlayAnimation(self, animID); + animTimer = RenderComponent::PlayAnimation(self, animID); } // If the anim time is less than the the default time use default diff --git a/dScripts/02_server/Enemy/AM/AmDarklingDragon.cpp b/dScripts/02_server/Enemy/AM/AmDarklingDragon.cpp index 28ba0044..ff30f8e8 100644 --- a/dScripts/02_server/Enemy/AM/AmDarklingDragon.cpp +++ b/dScripts/02_server/Enemy/AM/AmDarklingDragon.cpp @@ -7,6 +7,7 @@ #include "BaseCombatAIComponent.h" #include "EntityInfo.h" #include "eAninmationFlags.h" +#include "RenderComponent.h" void AmDarklingDragon::OnStartup(Entity* self) { self->SetVar(u"weakspot", 0); @@ -70,9 +71,9 @@ void AmDarklingDragon::OnHitOrHealResult(Entity* self, Entity* attacker, int32_t self->SetVar(u"weakpoint", 2); GameMessages::SendChangeIdleFlags(self->GetObjectID(), eAnimationFlags::IDLE_NONE, eAnimationFlags::IDLE_COMBAT, UNASSIGNED_SYSTEM_ADDRESS); - GameMessages::SendPlayAnimation(self, u"stunstart", 1.7f); + float animationTime = RenderComponent::PlayAnimation(self, u"stunstart", 1.7f); - self->AddTimer("timeToStunLoop", 1); + self->AddTimer("timeToStunLoop", 1.0f); auto position = self->GetPosition(); auto forward = self->GetRotation().GetForwardVector(); @@ -121,9 +122,9 @@ void AmDarklingDragon::OnTimerDone(Entity* self, std::string timerName) { } else if (timerName == "ExposeWeakSpotTimer") { self->SetVar(u"weakspot", 1); } else if (timerName == "timeToStunLoop") { - GameMessages::SendPlayAnimation(self, u"stunloop", 1.8f); + RenderComponent::PlayAnimation(self, u"stunloop", 1.8f); } else if (timerName == "ReviveTimer") { - GameMessages::SendPlayAnimation(self, u"stunend", 2.0f); + RenderComponent::PlayAnimation(self, u"stunend", 2.0f); self->AddTimer("backToAttack", 1); } else if (timerName == "backToAttack") { auto* baseCombatAIComponent = self->GetComponent(); @@ -153,5 +154,5 @@ void AmDarklingDragon::OnFireEventServerSide(Entity* self, Entity* sender, std:: self->SetVar(u"Golem", sender->GetObjectID()); - GameMessages::SendPlayAnimation(self, u"quickbuildhold", 1.9f); + RenderComponent::PlayAnimation(self, u"quickbuildhold", 1.9f); } diff --git a/dScripts/02_server/Enemy/FV/FvMaelstromDragon.cpp b/dScripts/02_server/Enemy/FV/FvMaelstromDragon.cpp index e78f537f..664d8b67 100644 --- a/dScripts/02_server/Enemy/FV/FvMaelstromDragon.cpp +++ b/dScripts/02_server/Enemy/FV/FvMaelstromDragon.cpp @@ -5,6 +5,7 @@ #include "DestroyableComponent.h" #include "eAninmationFlags.h" #include "EntityInfo.h" +#include "RenderComponent.h" void FvMaelstromDragon::OnStartup(Entity* self) { self->SetVar(u"weakspot", 0); @@ -86,9 +87,9 @@ void FvMaelstromDragon::OnHitOrHealResult(Entity* self, Entity* attacker, int32_ self->SetVar(u"weakpoint", 2); GameMessages::SendChangeIdleFlags(self->GetObjectID(), eAnimationFlags::IDLE_NONE, eAnimationFlags::IDLE_COMBAT, UNASSIGNED_SYSTEM_ADDRESS); - GameMessages::SendPlayAnimation(self, u"stunstart", 1.7f); + RenderComponent::PlayAnimation(self, u"stunstart", 1.7f); - self->AddTimer("timeToStunLoop", 1); + self->AddTimer("timeToStunLoop", 1.0f); auto position = self->GetPosition(); auto forward = self->GetRotation().GetForwardVector(); @@ -137,10 +138,10 @@ void FvMaelstromDragon::OnTimerDone(Entity* self, std::string timerName) { } else if (timerName == "ExposeWeakSpotTimer") { self->SetVar(u"weakspot", 1); } else if (timerName == "timeToStunLoop") { - GameMessages::SendPlayAnimation(self, u"stunloop", 1.8f); + RenderComponent::PlayAnimation(self, u"stunloop", 1.8f); } else if (timerName == "ReviveTimer") { - GameMessages::SendPlayAnimation(self, u"stunend", 2.0f); - self->AddTimer("backToAttack", 1); + RenderComponent::PlayAnimation(self, u"stunend", 2.0f); + self->AddTimer("backToAttack", 1.0f); } else if (timerName == "backToAttack") { auto* baseCombatAIComponent = self->GetComponent(); auto* skillComponent = self->GetComponent(); @@ -174,5 +175,5 @@ FvMaelstromDragon::OnFireEventServerSide(Entity* self, Entity* sender, std::stri self->SetVar(u"Golem", sender->GetObjectID()); - GameMessages::SendPlayAnimation(self, u"quickbuildhold", 1.9f); + RenderComponent::PlayAnimation(self, u"quickbuildhold", 1.9f); } diff --git a/dScripts/02_server/Enemy/General/BaseEnemyApe.cpp b/dScripts/02_server/Enemy/General/BaseEnemyApe.cpp index e9863b17..19a6490a 100644 --- a/dScripts/02_server/Enemy/General/BaseEnemyApe.cpp +++ b/dScripts/02_server/Enemy/General/BaseEnemyApe.cpp @@ -6,6 +6,7 @@ #include "EntityInfo.h" #include "SkillComponent.h" #include "eAninmationFlags.h" +#include "RenderComponent.h" #include "eStateChangeType.h" void BaseEnemyApe::OnStartup(Entity* self) { @@ -38,7 +39,7 @@ void BaseEnemyApe::OnHit(Entity* self, Entity* attacker) { if (skillComponent) { skillComponent->Reset(); } - GameMessages::SendPlayAnimation(self, u"disable", 1.7f); + RenderComponent::PlayAnimation(self, u"disable", 1.7f); GameMessages::SendChangeIdleFlags(self->GetObjectID(), eAnimationFlags::IDLE_NONE, eAnimationFlags::IDLE_COMBAT, UNASSIGNED_SYSTEM_ADDRESS); const auto reviveTime = self->GetVar(u"reviveTime") != 0.0f ? self->GetVar(u"reviveTime") : 12.0f; diff --git a/dScripts/02_server/Enemy/General/GfApeSmashingQB.cpp b/dScripts/02_server/Enemy/General/GfApeSmashingQB.cpp index 5bba6450..40cc88f4 100644 --- a/dScripts/02_server/Enemy/General/GfApeSmashingQB.cpp +++ b/dScripts/02_server/Enemy/General/GfApeSmashingQB.cpp @@ -1,6 +1,8 @@ #include "GfApeSmashingQB.h" #include "EntityManager.h" #include "GameMessages.h" +#include "Entity.h" +#include "RenderComponent.h" void GfApeSmashingQB::OnStartup(Entity* self) { self->SetNetworkVar(u"lootTagOwner", self->GetVar(u"lootTagOwner")); @@ -16,7 +18,7 @@ void GfApeSmashingQB::OnRebuildComplete(Entity* self, Entity* target) { auto* ape = EntityManager::Instance()->GetEntity(self->GetVar(u"ape")); if (ape != nullptr) { ape->OnFireEventServerSide(target, "rebuildDone"); - GameMessages::SendPlayAnimation(self, u"smash", 1.7f); + RenderComponent::PlayAnimation(self, u"smash", 1.7f); self->AddTimer("anchorBreakTime", 1.0f); } } diff --git a/dScripts/02_server/Equipment/MaestromExtracticatorServer.cpp b/dScripts/02_server/Equipment/MaestromExtracticatorServer.cpp index c01d2362..4de8a998 100644 --- a/dScripts/02_server/Equipment/MaestromExtracticatorServer.cpp +++ b/dScripts/02_server/Equipment/MaestromExtracticatorServer.cpp @@ -4,19 +4,18 @@ #include "EntityManager.h" #include "MissionComponent.h" #include "eMissionTaskType.h" +#include "RenderComponent.h" void MaestromExtracticatorServer::OnStartup(Entity* self) { - //self:SetNetworkVar("current_anim", failAnim) - GameMessages::SendPlayAnimation(self, GeneralUtils::ASCIIToUTF16(failAnim)); + float animTime = RenderComponent::PlayAnimation(self, failAnim); + if (animTime == 0.0f) animTime = defaultTime; - self->AddTimer("PlayFail", defaultTime); + self->AddTimer("PlayFail", animTime); self->AddTimer("RemoveSample", destroyAfterNoSampleTime); } -void MaestromExtracticatorServer::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, - int32_t param2, int32_t param3) { - if (sender == nullptr) - return; +void MaestromExtracticatorServer::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2, int32_t param3) { + if (sender == nullptr) return; if (args == "attemptCollection") { Entity* player = EntityManager::Instance()->GetEntity(self->GetSpawnerID()); @@ -32,20 +31,17 @@ void MaestromExtracticatorServer::OnFireEventServerSide(Entity* self, Entity* se } void MaestromExtracticatorServer::CollectSample(Entity* self, LWOOBJID sampleObj) { - PlayAnimAndReturnTime(self, collectAnim); - self->AddTimer("RemoveSample", defaultTime); + self->AddTimer("RemoveSample", PlayAnimAndReturnTime(self, collectAnim)); } -void MaestromExtracticatorServer::PlayAnimAndReturnTime(Entity* self, std::string animID) { - GameMessages::SendPlayAnimation(self, GeneralUtils::ASCIIToUTF16(animID)); +float MaestromExtracticatorServer::PlayAnimAndReturnTime(Entity* self, std::string animID) { + return RenderComponent::PlayAnimation(self, animID); } void MaestromExtracticatorServer::OnTimerDone(Entity* self, std::string timerName) { if (timerName == "RemoveSample") { self->ScheduleKillAfterUpdate(); - } - - if (timerName == "PlayFail") { - GameMessages::SendPlayAnimation(self, GeneralUtils::ASCIIToUTF16(failAnim)); + } else if (timerName == "PlayFail") { + RenderComponent::PlayAnimation(self, failAnim); } } diff --git a/dScripts/02_server/Equipment/MaestromExtracticatorServer.h b/dScripts/02_server/Equipment/MaestromExtracticatorServer.h index c4adb51e..f0e976f3 100644 --- a/dScripts/02_server/Equipment/MaestromExtracticatorServer.h +++ b/dScripts/02_server/Equipment/MaestromExtracticatorServer.h @@ -7,7 +7,7 @@ public: void OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2, int32_t param3); void CollectSample(Entity* self, LWOOBJID sampleObj); - void PlayAnimAndReturnTime(Entity* self, std::string animID); + float PlayAnimAndReturnTime(Entity* self, std::string animID); void OnTimerDone(Entity* self, std::string timerName); private: diff --git a/dScripts/02_server/Map/AG/AgMonumentBirds.cpp b/dScripts/02_server/Map/AG/AgMonumentBirds.cpp index ad3417a4..9d4a3349 100644 --- a/dScripts/02_server/Map/AG/AgMonumentBirds.cpp +++ b/dScripts/02_server/Map/AG/AgMonumentBirds.cpp @@ -1,5 +1,8 @@ #include "AgMonumentBirds.h" #include "GameMessages.h" +#include "Entity.h" +#include "RenderComponent.h" +#include "EntityManager.h" //-------------------------------------------------------------- //Makes the ag birds fly away when you get close and smashes them. @@ -16,7 +19,7 @@ void AgMonumentBirds::OnProximityUpdate(Entity* self, Entity* entering, std::str if (name == "MonumentBirds" && status == "ENTER") { self->AddTimer("killBird", 1.0f); - GameMessages::SendPlayAnimation(self, sOnProximityAnim); + RenderComponent::PlayAnimation(self, sOnProximityAnim); self->SetVar(u"IsFlying", true); self->SetVar(u"PlayerID", entering->GetObjectID()); } diff --git a/dScripts/02_server/Map/AM/AmSkullkinDrill.cpp b/dScripts/02_server/Map/AM/AmSkullkinDrill.cpp index d26218a2..e35c700d 100644 --- a/dScripts/02_server/Map/AM/AmSkullkinDrill.cpp +++ b/dScripts/02_server/Map/AM/AmSkullkinDrill.cpp @@ -5,6 +5,7 @@ #include "ProximityMonitorComponent.h" #include "MissionComponent.h" #include "EntityInfo.h" +#include "RenderComponent.h" #include "eStateChangeType.h" void AmSkullkinDrill::OnStartup(Entity* self) { @@ -71,7 +72,7 @@ void AmSkullkinDrill::OnSkillEventFired(Entity* self, Entity* caster, const std: } void AmSkullkinDrill::TriggerDrill(Entity* self) { - GameMessages::SendPlayAnimation(self, u"slowdown"); + RenderComponent::PlayAnimation(self, u"slowdown"); self->AddTimer("killDrill", 10.0f); @@ -171,7 +172,7 @@ void AmSkullkinDrill::OnArrived(Entity* self, uint32_t waypointIndex) { auto* standObj = GetStandObj(self); if (waypointIndex == 1) { - GameMessages::SendPlayAnimation(self, u"no-spin"); + RenderComponent::PlayAnimation(self, u"no-spin"); GameMessages::SendStopFXEffect(self, true, "active"); GameMessages::SendPlayFXEffect(self->GetObjectID(), -1, u"indicator", "indicator"); @@ -191,7 +192,7 @@ void AmSkullkinDrill::OnArrived(Entity* self, uint32_t waypointIndex) { return; } else { - GameMessages::SendPlayAnimation(self, u"idle"); + RenderComponent::PlayAnimation(self, u"idle"); GameMessages::SendPlayFXEffect(self->GetObjectID(), -1, u"spin", "active"); GameMessages::SendStopFXEffect(self, true, "indicator"); } @@ -216,7 +217,7 @@ void AmSkullkinDrill::PlayCinematic(Entity* self) { void AmSkullkinDrill::PlayAnim(Entity* self, Entity* player, const std::string& animName) { const auto animTime = animName == "spinjitzu-staff-end" ? 0.5f : 1.0f; - GameMessages::SendPlayAnimation(player, GeneralUtils::ASCIIToUTF16(animName)); + RenderComponent::PlayAnimation(player, animName); self->AddTimer("AnimDone_" + animName, animTime); } @@ -309,7 +310,7 @@ void AmSkullkinDrill::OnTimerDone(Entity* self, std::string timerName) { if (animName == "spinjitzu-staff-windup") { TriggerDrill(self); - GameMessages::SendPlayAnimation(player, u"spinjitzu-staff-loop"); + RenderComponent::PlayAnimation(player, u"spinjitzu-staff-loop"); } else if (animName == "spinjitzu-staff-end") { FreezePlayer(self, player, false); diff --git a/dScripts/02_server/Map/AM/AmSkullkinDrillStand.cpp b/dScripts/02_server/Map/AM/AmSkullkinDrillStand.cpp index 628d616a..5493dc24 100644 --- a/dScripts/02_server/Map/AM/AmSkullkinDrillStand.cpp +++ b/dScripts/02_server/Map/AM/AmSkullkinDrillStand.cpp @@ -1,6 +1,8 @@ #include "AmSkullkinDrillStand.h" #include "GameMessages.h" #include "dpEntity.h" +#include "Entity.h" +#include "RenderComponent.h" void AmSkullkinDrillStand::OnStartup(Entity* self) { self->SetVar(u"bActive", true); @@ -31,5 +33,5 @@ void AmSkullkinDrillStand::OnProximityUpdate(Entity* self, Entity* entering, std GameMessages::SendPlayFXEffect(entering->GetObjectID(), 1378, u"create", "pushBack"); - GameMessages::SendPlayAnimation(entering, u"knockback-recovery"); + RenderComponent::PlayAnimation(entering, u"knockback-recovery"); } diff --git a/dScripts/02_server/Map/AM/AmSkullkinTower.cpp b/dScripts/02_server/Map/AM/AmSkullkinTower.cpp index 01acdeaf..f7825f8f 100644 --- a/dScripts/02_server/Map/AM/AmSkullkinTower.cpp +++ b/dScripts/02_server/Map/AM/AmSkullkinTower.cpp @@ -5,6 +5,7 @@ #include "EntityInfo.h" #include "GameMessages.h" #include "MissionComponent.h" +#include "RenderComponent.h" void AmSkullkinTower::OnStartup(Entity* self) { self->SetProximityRadius(20, "Tower"); @@ -117,13 +118,13 @@ void AmSkullkinTower::OnChildRemoved(Entity* self, Entity* child) { self->SetVar(u"legTable", legTable); if (legTable.size() == 2) { - GameMessages::SendPlayAnimation(self, u"wobble-1"); + RenderComponent::PlayAnimation(self, u"wobble-1"); } else if (legTable.size() == 1) { - GameMessages::SendPlayAnimation(self, u"wobble-2"); + RenderComponent::PlayAnimation(self, u"wobble-2"); } else if (legTable.empty()) { const auto animTime = 2.5f; - GameMessages::SendPlayAnimation(self, u"fall"); + RenderComponent::PlayAnimation(self, u"fall"); self->AddTimer("spawnGuys", animTime - 0.2f); diff --git a/dScripts/02_server/Map/GF/GfCaptainsCannon.cpp b/dScripts/02_server/Map/GF/GfCaptainsCannon.cpp index 13e2e4e5..c366d0fb 100644 --- a/dScripts/02_server/Map/GF/GfCaptainsCannon.cpp +++ b/dScripts/02_server/Map/GF/GfCaptainsCannon.cpp @@ -2,6 +2,7 @@ #include "GameMessages.h" #include "EntityManager.h" #include "MissionComponent.h" +#include "RenderComponent.h" #include "eTerminateType.h" #include "eStateChangeType.h" @@ -29,7 +30,7 @@ void GfCaptainsCannon::OnUse(Entity* self, Entity* user) { GameMessages::SendTeleport(user->GetObjectID(), position, rotation, user->GetSystemAddress()); - GameMessages::SendPlayAnimation(user, u"cannon-strike-no-equip"); + RenderComponent::PlayAnimation(user, u"cannon-strike-no-equip"); GameMessages::SendPlayFXEffect(user->GetObjectID(), 6039, u"hook", "hook", LWOOBJID_EMPTY, 1, 1, true); @@ -60,7 +61,7 @@ void GfCaptainsCannon::OnTimerDone(Entity* self, std::string timerName) { for (auto* shark : sharkObjects) { if (shark->GetLOT() != m_SharkItemID) continue; - GameMessages::SendPlayAnimation(shark, u"cannon"); + RenderComponent::PlayAnimation(shark, u"cannon"); } GameMessages::SendPlay2DAmbientSound(player, "{7457d85c-4537-4317-ac9d-2f549219ea87}"); diff --git a/dScripts/02_server/Map/GF/GfTikiTorch.cpp b/dScripts/02_server/Map/GF/GfTikiTorch.cpp index 8528192f..5d944f0f 100644 --- a/dScripts/02_server/Map/GF/GfTikiTorch.cpp +++ b/dScripts/02_server/Map/GF/GfTikiTorch.cpp @@ -5,6 +5,7 @@ #include "RenderComponent.h" #include "eMissionTaskType.h" #include "eReplicaComponentType.h" +#include "RenderComponent.h" #include "eTerminateType.h" void GfTikiTorch::OnStartup(Entity* self) { @@ -17,7 +18,7 @@ void GfTikiTorch::OnUse(Entity* self, Entity* killer) { return; } - GameMessages::SendPlayAnimation(self, u"interact"); + RenderComponent::PlayAnimation(self, u"interact"); self->SetI64(u"userID", killer->GetObjectID()); for (int i = 0; i < m_numspawn; i++) { @@ -56,7 +57,7 @@ void GfTikiTorch::LightTorch(Entity* self) { void GfTikiTorch::OnSkillEventFired(Entity* self, Entity* caster, const std::string& message) { if (self->GetBoolean(u"isBurning") && message == "waterspray") { - GameMessages::SendPlayAnimation(self, u"water"); + RenderComponent::PlayAnimation(self, u"water"); auto* renderComponent = self->GetComponent(); if (renderComponent != nullptr) { diff --git a/dScripts/02_server/Map/GF/MastTeleport.cpp b/dScripts/02_server/Map/GF/MastTeleport.cpp index 1447a6a0..311da34a 100644 --- a/dScripts/02_server/Map/GF/MastTeleport.cpp +++ b/dScripts/02_server/Map/GF/MastTeleport.cpp @@ -10,6 +10,7 @@ #define _USE_MATH_DEFINES #include #endif +#include "RenderComponent.h" void MastTeleport::OnStartup(Entity* self) { self->SetNetworkVar(u"hookPreconditions", "154;44", UNASSIGNED_SYSTEM_ADDRESS); @@ -63,11 +64,12 @@ void MastTeleport::OnTimerDone(Entity* self, std::string timerName) { GameMessages::SendPlayFXEffect(playerId, 6039, u"hook", "hook", LWOOBJID_EMPTY, 1, 1, true); - GameMessages::SendPlayAnimation(player, u"crow-swing-no-equip", 4.0f); + float animationTime = 6.25f; + animationTime = RenderComponent::PlayAnimation(player, "crow-swing-no-equip", 4.0f); - GameMessages::SendPlayAnimation(self, u"swing"); + RenderComponent::PlayAnimation(self, u"swing"); - self->AddTimer("PlayerAnimDone", 6.25f); + self->AddTimer("PlayerAnimDone", animationTime); } else if (timerName == "PlayerAnimDone") { GameMessages::SendStopFXEffect(player, true, "hook"); diff --git a/dScripts/02_server/Map/General/ExplodingAsset.cpp b/dScripts/02_server/Map/General/ExplodingAsset.cpp index 16340ee6..ee8f8e68 100644 --- a/dScripts/02_server/Map/General/ExplodingAsset.cpp +++ b/dScripts/02_server/Map/General/ExplodingAsset.cpp @@ -4,6 +4,7 @@ #include "MissionComponent.h" #include "SkillComponent.h" #include "eMissionTaskType.h" +#include "RenderComponent.h" //TODO: this has to be updated so that you only get killed if you're in a certain radius. //And so that all entities in a certain radius are killed, not just the attacker. @@ -69,23 +70,6 @@ void ExplodingAsset::OnHit(Entity* self, Entity* attacker) { } void ExplodingAsset::OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status) { - /* - if msg.objId:BelongsToFaction{factionID = 1}.bIsInFaction then - if (msg.status == "ENTER") then - self:PlayAnimation{ animationID = "bounce" } - self:PlayFXEffect{ name = "bouncin", effectType = "anim" } - self:SetVar("playersNearChest", (self:GetVar("playersNearChest") + 1 )) - elseif (msg.status == "LEAVE") then - self:SetVar("playersNearChest", (self:GetVar("playersNearChest") - 1 )) - if self:GetVar("playersNearChest") < 1 then - self:PlayAnimation{ animationID = "idle" } - self:StopFXEffect{ name = "bouncin" } - self:SetVar("playersNearChest", 0) - end - end - end - */ - auto* destuctableComponent = entering->GetComponent(); if (destuctableComponent == nullptr) return; @@ -95,14 +79,14 @@ void ExplodingAsset::OnProximityUpdate(Entity* self, Entity* entering, std::stri if (!std::count(factions.begin(), factions.end(), 1)) return; if (status == "ENTER") { - GameMessages::SendPlayAnimation(self, u"bounce"); + RenderComponent::PlayAnimation(self, u"bounce"); GameMessages::SendPlayFXEffect(self, -1, u"anim", "bouncin", LWOOBJID_EMPTY, 1, 1, true); self->SetVar(u"playersNearChest", self->GetVar(u"playersNearChest") + 1); } else if (status == "LEAVE") { self->SetVar(u"playersNearChest", self->GetVar(u"playersNearChest") - 1); if (self->GetVar(u"playersNearChest") < 1) { - GameMessages::SendPlayAnimation(self, u"idle"); + RenderComponent::PlayAnimation(self, u"idle"); GameMessages::SendStopFXEffect(self, true, "bouncin"); self->SetVar(u"playersNearChest", 0); } diff --git a/dScripts/02_server/Map/General/Ninjago/NjIceRailActivator.cpp b/dScripts/02_server/Map/General/Ninjago/NjIceRailActivator.cpp index 2549cd0f..8a9230d9 100644 --- a/dScripts/02_server/Map/General/Ninjago/NjIceRailActivator.cpp +++ b/dScripts/02_server/Map/General/Ninjago/NjIceRailActivator.cpp @@ -1,6 +1,8 @@ #include "NjIceRailActivator.h" #include "EntityManager.h" #include "GameMessages.h" +#include "Entity.h" +#include "RenderComponent.h" void NjIceRailActivator::OnPlayerRailArrived(Entity* self, Entity* sender, const std::u16string& pathName, int32_t waypoint) { @@ -9,7 +11,7 @@ void NjIceRailActivator::OnPlayerRailArrived(Entity* self, Entity* sender, const const auto& blockGroup = self->GetVar(BlockGroupVariable); for (auto* block : EntityManager::Instance()->GetEntitiesInGroup(GeneralUtils::UTF16ToWTF8(blockGroup))) { - GameMessages::SendPlayAnimation(block, u"explode"); + RenderComponent::PlayAnimation(block, u"explode"); const auto blockID = block->GetObjectID(); diff --git a/dScripts/02_server/Map/NT/NtAssemblyTubeServer.cpp b/dScripts/02_server/Map/NT/NtAssemblyTubeServer.cpp index 5f1619ab..99bc0de5 100644 --- a/dScripts/02_server/Map/NT/NtAssemblyTubeServer.cpp +++ b/dScripts/02_server/Map/NT/NtAssemblyTubeServer.cpp @@ -4,6 +4,7 @@ #include "MissionComponent.h" #include "eMissionTaskType.h" #include "eMissionState.h" +#include "RenderComponent.h" #include "eEndBehavior.h" #include "eStateChangeType.h" @@ -51,7 +52,7 @@ void NtAssemblyTubeServer::RunAssemblyTube(Entity* self, Entity* player) { ); } - GameMessages::SendPlayAnimation(player, u"tube-sucker", 4.0f); + RenderComponent::PlayAnimation(player, u"tube-sucker", 4.0f); const auto animTime = 3; @@ -84,7 +85,7 @@ void NtAssemblyTubeServer::TeleportPlayer(Entity* self, Entity* player) { GameMessages::SendTeleport(player->GetObjectID(), destPosition, destRotation, player->GetSystemAddress(), true); - GameMessages::SendPlayAnimation(player, u"tube-resurrect", 4.0f); + RenderComponent::PlayAnimation(player, u"tube-resurrect", 4.0f); const auto animTime = 2; diff --git a/dScripts/02_server/Map/NT/NtParadoxPanelServer.cpp b/dScripts/02_server/Map/NT/NtParadoxPanelServer.cpp index 23d336a7..dcae84d2 100644 --- a/dScripts/02_server/Map/NT/NtParadoxPanelServer.cpp +++ b/dScripts/02_server/Map/NT/NtParadoxPanelServer.cpp @@ -4,6 +4,7 @@ #include "EntityManager.h" #include "Character.h" #include "eMissionState.h" +#include "RenderComponent.h" #include "eTerminateType.h" #include "eStateChangeType.h" @@ -34,18 +35,18 @@ void NtParadoxPanelServer::OnUse(Entity* self, Entity* user) { player->GetCharacter()->SetPlayerFlag(flag, true); - GameMessages::SendPlayAnimation(player, u"rebuild-celebrate"); + RenderComponent::PlayAnimation(player, u"rebuild-celebrate"); GameMessages::SendNotifyClientObject(self->GetObjectID(), u"SparkStop", 0, 0, player->GetObjectID(), "", player->GetSystemAddress()); GameMessages::SendSetStunned(player->GetObjectID(), eStateChangeType::POP, player->GetSystemAddress(), LWOOBJID_EMPTY, false, false, true, false, true, true, false, false, true); self->SetVar(u"bActive", false); }); - GameMessages::SendPlayAnimation(user, u"nexus-powerpanel", 6.0f); + RenderComponent::PlayAnimation(user, u"nexus-powerpanel", 6.0f); GameMessages::SendSetStunned(user->GetObjectID(), eStateChangeType::PUSH, user->GetSystemAddress(), LWOOBJID_EMPTY, false, false, true, false, true, true, false, false, true); return; } - GameMessages::SendPlayAnimation(user, shockAnim); + RenderComponent::PlayAnimation(user, shockAnim); const auto dir = self->GetRotation().GetRightVector(); diff --git a/dScripts/02_server/Map/NT/NtParadoxTeleServer.cpp b/dScripts/02_server/Map/NT/NtParadoxTeleServer.cpp index b19c8c0b..687a3477 100644 --- a/dScripts/02_server/Map/NT/NtParadoxTeleServer.cpp +++ b/dScripts/02_server/Map/NT/NtParadoxTeleServer.cpp @@ -3,6 +3,7 @@ #include "EntityManager.h" #include "MissionComponent.h" #include "eMissionTaskType.h" +#include "RenderComponent.h" #include "eStateChangeType.h" void NtParadoxTeleServer::OnStartup(Entity* self) { @@ -28,9 +29,8 @@ void NtParadoxTeleServer::OnProximityUpdate(Entity* self, Entity* entering, std: true, true, true, true, true, true, true ); - GameMessages::SendPlayAnimation(player, u"teledeath", 4.0f); - - const auto animTime = 2; + auto animTime = RenderComponent::PlayAnimation(player, u"teledeath", 4.0f); + if (animTime == 0.0f) animTime = 2.0f; self->AddCallbackTimer(animTime, [this, self, playerID]() { auto* player = EntityManager::Instance()->GetEntity(playerID); @@ -74,7 +74,7 @@ void NtParadoxTeleServer::TeleportPlayer(Entity* self, Entity* player) { GameMessages::SendTeleport(player->GetObjectID(), destPosition, destRotation, player->GetSystemAddress(), true); - GameMessages::SendPlayAnimation(player, u"paradox-teleport-in", 4.0f); + RenderComponent::PlayAnimation(player, u"paradox-teleport-in", 4.0f); const auto animTime = 2; diff --git a/dScripts/02_server/Map/NT/NtSleepingGuard.cpp b/dScripts/02_server/Map/NT/NtSleepingGuard.cpp index 145df6c8..92a80582 100644 --- a/dScripts/02_server/Map/NT/NtSleepingGuard.cpp +++ b/dScripts/02_server/Map/NT/NtSleepingGuard.cpp @@ -1,6 +1,7 @@ #include "NtSleepingGuard.h" #include "GameMessages.h" #include "MissionComponent.h" +#include "RenderComponent.h" void NtSleepingGuard::OnStartup(Entity* self) { self->SetNetworkVar(u"asleep", true); @@ -17,7 +18,7 @@ void NtSleepingGuard::OnEmoteReceived(Entity* self, const int32_t emote, Entity* // Set asleep to false self->SetNetworkVar(u"asleep", false); - GameMessages::SendPlayAnimation(self, u"greet"); + RenderComponent::PlayAnimation(self, u"greet"); auto* missionComponent = target->GetComponent(); diff --git a/dScripts/02_server/Map/NT/NtVentureCannonServer.cpp b/dScripts/02_server/Map/NT/NtVentureCannonServer.cpp index 38f929a1..976cc24f 100644 --- a/dScripts/02_server/Map/NT/NtVentureCannonServer.cpp +++ b/dScripts/02_server/Map/NT/NtVentureCannonServer.cpp @@ -1,6 +1,9 @@ #include "NtVentureCannonServer.h" #include "GameMessages.h" #include "EntityManager.h" +#include "Entity.h" +#include "GeneralUtils.h" +#include "RenderComponent.h" #include "eEndBehavior.h" #include "eTerminateType.h" #include "eStateChangeType.h" @@ -29,7 +32,7 @@ void NtVentureCannonServer::OnUse(Entity* self, Entity* user) { GameMessages::SendTeleport(playerID, destPosition, destRotation, player->GetSystemAddress(), true); - GameMessages::SendPlayAnimation(player, u"scale-down", 4.0f); + RenderComponent::PlayAnimation(player, u"scale-down", 4.0f); const auto enterCinematicUname = enterCinematic; GameMessages::SendPlayCinematic(player->GetObjectID(), enterCinematicUname, player->GetSystemAddress()); @@ -121,5 +124,5 @@ void NtVentureCannonServer::FirePlayer(Entity* self, Entity* player) { GameMessages::SendTeleport(player->GetObjectID(), destPosition, destRotation, player->GetSystemAddress(), true); - GameMessages::SendPlayAnimation(player, u"venture-cannon-out", 4.0f); + RenderComponent::PlayAnimation(player, u"venture-cannon-out", 4.0f); } diff --git a/dScripts/02_server/Map/njhub/CatapultBaseServer.cpp b/dScripts/02_server/Map/njhub/CatapultBaseServer.cpp index 2df32658..270e7f40 100644 --- a/dScripts/02_server/Map/njhub/CatapultBaseServer.cpp +++ b/dScripts/02_server/Map/njhub/CatapultBaseServer.cpp @@ -1,6 +1,8 @@ #include "CatapultBaseServer.h" #include "GameMessages.h" #include "EntityManager.h" +#include "Entity.h" +#include "RenderComponent.h" void CatapultBaseServer::OnNotifyObject(Entity* self, Entity* sender, const std::string& name, int32_t param1, int32_t param2) { if (name == "BouncerBuilt") { @@ -21,7 +23,7 @@ void CatapultBaseServer::OnTimerDone(Entity* self, std::string timerName) { // tell the arm to the play the platform animation, which is just the arm laying there but with bouncer for (auto* obj : arm) { - GameMessages::SendPlayAnimation(obj, u"idle-platform"); + RenderComponent::PlayAnimation(obj, u"idle-platform"); GameMessages::SendPlayNDAudioEmitter(obj, UNASSIGNED_SYSTEM_ADDRESS, "{8cccf912-69e3-4041-a20b-63e4afafc993}"); // set the art so we can use it again self->SetVar(u"Arm", obj->GetObjectID()); @@ -38,7 +40,7 @@ void CatapultBaseServer::OnTimerDone(Entity* self, std::string timerName) { // tell the arm to player the launcher animation auto animTime = 1; self->AddTimer("resetArm", animTime); - GameMessages::SendPlayAnimation(arm, u"launch"); + RenderComponent::PlayAnimation(arm, u"launch"); } else if (timerName == "bounce") { auto* bouncer = EntityManager::Instance()->GetEntity(self->GetVar(u"Bouncer")); if (bouncer == nullptr) return; @@ -52,7 +54,7 @@ void CatapultBaseServer::OnTimerDone(Entity* self, std::string timerName) { if (arm == nullptr) return; // set the arm back to natural state - GameMessages::SendPlayAnimation(arm, u"idle"); + RenderComponent::PlayAnimation(arm, u"idle"); auto* bouncer = EntityManager::Instance()->GetEntity(self->GetVar(u"Bouncer")); if (bouncer == nullptr) return; diff --git a/dScripts/02_server/Map/njhub/CavePrisonCage.cpp b/dScripts/02_server/Map/njhub/CavePrisonCage.cpp index 60bd1b88..d04fc03d 100644 --- a/dScripts/02_server/Map/njhub/CavePrisonCage.cpp +++ b/dScripts/02_server/Map/njhub/CavePrisonCage.cpp @@ -4,6 +4,7 @@ #include "GameMessages.h" #include "Character.h" #include "dZoneManager.h" +#include "RenderComponent.h" void CavePrisonCage::OnStartup(Entity* self) { const auto& myNum = self->GetVar(u"myNumber"); @@ -101,7 +102,7 @@ void CavePrisonCage::SpawnCounterweight(Entity* self, Spawner* spawner) { } // Play the 'down' animation on the button - GameMessages::SendPlayAnimation(button, u"down"); + RenderComponent::PlayAnimation(button, u"down"); // Setup a timer named 'buttonGoingDown' to be triggered in 5 seconds self->AddTimer("buttonGoingDown", 5.0f); @@ -136,13 +137,13 @@ void CavePrisonCage::OnTimerDone(Entity* self, std::string timerName) { // the anim of the button down is over if (timerName == "buttonGoingDown") { // Play the 'up' animation - GameMessages::SendPlayAnimation(self, u"up"); + RenderComponent::PlayAnimation(self, u"up"); // Setup a timer named 'CageOpen' to be triggered in 1 second self->AddTimer("CageOpen", 1.0f); } else if (timerName == "CageOpen") { // play the idle open anim - GameMessages::SendPlayAnimation(self, u"idle-up"); + RenderComponent::PlayAnimation(self, u"idle-up"); // Get the villeger auto* villager = EntityManager::Instance()->GetEntity(self->GetVar(u"villager")); @@ -199,13 +200,13 @@ void CavePrisonCage::OnTimerDone(Entity* self, std::string timerName) { } // Play the 'up' animation on the button - GameMessages::SendPlayAnimation(button, u"up"); + RenderComponent::PlayAnimation(button, u"up"); // Setup a timer named 'CageClosed' to be triggered in 1 second self->AddTimer("CageClosed", 1.0f); } else if (timerName == "CageClosed") { // play the idle closed anim - GameMessages::SendPlayAnimation(self, u"idle"); + RenderComponent::PlayAnimation(self, u"idle"); // Setup a timer named 'ResetPrison' to be triggered in 10 seconds self->AddTimer("ResetPrison", 10.0f); diff --git a/dScripts/02_server/Map/njhub/boss_instance/NjMonastryBossInstance.cpp b/dScripts/02_server/Map/njhub/boss_instance/NjMonastryBossInstance.cpp index 4de7638f..9f129ce3 100644 --- a/dScripts/02_server/Map/njhub/boss_instance/NjMonastryBossInstance.cpp +++ b/dScripts/02_server/Map/njhub/boss_instance/NjMonastryBossInstance.cpp @@ -9,6 +9,7 @@ #include "SkillComponent.h" #include "TeamManager.h" #include +#include "RenderComponent.h" // // // // // // // // Event handling // @@ -261,7 +262,7 @@ void NjMonastryBossInstance::HandleCounterWeightSpawned(Entity* self, Entity* co skillComponent->CalculateBehavior(1635, 39097, frakjaw->GetObjectID(), true, false); } - GameMessages::SendPlayAnimation(frakjaw, StunnedAnimation); + RenderComponent::PlayAnimation(frakjaw, StunnedAnimation); GameMessages::SendPlayNDAudioEmitter(frakjaw, UNASSIGNED_SYSTEM_ADDRESS, CounterSmashAudio); // Before wave 4 we should lower frakjaw from the ledge @@ -281,7 +282,7 @@ void NjMonastryBossInstance::HandleCounterWeightSpawned(Entity* self, Entity* co } void NjMonastryBossInstance::HandleLowerFrakjawSpawned(Entity* self, Entity* lowerFrakjaw) { - GameMessages::SendPlayAnimation(lowerFrakjaw, TeleportInAnimation); + RenderComponent::PlayAnimation(lowerFrakjaw, TeleportInAnimation); self->SetVar(LowerFrakjawVariable, lowerFrakjaw->GetObjectID()); auto* combatAI = lowerFrakjaw->GetComponent(); @@ -401,7 +402,7 @@ void NjMonastryBossInstance::TeleportPlayer(Entity* player, uint32_t position) { void NjMonastryBossInstance::SummonWave(Entity* self, Entity* frakjaw) { GameMessages::SendNotifyClientObject(self->GetObjectID(), PlayCinematicNotification, 0, 0, LWOOBJID_EMPTY, LedgeFrakSummon, UNASSIGNED_SYSTEM_ADDRESS); - GameMessages::SendPlayAnimation(frakjaw, SummonAnimation); + RenderComponent::PlayAnimation(frakjaw, SummonAnimation); // Stop the music for the first, fourth and fifth wave const auto wave = self->GetVar(WaveNumberVariable); @@ -425,7 +426,7 @@ void NjMonastryBossInstance::LowerFrakjawSummon(Entity* self, Entity* frakjaw) { GameMessages::SendNotifyClientObject(self->GetObjectID(), PlayCinematicNotification, 0, 0, LWOOBJID_EMPTY, BottomFrakSummon, UNASSIGNED_SYSTEM_ADDRESS); ActivityTimerStart(self, SpawnWaveTimer, 2.0f, 2.0f); - GameMessages::SendPlayAnimation(frakjaw, SummonAnimation); + RenderComponent::PlayAnimation(frakjaw, SummonAnimation); } void NjMonastryBossInstance::RemovePoison(Entity* self) { @@ -444,7 +445,7 @@ void NjMonastryBossInstance::RemovePoison(Entity* self) { } void NjMonastryBossInstance::LowerFrakjaw(Entity* self, Entity* frakjaw) { - GameMessages::SendPlayAnimation(frakjaw, TeleportOutAnimation); + RenderComponent::PlayAnimation(frakjaw, TeleportOutAnimation); ActivityTimerStart(self, LowerFrakjawCamTimer, 2.0f, 2.0f); GameMessages::SendNotifyClientObject(frakjaw->GetObjectID(), StopMusicNotification, 0, 0, diff --git a/dScripts/BaseConsoleTeleportServer.cpp b/dScripts/BaseConsoleTeleportServer.cpp index 4a059535..e04500b5 100644 --- a/dScripts/BaseConsoleTeleportServer.cpp +++ b/dScripts/BaseConsoleTeleportServer.cpp @@ -1,6 +1,8 @@ #include "BaseConsoleTeleportServer.h" #include "GameMessages.h" #include "Player.h" +#include "RenderComponent.h" +#include "EntityManager.h" #include "eTerminateType.h" #include "eStateChangeType.h" @@ -33,13 +35,11 @@ void BaseConsoleTeleportServer::BaseOnMessageBoxResponse(Entity* self, Entity* s } const auto& teleIntroAnim = self->GetVar(u"teleportAnim"); - + auto animTime = 3.32999992370605f; if (!teleIntroAnim.empty()) { - GameMessages::SendPlayAnimation(player, teleIntroAnim); + animTime = RenderComponent::PlayAnimation(player, teleIntroAnim); } - const auto animTime = 3.32999992370605f; - UpdatePlayerTable(self, player, true); const auto playerID = player->GetObjectID(); diff --git a/dScripts/ai/AG/AgFans.cpp b/dScripts/ai/AG/AgFans.cpp index e05fe68d..aaff9c0d 100644 --- a/dScripts/ai/AG/AgFans.cpp +++ b/dScripts/ai/AG/AgFans.cpp @@ -5,6 +5,8 @@ #include "PhantomPhysicsComponent.h" #include "RenderComponent.h" #include "eReplicaComponentType.h" +#include "RenderComponent.h" +#include "Entity.h" void AgFans::OnStartup(Entity* self) { self->SetVar(u"alive", true); @@ -34,7 +36,7 @@ void AgFans::ToggleFX(Entity* self, bool hit) { if (fanVolumes.size() == 0 || !self->GetVar(u"alive")) return; if (self->GetVar(u"on")) { - GameMessages::SendPlayAnimation(self, u"fan-off"); + RenderComponent::PlayAnimation(self, u"fan-off"); renderComponent->StopEffect("fanOn"); self->SetVar(u"on", false); @@ -46,11 +48,11 @@ void AgFans::ToggleFX(Entity* self, bool hit) { EntityManager::Instance()->SerializeEntity(volume); if (!hit) { Entity* fxObj = EntityManager::Instance()->GetEntitiesInGroup(fanGroup + "fx")[0]; - GameMessages::SendPlayAnimation(fxObj, u"trigger"); + RenderComponent::PlayAnimation(fxObj, u"trigger"); } } } else if (!self->GetVar(u"on") && self->GetVar(u"alive")) { - GameMessages::SendPlayAnimation(self, u"fan-on"); + RenderComponent::PlayAnimation(self, u"fan-on"); renderComponent->PlayEffect(495, u"fanOn", "fanOn"); self->SetVar(u"on", true); @@ -62,7 +64,7 @@ void AgFans::ToggleFX(Entity* self, bool hit) { EntityManager::Instance()->SerializeEntity(volume); if (!hit) { Entity* fxObj = EntityManager::Instance()->GetEntitiesInGroup(fanGroup + "fx")[0]; - GameMessages::SendPlayAnimation(fxObj, u"idle"); + RenderComponent::PlayAnimation(fxObj, u"idle"); } } } diff --git a/dScripts/ai/AG/AgJetEffectServer.cpp b/dScripts/ai/AG/AgJetEffectServer.cpp index 3d132991..0a26069e 100644 --- a/dScripts/ai/AG/AgJetEffectServer.cpp +++ b/dScripts/ai/AG/AgJetEffectServer.cpp @@ -3,6 +3,7 @@ #include "EntityManager.h" #include "SkillComponent.h" #include "eReplicaComponentType.h" +#include "RenderComponent.h" void AgJetEffectServer::OnUse(Entity* self, Entity* user) { if (inUse || self->GetLOT() != 6859) return; @@ -23,7 +24,7 @@ void AgJetEffectServer::OnRebuildComplete(Entity* self, Entity* target) { if (self->GetLOT() != 6209) return; auto entities = EntityManager::Instance()->GetEntitiesInGroup("Jet_FX"); if (entities.empty()) return; - GameMessages::SendPlayAnimation(entities.at(0), u"jetFX"); + RenderComponent::PlayAnimation(entities.at(0), u"jetFX"); // So we can give kill credit to person who build this builder = target->GetObjectID(); diff --git a/dScripts/ai/AG/AgSalutingNpcs.cpp b/dScripts/ai/AG/AgSalutingNpcs.cpp index 4e4d8b2c..d3bbe9ab 100644 --- a/dScripts/ai/AG/AgSalutingNpcs.cpp +++ b/dScripts/ai/AG/AgSalutingNpcs.cpp @@ -1,11 +1,10 @@ #include "AgSalutingNpcs.h" -#include "GameMessages.h" - +#include "RenderComponent.h" void AgSalutingNpcs::OnEmoteReceived(Entity* self, const int32_t emote, Entity* target) { if (emote != 356) { return; } - GameMessages::SendPlayAnimation(self, u"salutePlayer"); + RenderComponent::PlayAnimation(self, u"salutePlayer"); } diff --git a/dScripts/ai/AG/AgShipPlayerShockServer.cpp b/dScripts/ai/AG/AgShipPlayerShockServer.cpp index 9e6c90d4..e14d48ae 100644 --- a/dScripts/ai/AG/AgShipPlayerShockServer.cpp +++ b/dScripts/ai/AG/AgShipPlayerShockServer.cpp @@ -1,5 +1,7 @@ #include "AgShipPlayerShockServer.h" #include "GameMessages.h" +#include "RenderComponent.h" +#include "Entity.h" #include "eTerminateType.h" void AgShipPlayerShockServer::OnUse(Entity* self, Entity* user) { @@ -8,7 +10,7 @@ void AgShipPlayerShockServer::OnUse(Entity* self, Entity* user) { return; } active = true; - GameMessages::SendPlayAnimation(user, shockAnim); + RenderComponent::PlayAnimation(user, shockAnim); GameMessages::SendKnockback(user->GetObjectID(), self->GetObjectID(), self->GetObjectID(), 0, NiPoint3(-20, 10, -20)); GameMessages::SendPlayFXEffect(self, 1430, u"create", "console_sparks", LWOOBJID_EMPTY, 1.0, 1.0, true); diff --git a/dScripts/ai/AG/AgSpaceStuff.cpp b/dScripts/ai/AG/AgSpaceStuff.cpp index 30929ebf..0887608e 100644 --- a/dScripts/ai/AG/AgSpaceStuff.cpp +++ b/dScripts/ai/AG/AgSpaceStuff.cpp @@ -3,6 +3,8 @@ #include "GeneralUtils.h" #include "GameMessages.h" #include "EntityManager.h" +#include "RenderComponent.h" +#include "Entity.h" void AgSpaceStuff::OnStartup(Entity* self) { self->AddTimer("FloaterScale", 5.0f); @@ -27,13 +29,13 @@ void AgSpaceStuff::OnTimerDone(Entity* self, std::string timerName) { if (timerName == "FloaterScale") { int scaleType = GeneralUtils::GenerateRandomNumber(1, 5); - GameMessages::SendPlayAnimation(self, u"scale_0" + GeneralUtils::to_u16string(scaleType)); + RenderComponent::PlayAnimation(self, u"scale_0" + GeneralUtils::to_u16string(scaleType)); self->AddTimer("FloaterPath", 0.4); } else if (timerName == "FloaterPath") { int pathType = GeneralUtils::GenerateRandomNumber(1, 4); int randTime = GeneralUtils::GenerateRandomNumber(20, 25); - GameMessages::SendPlayAnimation(self, u"path_0" + (GeneralUtils::to_u16string(pathType))); + RenderComponent::PlayAnimation(self, u"path_0" + (GeneralUtils::to_u16string(pathType))); self->AddTimer("FloaterScale", randTime); } else if (timerName == "ShipShakeExplode") { DoShake(self, true); @@ -76,16 +78,16 @@ void AgSpaceStuff::DoShake(Entity* self, bool explodeIdle) { auto* shipFxObject2 = GetEntityInGroup(ShipFX2); if (shipFxObject2) - GameMessages::SendPlayAnimation(shipFxObject2, u"explosion"); + RenderComponent::PlayAnimation(shipFxObject2, u"explosion"); } else { auto* shipFxObject = GetEntityInGroup(ShipFX); auto* shipFxObject2 = GetEntityInGroup(ShipFX2); if (shipFxObject) - GameMessages::SendPlayAnimation(shipFxObject, u"idle"); + RenderComponent::PlayAnimation(shipFxObject, u"idle"); if (shipFxObject2) - GameMessages::SendPlayAnimation(shipFxObject2, u"idle"); + RenderComponent::PlayAnimation(shipFxObject2, u"idle"); } } diff --git a/dScripts/ai/FV/FvDragonSmashingGolemQb.cpp b/dScripts/ai/FV/FvDragonSmashingGolemQb.cpp index 9cf7fa18..8f2133a9 100644 --- a/dScripts/ai/FV/FvDragonSmashingGolemQb.cpp +++ b/dScripts/ai/FV/FvDragonSmashingGolemQb.cpp @@ -1,6 +1,8 @@ #include "FvDragonSmashingGolemQb.h" #include "GameMessages.h" #include "EntityManager.h" +#include "RenderComponent.h" +#include "Entity.h" #include "eRebuildState.h" void FvDragonSmashingGolemQb::OnStartup(Entity* self) { @@ -15,7 +17,7 @@ void FvDragonSmashingGolemQb::OnTimerDone(Entity* self, std::string timerName) { void FvDragonSmashingGolemQb::OnRebuildNotifyState(Entity* self, eRebuildState state) { if (state == eRebuildState::COMPLETED) { - GameMessages::SendPlayAnimation(self, u"dragonsmash"); + RenderComponent::PlayAnimation(self, u"dragonsmash"); const auto dragonId = self->GetVar(u"Dragon"); diff --git a/dScripts/ai/FV/FvFlyingCreviceDragon.cpp b/dScripts/ai/FV/FvFlyingCreviceDragon.cpp index 16eda512..cb0fe3d0 100644 --- a/dScripts/ai/FV/FvFlyingCreviceDragon.cpp +++ b/dScripts/ai/FV/FvFlyingCreviceDragon.cpp @@ -3,6 +3,7 @@ #include "EntityManager.h" #include "SkillComponent.h" #include "GeneralUtils.h" +#include "RenderComponent.h" void FvFlyingCreviceDragon::OnStartup(Entity* self) { self->AddTimer("waypoint", 5); @@ -67,10 +68,10 @@ void FvFlyingCreviceDragon::OnArrived(Entity* self) { auto point = self->GetVar(u"waypoint"); if (point == 4) { - GameMessages::SendPlayAnimation(self, u"attack1", 2); + RenderComponent::PlayAnimation(self, u"attack1", 2.0f); self->AddTimer("platform1attack", 1.75f); } else if (point == 12) { - GameMessages::SendPlayAnimation(self, u"attack2", 2); + RenderComponent::PlayAnimation(self, u"attack2", 2.0f); const auto& group2 = EntityManager::Instance()->GetEntitiesInGroup("dragonFireballs2"); @@ -101,7 +102,7 @@ void FvFlyingCreviceDragon::OnArrived(Entity* self) { } } } else if (point == 16) { - GameMessages::SendPlayAnimation(self, u"attack3", 2); + RenderComponent::PlayAnimation(self, u"attack3", 2.0f); self->AddTimer("platform3attack", 0.5f); } } diff --git a/dScripts/ai/FV/FvNinjaGuard.cpp b/dScripts/ai/FV/FvNinjaGuard.cpp index 58267999..c487f5cc 100644 --- a/dScripts/ai/FV/FvNinjaGuard.cpp +++ b/dScripts/ai/FV/FvNinjaGuard.cpp @@ -1,6 +1,8 @@ #include "FvNinjaGuard.h" #include "GameMessages.h" #include "MissionComponent.h" +#include "RenderComponent.h" +#include "EntityManager.h" void FvNinjaGuard::OnStartup(Entity* self) { if (self->GetLOT() == 7412) { @@ -12,24 +14,24 @@ void FvNinjaGuard::OnStartup(Entity* self) { void FvNinjaGuard::OnEmoteReceived(Entity* self, const int32_t emote, Entity* target) { if (emote != 392) { - GameMessages::SendPlayAnimation(self, u"no"); + RenderComponent::PlayAnimation(self, u"no"); return; } - GameMessages::SendPlayAnimation(self, u"scared"); + RenderComponent::PlayAnimation(self, u"scared"); if (self->GetLOT() == 7412) { auto* rightGuard = EntityManager::Instance()->GetEntity(m_RightGuard); if (rightGuard != nullptr) { - GameMessages::SendPlayAnimation(rightGuard, u"laugh_rt"); + RenderComponent::PlayAnimation(rightGuard, u"laugh_rt"); } } else if (self->GetLOT() == 11128) { auto* leftGuard = EntityManager::Instance()->GetEntity(m_LeftGuard); if (leftGuard != nullptr) { - GameMessages::SendPlayAnimation(leftGuard, u"laugh_lt"); + RenderComponent::PlayAnimation(leftGuard, u"laugh_lt"); } } } diff --git a/dScripts/ai/GENERAL/LegoDieRoll.cpp b/dScripts/ai/GENERAL/LegoDieRoll.cpp index 18082065..763a4704 100644 --- a/dScripts/ai/GENERAL/LegoDieRoll.cpp +++ b/dScripts/ai/GENERAL/LegoDieRoll.cpp @@ -2,6 +2,7 @@ #include "Entity.h" #include "GameMessages.h" #include "MissionComponent.h" +#include "RenderComponent.h" #include "eMissionState.h" void LegoDieRoll::OnStartup(Entity* self) { @@ -17,23 +18,23 @@ void LegoDieRoll::OnTimerDone(Entity* self, std::string timerName) { switch (dieRoll) { case 1: - GameMessages::SendPlayAnimation(self, u"roll-die-1"); + RenderComponent::PlayAnimation(self, u"roll-die-1"); break; case 2: - GameMessages::SendPlayAnimation(self, u"roll-die-2"); + RenderComponent::PlayAnimation(self, u"roll-die-2"); break; case 3: - GameMessages::SendPlayAnimation(self, u"roll-die-3"); + RenderComponent::PlayAnimation(self, u"roll-die-3"); break; case 4: - GameMessages::SendPlayAnimation(self, u"roll-die-4"); + RenderComponent::PlayAnimation(self, u"roll-die-4"); break; case 5: - GameMessages::SendPlayAnimation(self, u"roll-die-5"); + RenderComponent::PlayAnimation(self, u"roll-die-5"); break; case 6: { - GameMessages::SendPlayAnimation(self, u"roll-die-6"); + RenderComponent::PlayAnimation(self, u"roll-die-6"); // tracking the It's Truly Random Achievement auto* owner = self->GetOwner(); auto* missionComponent = owner->GetComponent(); diff --git a/dScripts/ai/GF/GfOrgan.cpp b/dScripts/ai/GF/GfOrgan.cpp index 372ed3a2..3184aa82 100644 --- a/dScripts/ai/GF/GfOrgan.cpp +++ b/dScripts/ai/GF/GfOrgan.cpp @@ -1,5 +1,7 @@ #include "GfOrgan.h" #include "GameMessages.h" +#include "Entity.h" +#include "RenderComponent.h" void GfOrgan::OnUse(Entity* self, Entity* user) { if (self->GetBoolean(u"bIsInUse")) { @@ -11,7 +13,7 @@ void GfOrgan::OnUse(Entity* self, Entity* user) { self->SetBoolean(u"bIsInUse", true); self->AddTimer("reset", 5.0f); - GameMessages::SendPlayAnimation(user, u"jig"); + RenderComponent::PlayAnimation(user, u"jig"); } void GfOrgan::OnTimerDone(Entity* self, std::string timerName) { diff --git a/dScripts/ai/MINIGAME/SG_GF/SERVER/SGCannon.cpp b/dScripts/ai/MINIGAME/SG_GF/SERVER/SGCannon.cpp index c3274da1..9543504a 100644 --- a/dScripts/ai/MINIGAME/SG_GF/SERVER/SGCannon.cpp +++ b/dScripts/ai/MINIGAME/SG_GF/SERVER/SGCannon.cpp @@ -15,6 +15,7 @@ #include "InventoryComponent.h" #include "eMissionTaskType.h" #include "eReplicaComponentType.h" +#include "RenderComponent.h" #include "eGameActivity.h" void SGCannon::OnStartup(Entity* self) { @@ -508,17 +509,17 @@ void SGCannon::RecordPlayerScore(Entity* self) { void SGCannon::PlaySceneAnimation(Entity* self, const std::u16string& animationName, bool onCannon, bool onPlayer, float_t priority) { for (auto* cannon : EntityManager::Instance()->GetEntitiesInGroup("cannongroup")) { - GameMessages::SendPlayAnimation(cannon, animationName, priority); + RenderComponent::PlayAnimation(cannon, animationName, priority); } if (onCannon) { - GameMessages::SendPlayAnimation(self, animationName, priority); + RenderComponent::PlayAnimation(self, animationName, priority); } if (onPlayer) { auto* player = EntityManager::Instance()->GetEntity(self->GetVar(PlayerIDVariable)); if (player != nullptr) { - GameMessages::SendPlayAnimation(player, animationName, priority); + RenderComponent::PlayAnimation(player, animationName, priority); } } } diff --git a/dScripts/ai/NS/NsConcertInstrument.cpp b/dScripts/ai/NS/NsConcertInstrument.cpp index 7db1ca16..ba99d4d1 100644 --- a/dScripts/ai/NS/NsConcertInstrument.cpp +++ b/dScripts/ai/NS/NsConcertInstrument.cpp @@ -9,6 +9,7 @@ #include "MissionComponent.h" #include "eMissionState.h" #include "eMissionTaskType.h" +#include "RenderComponent.h" // Constants are at the bottom @@ -122,7 +123,7 @@ void NsConcertInstrument::StartPlayingInstrument(Entity* self, Entity* player) { player->GetObjectID(), "", UNASSIGNED_SYSTEM_ADDRESS); GameMessages::SendPlayCinematic(player->GetObjectID(), cinematics.at(instrumentLot), UNASSIGNED_SYSTEM_ADDRESS); self->AddCallbackTimer(1.0f, [player, instrumentLot]() { - GameMessages::SendPlayAnimation(player, animations.at(instrumentLot), 2.0f); + RenderComponent::PlayAnimation(player, animations.at(instrumentLot), 2.0f); }); for (auto* soundBox : EntityManager::Instance()->GetEntitiesInGroup("Audio-Concert")) { @@ -153,7 +154,7 @@ void NsConcertInstrument::StopPlayingInstrument(Entity* self, Entity* player) { } GameMessages::SendEndCinematic(player->GetObjectID(), cinematics.at(instrumentLot), UNASSIGNED_SYSTEM_ADDRESS, 1.0f); - GameMessages::SendPlayAnimation(player, smashAnimations.at(instrumentLot), 2.0f); + RenderComponent::PlayAnimation(player, smashAnimations.at(instrumentLot), 2.0f); GameMessages::SendNotifyClientObject(self->GetObjectID(), u"stopCheckingMovement", 0, 0, player->GetObjectID(), "", UNASSIGNED_SYSTEM_ADDRESS); } diff --git a/dScripts/ai/NS/WhFans.cpp b/dScripts/ai/NS/WhFans.cpp index 44354127..8500e824 100644 --- a/dScripts/ai/NS/WhFans.cpp +++ b/dScripts/ai/NS/WhFans.cpp @@ -4,6 +4,8 @@ #include "GameMessages.h" #include "EntityManager.h" #include "PhantomPhysicsComponent.h" +#include "RenderComponent.h" +#include "Entity.h" void WhFans::OnStartup(Entity* self) { self->SetVar(u"alive", true); @@ -30,7 +32,7 @@ void WhFans::ToggleFX(Entity* self, bool hit) { if (fanVolumes.size() == 0 || !self->GetVar(u"alive")) return; if (self->GetVar(u"on")) { - GameMessages::SendPlayAnimation(self, u"fan-off"); + RenderComponent::PlayAnimation(self, u"fan-off"); renderComponent->StopEffect("fanOn"); self->SetVar(u"on", false); @@ -42,7 +44,7 @@ void WhFans::ToggleFX(Entity* self, bool hit) { EntityManager::Instance()->SerializeEntity(volume); } } else if (!self->GetVar(u"on") && self->GetVar(u"alive")) { - GameMessages::SendPlayAnimation(self, u"fan-on"); + RenderComponent::PlayAnimation(self, u"fan-on"); self->SetVar(u"on", true); diff --git a/dScripts/ai/WILD/WildAmbients.cpp b/dScripts/ai/WILD/WildAmbients.cpp index 16dfa043..c21b6d76 100644 --- a/dScripts/ai/WILD/WildAmbients.cpp +++ b/dScripts/ai/WILD/WildAmbients.cpp @@ -1,6 +1,7 @@ #include "WildAmbients.h" #include "GameMessages.h" +#include "RenderComponent.h" void WildAmbients::OnUse(Entity* self, Entity* user) { - GameMessages::SendPlayAnimation(self, u"interact"); + RenderComponent::PlayAnimation(self, u"interact"); }