diff --git a/dGame/Character.cpp b/dGame/Character.cpp index 763223e59..46f061081 100644 --- a/dGame/Character.cpp +++ b/dGame/Character.cpp @@ -10,6 +10,7 @@ #include "Entity.h" #include "EntityManager.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "MissionMessages.h" #include "MissionComponent.h" #include "dZoneManager.h" @@ -239,7 +240,12 @@ void Character::DoQuickXMLDataParse() { void Character::UnlockEmote(int emoteID) { m_UnlockedEmotes.push_back(emoteID); - GameMessages::SendSetEmoteLockState(Game::entityManager->GetEntity(m_ObjectID), false, emoteID); + auto* const entity = Game::entityManager->GetEntity(m_ObjectID); + GameMessages::SetEmoteLockState lockState; + lockState.target = entity->GetObjectID(); + lockState.bLock = false; + lockState.emoteID = emoteID; + lockState.SendToClient(entity->GetSystemAddress()); } void Character::SetBuildMode(bool buildMode) { @@ -590,7 +596,9 @@ void Character::SetBillboardVisible(bool visible) { if (m_BillboardVisible == visible) return; m_BillboardVisible = visible; - GameMessages::SendSetNamebillboardState(UNASSIGNED_SYSTEM_ADDRESS, m_OurEntity->GetObjectID()); + GameMessages::SetNameBillboardState billboardState; + billboardState.target = m_OurEntity->GetObjectID(); + billboardState.Send(UNASSIGNED_SYSTEM_ADDRESS); if (!visible) return; @@ -598,8 +606,12 @@ void Character::SetBillboardVisible(bool visible) { // Because that same message does not allow for custom parameters, we need to create the BillboardSubcomponent a different way // This workaround involves sending an unrelated GameMessage that does not apply to player entites, // but forces the client to create the necessary SubComponent that controls the billboard. - GameMessages::SendShowBillboardInteractIcon(UNASSIGNED_SYSTEM_ADDRESS, m_OurEntity->GetObjectID()); + GameMessages::ShowBillboardInteractIcon interactIcon; + interactIcon.target = m_OurEntity->GetObjectID(); + interactIcon.Send(UNASSIGNED_SYSTEM_ADDRESS); // Now turn off the billboard for the owner. - GameMessages::SendSetNamebillboardState(m_OurEntity->GetSystemAddress(), m_OurEntity->GetObjectID()); + GameMessages::SetNameBillboardState ownerBillboardState; + ownerBillboardState.target = m_OurEntity->GetObjectID(); + ownerBillboardState.Send(m_OurEntity->GetSystemAddress()); } diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index 622bbf1cd..c9434cffb 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -12,6 +12,7 @@ #include #include "dServer.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "EntityManager.h" #include "dZoneManager.h" #include "Zone.h" @@ -2265,7 +2266,12 @@ bool Entity::MsgRequestServerObjectInfo(GameMessages::RequestServerObjectInfoEve HandleMsg(info); auto* client = Game::entityManager->GetEntity(requestInfo.clientId); - if (client) GameMessages::SendUIMessageServerToSingleClient("ToggleObjectDebugger", response, client->GetSystemAddress()); + if (client) { + GameMessages::UIMessageServerToAllClients uiMessage; + uiMessage.strMessageName = "ToggleObjectDebugger"; + uiMessage.args = std::move(response); + uiMessage.SendToClient(client->GetSystemAddress()); + } return true; } diff --git a/dGame/dBehaviors/Behavior.cpp b/dGame/dBehaviors/Behavior.cpp index 7cefd4dd7..9ad9d8a53 100644 --- a/dGame/dBehaviors/Behavior.cpp +++ b/dGame/dBehaviors/Behavior.cpp @@ -25,6 +25,7 @@ #include "ChainBehavior.h" #include "ChargeUpBehavior.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "HealBehavior.h" #include "ImaginationBehavior.h" #include "KnockbackBehavior.h" @@ -326,7 +327,9 @@ void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID const auto effectId = this->m_effectId; if (effectId == 0) { - GameMessages::SendPlayFXEffect(targetEntity, -1, type, "", secondary, 1, 1, true); + GameMessages::PlayFXEffect fx(targetEntity->GetObjectID(), -1, type, ""); + fx.secondary = secondary; + fx.Send(UNASSIGNED_SYSTEM_ADDRESS); return; } @@ -343,7 +346,9 @@ void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID if (itr != m_effectNames.end()) { if (renderComponent == nullptr) { - GameMessages::SendPlayFXEffect(targetEntity, effectId, type, itr->second, secondary, 1, 1, true); + GameMessages::PlayFXEffect fx(targetEntity->GetObjectID(), effectId, type, itr->second); + fx.secondary = secondary; + fx.Send(UNASSIGNED_SYSTEM_ADDRESS); return; } @@ -392,7 +397,9 @@ void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID m_effectNames.insert_or_assign(typeString, name); if (renderComponent == nullptr) { - GameMessages::SendPlayFXEffect(targetEntity, effectId, type, name, secondary, 1, 1, true); + GameMessages::PlayFXEffect fx(targetEntity->GetObjectID(), effectId, type, name); + fx.secondary = secondary; + fx.Send(UNASSIGNED_SYSTEM_ADDRESS); return; } diff --git a/dGame/dBehaviors/ChangeIdleFlagsBehavior.cpp b/dGame/dBehaviors/ChangeIdleFlagsBehavior.cpp index b7c6b80a2..8d7ed89ec 100644 --- a/dGame/dBehaviors/ChangeIdleFlagsBehavior.cpp +++ b/dGame/dBehaviors/ChangeIdleFlagsBehavior.cpp @@ -2,12 +2,17 @@ #include "ChangeIdleFlagsBehavior.h" #include "BehaviorContext.h" #include "BehaviorBranchContext.h" +#include "EffectsMessages.h" void ChangeIdleFlagsBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) { const auto target = branch.target != LWOOBJID_EMPTY ? branch.target : context->originator; if (!target) return; - GameMessages::SendChangeIdleFlags(target, m_FlagsOn, m_FlagsOff, UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::ChangeIdleFlags idleFlags; + idleFlags.target = target; + idleFlags.flagsOn = m_FlagsOn; + idleFlags.flagsOff = m_FlagsOff; + idleFlags.Send(UNASSIGNED_SYSTEM_ADDRESS); if (branch.duration > 0.0f) { context->RegisterTimerBehavior(this, branch); @@ -24,7 +29,11 @@ void ChangeIdleFlagsBehavior::End(BehaviorContext* context, BehaviorBranchContex const auto target = branch.target != LWOOBJID_EMPTY ? branch.target : context->originator; if (!target) return; // flip on and off to end behavior - GameMessages::SendChangeIdleFlags(target, m_FlagsOff, m_FlagsOn, UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::ChangeIdleFlags idleFlags; + idleFlags.target = target; + idleFlags.flagsOn = m_FlagsOff; + idleFlags.flagsOff = m_FlagsOn; + idleFlags.Send(UNASSIGNED_SYSTEM_ADDRESS); } void ChangeIdleFlagsBehavior::Timer(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) { diff --git a/dGame/dComponents/BaseCombatAIComponent.cpp b/dGame/dComponents/BaseCombatAIComponent.cpp index 09335459c..5bc74f6e9 100644 --- a/dGame/dComponents/BaseCombatAIComponent.cpp +++ b/dGame/dComponents/BaseCombatAIComponent.cpp @@ -8,6 +8,7 @@ #include "dpWorld.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "dServer.h" #include "Game.h" @@ -163,7 +164,7 @@ void BaseCombatAIComponent::Update(const float deltaTime) { m_TetherTime -= deltaTime; m_ForcedTetherTime -= deltaTime; if (m_ForcedTetherTime >= 0) return; - GameMessages::SendStopFXEffect(m_Parent, true, "tether"); + GameMessages::StopFXEffect(m_Parent->GetObjectID(), true, "tether").Send(UNASSIGNED_SYSTEM_ADDRESS); m_TetherEffectActive = false; } @@ -836,7 +837,7 @@ void BaseCombatAIComponent::TetherLogic() { Game::entityManager->SerializeEntity(m_Parent); } - GameMessages::SendPlayFXEffect(m_Parent->GetObjectID(), 6270, u"tether", "tether"); + GameMessages::PlayFXEffect(m_Parent->GetObjectID(), 6270, u"tether", "tether").Send(UNASSIGNED_SYSTEM_ADDRESS); m_TetherEffectActive = true; } diff --git a/dGame/dComponents/BouncerComponent.cpp b/dGame/dComponents/BouncerComponent.cpp index dc1d50f22..c58fba088 100644 --- a/dGame/dComponents/BouncerComponent.cpp +++ b/dGame/dComponents/BouncerComponent.cpp @@ -7,6 +7,7 @@ #include "Game.h" #include "Logger.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "BitStream.h" #include "eTriggerEventType.h" #include "Amf3.h" @@ -67,10 +68,10 @@ void BouncerComponent::SetPetBouncerEnabled(bool value) { if (value) { m_Parent->TriggerEvent(eTriggerEventType::PET_ON_SWITCH, m_Parent); - GameMessages::SendPlayFXEffect(m_Parent->GetObjectID(), 1513, u"create", "PetOnSwitch", LWOOBJID_EMPTY, 1, 1, true); + GameMessages::PlayFXEffect(m_Parent->GetObjectID(), 1513, u"create", "PetOnSwitch").Send(UNASSIGNED_SYSTEM_ADDRESS); } else { m_Parent->TriggerEvent(eTriggerEventType::PET_OFF_SWITCH, m_Parent); - GameMessages::SendStopFXEffect(m_Parent, true, "PetOnSwitch"); + GameMessages::StopFXEffect(m_Parent->GetObjectID(), true, "PetOnSwitch").Send(UNASSIGNED_SYSTEM_ADDRESS); } } diff --git a/dGame/dComponents/BuffComponent.cpp b/dGame/dComponents/BuffComponent.cpp index 8d699b548..95a9c4508 100644 --- a/dGame/dComponents/BuffComponent.cpp +++ b/dGame/dComponents/BuffComponent.cpp @@ -6,6 +6,7 @@ #include "Game.h" #include "Logger.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "SkillComponent.h" #include "ControllablePhysicsComponent.h" #include "EntityManager.h" @@ -123,7 +124,10 @@ void BuffComponent::ApplyBuffFx(uint32_t buffId, const BuffParameter& buff) { fxToPlay += std::to_string(buffId); LOG_DEBUG("Playing %s %i", fxToPlay.c_str(), buff.effectId); - GameMessages::SendPlayFXEffect(m_Parent->GetObjectID(), buff.effectId, u"cast", fxToPlay, LWOOBJID_EMPTY, 1.07f, 1.0f, false); + GameMessages::PlayFXEffect fx(m_Parent->GetObjectID(), buff.effectId, u"cast", fxToPlay); + fx.priority = 1.07f; + fx.serialize = false; + fx.Send(UNASSIGNED_SYSTEM_ADDRESS); } void BuffComponent::RemoveBuffFx(uint32_t buffId, const BuffParameter& buff) { @@ -134,7 +138,7 @@ void BuffComponent::RemoveBuffFx(uint32_t buffId, const BuffParameter& buff) { fxToPlay += std::to_string(buffId); LOG_DEBUG("Stopping %s", fxToPlay.c_str()); - GameMessages::SendStopFXEffect(m_Parent, false, fxToPlay); + GameMessages::StopFXEffect(m_Parent->GetObjectID(), false, fxToPlay).Send(UNASSIGNED_SYSTEM_ADDRESS); } void BuffComponent::ApplyBuff(const int32_t id, const float duration, const LWOOBJID source, bool addImmunity, diff --git a/dGame/dComponents/CharacterComponent.cpp b/dGame/dComponents/CharacterComponent.cpp index 1ee3ca961..a47c0e6c5 100644 --- a/dGame/dComponents/CharacterComponent.cpp +++ b/dGame/dComponents/CharacterComponent.cpp @@ -12,6 +12,7 @@ #include "EntityManager.h" #include "HavokVehiclePhysicsComponent.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "Item.h" #include "Amf3.h" #include "eGameMasterLevel.h" @@ -844,7 +845,11 @@ void CharacterComponent::UpdateClientMinimap(bool showFaction, std::string ventu if (!m_Parent) return; AMFArrayValue arrayToSend; arrayToSend.Insert(ventureVisionType, showFaction); - GameMessages::SendUIMessageServerToSingleClient(m_Parent, m_Parent ? m_Parent->GetSystemAddress() : UNASSIGNED_SYSTEM_ADDRESS, "SetFactionVisibility", arrayToSend); + GameMessages::UIMessageServerToSingleClient uiMessage; + uiMessage.target = m_Parent->GetObjectID(); + uiMessage.strMessageName = "SetFactionVisibility"; + uiMessage.args = std::move(arrayToSend); + uiMessage.SendToClient(m_Parent ? m_Parent->GetSystemAddress() : UNASSIGNED_SYSTEM_ADDRESS); } void CharacterComponent::AwardClaimCodes() { diff --git a/dGame/dComponents/DestroyableComponent.cpp b/dGame/dComponents/DestroyableComponent.cpp index 44f8bb41a..297dd574a 100644 --- a/dGame/dComponents/DestroyableComponent.cpp +++ b/dGame/dComponents/DestroyableComponent.cpp @@ -11,6 +11,7 @@ #include "Amf3.h" #include "AmfSerialize.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "User.h" #include "CDClientManager.h" #include "CDDestructibleComponentTable.h" @@ -272,7 +273,11 @@ void DestroyableComponent::SetMaxHealth(float value, bool playAnim) { args.Insert("amount", std::to_string(difference)); args.Insert("type", "health"); - GameMessages::SendUIMessageServerToSingleClient(m_Parent, characterComponent->GetSystemAddress(), "MaxPlayerBarUpdate", args); + GameMessages::UIMessageServerToSingleClient uiMessage; + uiMessage.target = m_Parent->GetObjectID(); + uiMessage.strMessageName = "MaxPlayerBarUpdate"; + uiMessage.args = std::move(args); + uiMessage.SendToClient(characterComponent->GetSystemAddress()); } Game::entityManager->SerializeEntity(m_Parent); @@ -314,7 +319,11 @@ void DestroyableComponent::SetMaxArmor(float value, bool playAnim) { args.Insert("amount", std::to_string(value)); args.Insert("type", "armor"); - GameMessages::SendUIMessageServerToSingleClient(m_Parent, characterComponent->GetSystemAddress(), "MaxPlayerBarUpdate", args); + GameMessages::UIMessageServerToSingleClient uiMessage; + uiMessage.target = m_Parent->GetObjectID(); + uiMessage.strMessageName = "MaxPlayerBarUpdate"; + uiMessage.args = std::move(args); + uiMessage.SendToClient(characterComponent->GetSystemAddress()); } Game::entityManager->SerializeEntity(m_Parent); @@ -355,7 +364,11 @@ void DestroyableComponent::SetMaxImagination(float value, bool playAnim) { args.Insert("amount", std::to_string(difference)); args.Insert("type", "imagination"); - GameMessages::SendUIMessageServerToSingleClient(m_Parent, characterComponent->GetSystemAddress(), "MaxPlayerBarUpdate", args); + GameMessages::UIMessageServerToSingleClient uiMessage; + uiMessage.target = m_Parent->GetObjectID(); + uiMessage.strMessageName = "MaxPlayerBarUpdate"; + uiMessage.args = std::move(args); + uiMessage.SendToClient(characterComponent->GetSystemAddress()); } Game::entityManager->SerializeEntity(m_Parent); } diff --git a/dGame/dComponents/PetComponent.cpp b/dGame/dComponents/PetComponent.cpp index c2e36929e..2181361c2 100644 --- a/dGame/dComponents/PetComponent.cpp +++ b/dGame/dComponents/PetComponent.cpp @@ -2,6 +2,7 @@ #include "DashboardNotify.h" #include "GameMessages.h" #include "PetMessages.h" +#include "EffectsMessages.h" #include "BrickDatabase.h" #include "CDClientDatabase.h" #include "CDTamingBuildPuzzleTable.h" @@ -469,7 +470,7 @@ void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) { const auto* const entry = CDClientManager::GetTable()->GetByLOT(m_Parent->GetLOT()); if (!entry) return; - GameMessages::SendPlayFXEffect(tamer, -1, u"petceleb", "", LWOOBJID_EMPTY, 1, 1, true); + GameMessages::PlayFXEffect(tamer->GetObjectID(), -1, u"petceleb", "").Send(UNASSIGNED_SYSTEM_ADDRESS); RenderComponent::PlayAnimation(tamer, u"rebuild-celebrate"); EntityInfo info{}; @@ -1036,7 +1037,7 @@ void PetComponent::AddDrainImaginationTimer(bool fromTaming) { } void PetComponent::Deactivate() { - GameMessages::SendPlayFXEffect(m_Parent->GetObjectID(), -1, u"despawn", "", LWOOBJID_EMPTY, 1, 1, true); + GameMessages::PlayFXEffect(m_Parent->GetObjectID(), -1, u"despawn", "").Send(UNASSIGNED_SYSTEM_ADDRESS); activePets.erase(m_Owner); @@ -1105,7 +1106,11 @@ void PetComponent::Command(const NiPoint3& position, const LWOOBJID source, cons if (commandType == 1) { // Emotes - GameMessages::SendPlayEmote(m_Parent->GetObjectID(), typeId, owner->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::PlayEmote playEmote; + playEmote.target = m_Parent->GetObjectID(); + playEmote.emoteID = typeId; + playEmote.targetID = owner->GetObjectID(); + playEmote.Send(UNASSIGNED_SYSTEM_ADDRESS); GameMessages::EmotePlayed msg; msg.target = owner->GetObjectID(); msg.emoteID = typeId; diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index b4a02ac4a..5548b89c6 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -5,6 +5,7 @@ #include "Character.h" #include "Database.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "PropertyManagementComponent.h" #include "PropertyMessages.h" #include "RocketLaunchpadControlComponent.h" @@ -42,7 +43,11 @@ void PropertyEntranceComponent::OnUse(Entity* entity) { args.Insert("state", "property_menu"); - GameMessages::SendUIMessageServerToSingleClient(entity, entity->GetSystemAddress(), "pushGameState", args); + GameMessages::UIMessageServerToSingleClient uiMessage; + uiMessage.target = entity->GetObjectID(); + uiMessage.strMessageName = "pushGameState"; + uiMessage.args = std::move(args); + uiMessage.SendToClient(entity->GetSystemAddress()); } void PropertyEntranceComponent::OnEnterProperty(Entity* entity, uint32_t index, bool returnToZone, const SystemAddress& sysAddr) { diff --git a/dGame/dComponents/QuickBuildComponent.cpp b/dGame/dComponents/QuickBuildComponent.cpp index 8fda9fe7d..11737c82a 100644 --- a/dGame/dComponents/QuickBuildComponent.cpp +++ b/dGame/dComponents/QuickBuildComponent.cpp @@ -2,6 +2,7 @@ #include "Entity.h" #include "DestroyableComponent.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "EntityManager.h" #include "Game.h" #include "Logger.h" @@ -425,7 +426,9 @@ void QuickBuildComponent::CompleteQuickBuild(Entity* const user) { Game::entityManager->SerializeEntity(user); GameMessages::SendQuickBuildNotifyState(m_Parent, m_State, eQuickBuildState::COMPLETED, user->GetObjectID()); - GameMessages::SendPlayFXEffect(m_Parent, 507, u"create", "BrickFadeUpVisCompleteEffect", LWOOBJID_EMPTY, 0.4f, 1.0f, true); + GameMessages::PlayFXEffect fx(m_Parent->GetObjectID(), 507, u"create", "BrickFadeUpVisCompleteEffect"); + fx.priority = 0.4f; + fx.Send(UNASSIGNED_SYSTEM_ADDRESS); GameMessages::SendEnableQuickBuild(m_Parent, false, false, true, eQuickBuildFailReason::NOT_GIVEN, m_ResetTime, user->GetObjectID()); GameMessages::SendTerminateInteraction(user->GetObjectID(), eTerminateType::FROM_INTERACTION, m_Parent->GetObjectID()); diff --git a/dGame/dComponents/RailActivatorComponent.cpp b/dGame/dComponents/RailActivatorComponent.cpp index 8ef050753..ce54ce057 100644 --- a/dGame/dComponents/RailActivatorComponent.cpp +++ b/dGame/dComponents/RailActivatorComponent.cpp @@ -4,6 +4,7 @@ #include "CDRailActivatorComponent.h" #include "Entity.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "QuickBuildComponent.h" #include "Game.h" #include "Logger.h" @@ -55,8 +56,7 @@ void RailActivatorComponent::OnUse(Entity* originator) { // Start the initial effects if (!m_StartEffect.second.empty()) { - GameMessages::SendPlayFXEffect(originator->GetObjectID(), m_StartEffect.first, m_StartEffect.second, - std::to_string(m_StartEffect.first)); + GameMessages::PlayFXEffect(originator->GetObjectID(), m_StartEffect.first, m_StartEffect.second, std::to_string(m_StartEffect.first)).Send(UNASSIGNED_SYSTEM_ADDRESS); } float animationLength = 0.5f; @@ -90,13 +90,12 @@ void RailActivatorComponent::OnRailMovementReady(Entity* originator) const { if (std::find(m_EntitiesOnRail.begin(), m_EntitiesOnRail.end(), originator->GetObjectID()) != m_EntitiesOnRail.end()) { // Stop the initial effects if (!m_StartEffect.second.empty()) { - GameMessages::SendStopFXEffect(originator, false, std::to_string(m_StartEffect.first)); + GameMessages::StopFXEffect(originator->GetObjectID(), false, std::to_string(m_StartEffect.first)).Send(UNASSIGNED_SYSTEM_ADDRESS); } // Start the looping effects if (!m_LoopEffect.second.empty()) { - GameMessages::SendPlayFXEffect(originator->GetObjectID(), m_LoopEffect.first, m_LoopEffect.second, - std::to_string(m_LoopEffect.first)); + GameMessages::PlayFXEffect(originator->GetObjectID(), m_LoopEffect.first, m_LoopEffect.second, std::to_string(m_LoopEffect.first)).Send(UNASSIGNED_SYSTEM_ADDRESS); } if (!m_LoopAnimation.empty()) { @@ -125,13 +124,12 @@ void RailActivatorComponent::OnCancelRailMovement(Entity* originator) { if (std::find(m_EntitiesOnRail.begin(), m_EntitiesOnRail.end(), originator->GetObjectID()) != m_EntitiesOnRail.end()) { // Stop the looping effects if (!m_LoopEffect.second.empty()) { - GameMessages::SendStopFXEffect(originator, false, std::to_string(m_LoopEffect.first)); + GameMessages::StopFXEffect(originator->GetObjectID(), false, std::to_string(m_LoopEffect.first)).Send(UNASSIGNED_SYSTEM_ADDRESS); } // Start the end effects if (!m_StopEffect.second.empty()) { - GameMessages::SendPlayFXEffect(originator->GetObjectID(), m_StopEffect.first, m_StopEffect.second, - std::to_string(m_StopEffect.first)); + GameMessages::PlayFXEffect(originator->GetObjectID(), m_StopEffect.first, m_StopEffect.second, std::to_string(m_StopEffect.first)).Send(UNASSIGNED_SYSTEM_ADDRESS); } if (!m_StopAnimation.empty()) { diff --git a/dGame/dComponents/RenderComponent.cpp b/dGame/dComponents/RenderComponent.cpp index f30648cc9..74f7c4fa9 100644 --- a/dGame/dComponents/RenderComponent.cpp +++ b/dGame/dComponents/RenderComponent.cpp @@ -10,6 +10,7 @@ #include "CDClientManager.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "Game.h" #include "Logger.h" #include "CDAnimationsTable.h" @@ -96,7 +97,12 @@ void RenderComponent::Update(const float deltaTime) { 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); + GameMessages::PlayFXEffect fx(m_Parent->GetObjectID(), effectId, effectType, name); + fx.secondary = secondary; + fx.priority = priority; + fx.scale = scale; + fx.serialize = serialize; + fx.Send(UNASSIGNED_SYSTEM_ADDRESS); auto& effect = AddEffect(effectId, name, effectType, priority); @@ -135,7 +141,7 @@ void RenderComponent::PlayEffect(const int32_t effectId, const std::u16string& e } void RenderComponent::StopEffect(const std::string& name, const bool killImmediate) { - GameMessages::SendStopFXEffect(m_Parent, killImmediate, name); + GameMessages::StopFXEffect(m_Parent->GetObjectID(), killImmediate, name).Send(UNASSIGNED_SYSTEM_ADDRESS); RemoveEffect(name); } @@ -175,7 +181,12 @@ float RenderComponent::DoAnimation(Entity* self, const std::string& animation, b returnlength = animationGroup->animation_length; } } - if (sendAnimation) GameMessages::SendPlayAnimation(self, GeneralUtils::ASCIIToUTF16(animation), priority, scale); + if (sendAnimation) { + GameMessages::PlayAnimation playAnimation(self->GetObjectID(), GeneralUtils::ASCIIToUTF16(animation)); + playAnimation.fPriority = priority; + playAnimation.fScale = scale; + playAnimation.Send(UNASSIGNED_SYSTEM_ADDRESS); + } if (returnlength == 0.0f) LOG("WARNING: Unable to find animation %s for lot %i in any group.", animation.c_str(), self->GetLOT()); return returnlength; } diff --git a/dGame/dComponents/SwitchComponent.cpp b/dGame/dComponents/SwitchComponent.cpp index 6406690a3..07f989877 100644 --- a/dGame/dComponents/SwitchComponent.cpp +++ b/dGame/dComponents/SwitchComponent.cpp @@ -3,6 +3,7 @@ #include "eTriggerEventType.h" #include "RenderComponent.h" #include "DestroyableComponent.h" +#include "EffectsMessages.h" std::vector SwitchComponent::petSwitches; @@ -78,7 +79,7 @@ void SwitchComponent::EntityEnter(Entity* entity) { m_Timer = m_ResetTime; if (m_PetBouncer != nullptr) { - GameMessages::SendPlayFXEffect(m_Parent->GetObjectID(), 2602, u"pettriggeractive", "BounceEffect", LWOOBJID_EMPTY, 1, 1, true); + GameMessages::PlayFXEffect(m_Parent->GetObjectID(), 2602, u"pettriggeractive", "BounceEffect").Send(UNASSIGNED_SYSTEM_ADDRESS); RenderComponent::PlayAnimation(m_Parent, u"engaged"); m_PetBouncer->SetPetBouncerEnabled(true); } else { diff --git a/dGame/dComponents/TriggerComponent.cpp b/dGame/dComponents/TriggerComponent.cpp index 3c2489aa7..46037f6ac 100644 --- a/dGame/dComponents/TriggerComponent.cpp +++ b/dGame/dComponents/TriggerComponent.cpp @@ -18,6 +18,7 @@ #include "MovementAIComponent.h" #include +#include "EffectsMessages.h" TriggerComponent::TriggerComponent(Entity* parent, const int32_t componentID, const std::string triggerInfo) : Component(parent, componentID) { m_Parent = parent; @@ -124,7 +125,7 @@ void TriggerComponent::HandleTriggerCommand(LUTriggers::Command* command, Entity HandlePlayEffect(targetEntity, argArray); break; case eTriggerCommandType::STOP_EFFECT: - GameMessages::SendStopFXEffect(targetEntity, true, command->args); + GameMessages::StopFXEffect(targetEntity->GetObjectID(), true, command->args).Send(UNASSIGNED_SYSTEM_ADDRESS); break; case eTriggerCommandType::CAST_SKILL: HandleCastSkill(targetEntity, command->args); @@ -327,7 +328,19 @@ void TriggerComponent::HandlePlayCinematic(Entity* targetEntity, std::vectorGetObjectID(), GeneralUtils::UTF8ToUTF16(argArray.at(0)), targetEntity->GetSystemAddress(), true, true, false, false, wait, hidePlayer, leadIn, leaveLocked, unlock); + GameMessages::PlayCinematic cinematic; + cinematic.target = targetEntity->GetObjectID(); + cinematic.pathName = GeneralUtils::UTF8ToUTF16(argArray.at(0)); + cinematic.allowGhostUpdates = true; + cinematic.bCloseMultiInteract = true; + cinematic.bSendServerNotify = false; + cinematic.bUseControlledObjectForAudioListener = false; + cinematic.endBehavior = wait; + cinematic.hidePlayerDuringCine = hidePlayer; + cinematic.leadIn = leadIn; + cinematic.leavePlayerLockedWhenFinished = leaveLocked; + cinematic.lockPlayer = unlock; + cinematic.Send(targetEntity->GetSystemAddress()); } void TriggerComponent::HandleToggleBBB(Entity* targetEntity, std::string args) { @@ -366,7 +379,9 @@ void TriggerComponent::HandlePlayEffect(Entity* targetEntity, std::vector(argArray.at(3)).value_or(priority); } - GameMessages::SendPlayFXEffect(targetEntity, effectID.value(), effectType, argArray.at(0), LWOOBJID_EMPTY, priority); + GameMessages::PlayFXEffect fx(targetEntity->GetObjectID(), effectID.value(), effectType, argArray.at(0)); + fx.priority = priority; + fx.Send(UNASSIGNED_SYSTEM_ADDRESS); } void TriggerComponent::HandleCastSkill(Entity* targetEntity, std::string args) { diff --git a/dGame/dGameMessages/CMakeLists.txt b/dGame/dGameMessages/CMakeLists.txt index 1e7e49c1c..0d728669b 100644 --- a/dGame/dGameMessages/CMakeLists.txt +++ b/dGame/dGameMessages/CMakeLists.txt @@ -3,6 +3,7 @@ set(DGAME_DGAMEMESSAGES_SOURCES "BuildingMessages.cpp" "GameMessageDecoder.cpp" "GameMessageHandler.cpp" + "EffectsMessages.cpp" "GameMessages.cpp" "MissionMessages.cpp" "PetMessages.cpp" diff --git a/dGame/dGameMessages/EffectsMessages.cpp b/dGame/dGameMessages/EffectsMessages.cpp new file mode 100644 index 000000000..5fada082c --- /dev/null +++ b/dGame/dGameMessages/EffectsMessages.cpp @@ -0,0 +1,489 @@ +#include "EffectsMessages.h" + +#include "AMFDeserialize.h" +#include "AmfSerialize.h" +#include "BitStreamUtils.h" +#include "CDClientManager.h" +#include "CDEmoteTable.h" +#include "Character.h" +#include "eMissionTaskType.h" +#include "eReplicaComponentType.h" +#include "Entity.h" +#include "EntityManager.h" +#include "Game.h" +#include "GeneralUtils.h" +#include "Logger.h" +#include "MissionComponent.h" +#include "NiPoint3.h" +#include "RacingControlComponent.h" +#include "ScriptedActivityComponent.h" +#include "User.h" +#include "UserManager.h" + +#include + +namespace { + // Reads an AMF3 array written with Write. Fails on anything that is not an array. + bool ReadAmfArray(RakNet::BitStream& bitStream, AMFArrayValue& args) { + try { + AMFDeserialize reader; + auto value = reader.Read(bitStream); + if (!value || value->GetValueType() != eAmf::Array) return false; + args = std::move(*static_cast(value.get())); + return true; + } catch (const std::exception&) { + return false; + } + } +} + +namespace GameMessages { + void PlayAnimation::Serialize(RakNet::BitStream& bitStream) const { + const auto animationIDLength = static_cast(GeneralUtils::UTF16ToWTF8(animationID).size()); + bitStream.Write(animationIDLength); + bitStream.Write(LUWString(animationID, animationIDLength)); + bitStream.Write(bExpectAnimToExist); + bitStream.Write(bPlayImmediate); + bitStream.Write(bTriggerOnCompleteMsg); + BitStreamUtils::WriteOptional(bitStream, fPriority, 0.0f); + BitStreamUtils::WriteOptional(bitStream, fScale, 1.0f); + } + + bool PlayAnimation::Deserialize(RakNet::BitStream& bitStream) { + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, animationID)); + VALIDATE_READ(bitStream.Read(bExpectAnimToExist)); + VALIDATE_READ(bitStream.Read(bPlayImmediate)); + VALIDATE_READ(bitStream.Read(bTriggerOnCompleteMsg)); + VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, fPriority, 0.0f)); + VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, fScale, 1.0f)); + return true; + } + + void PlayNDAudioEmitter::Serialize(RakNet::BitStream& bitStream) const { + BitStreamUtils::WriteOptional(bitStream, NDAudioCallbackMessageData, 0); + BitStreamUtils::WriteOptional(bitStream, NDAudioEmitterID, 0); + BitStreamUtils::WriteLengthPrefixed(bitStream, NDAudioEventGUID); + BitStreamUtils::WriteLengthPrefixed(bitStream, NDAudioMetaEventName); + bitStream.Write(result); + BitStreamUtils::WriteOptional(bitStream, targetObjectIDForNDAudioCallbackMessages, LWOOBJID_EMPTY); + } + + bool PlayNDAudioEmitter::Deserialize(RakNet::BitStream& bitStream) { + VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, NDAudioCallbackMessageData, 0)); + VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, NDAudioEmitterID, 0)); + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, NDAudioEventGUID)); + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, NDAudioMetaEventName)); + VALIDATE_READ(bitStream.Read(result)); + VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, targetObjectIDForNDAudioCallbackMessages, LWOOBJID_EMPTY)); + return true; + } + + void PlayEmbeddedEffectOnAllClientsNearObject::Serialize(RakNet::BitStream& bitStream) const { + BitStreamUtils::WriteLengthPrefixed(bitStream, effectName); + bitStream.Write(fromObjectID); + bitStream.Write(radius); + } + + bool PlayEmbeddedEffectOnAllClientsNearObject::Deserialize(RakNet::BitStream& bitStream) { + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, effectName)); + VALIDATE_READ(bitStream.Read(fromObjectID)); + VALIDATE_READ(bitStream.Read(radius)); + return true; + } + + void PlayFXEffect::Serialize(RakNet::BitStream& bitStream) const { + BitStreamUtils::WriteOptional(bitStream, effectID, -1); + BitStreamUtils::WriteLengthPrefixed(bitStream, effectType); + BitStreamUtils::WriteOptional(bitStream, scale, 1.0f); + BitStreamUtils::WriteLengthPrefixed(bitStream, name); + BitStreamUtils::WriteOptional(bitStream, priority, 1.0f); + BitStreamUtils::WriteOptional(bitStream, secondary, LWOOBJID_EMPTY); + bitStream.Write(serialize); + } + + bool PlayFXEffect::Deserialize(RakNet::BitStream& bitStream) { + VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, effectID, -1)); + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, effectType)); + VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, scale, 1.0f)); + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, name)); + VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, priority, 1.0f)); + VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, secondary, LWOOBJID_EMPTY)); + VALIDATE_READ(bitStream.Read(serialize)); + return true; + } + + void StopFXEffect::Serialize(RakNet::BitStream& bitStream) const { + bitStream.Write(killImmediate); + BitStreamUtils::WriteLengthPrefixed(bitStream, name); + } + + bool StopFXEffect::Deserialize(RakNet::BitStream& bitStream) { + VALIDATE_READ(bitStream.Read(killImmediate)); + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, name)); + return true; + } + + void BroadcastTextToChatbox::Serialize(RakNet::BitStream& bitStream) const { + BitStreamUtils::WriteLengthPrefixed(bitStream, attrs); + bitStream.Write(0x00); // null terminator, always written + BitStreamUtils::WriteLengthPrefixed(bitStream, wsText); + } + + bool BroadcastTextToChatbox::Deserialize(RakNet::BitStream& bitStream) { + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, attrs)); + uint16_t nullTerminator{}; + VALIDATE_READ(bitStream.Read(nullTerminator)); + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, wsText)); + return true; + } + + void Play2DAmbientSound::Serialize(RakNet::BitStream& bitStream) const { + BitStreamUtils::WriteLengthPrefixed(bitStream, audioGUID); + bitStream.Write(result); + } + + bool Play2DAmbientSound::Deserialize(RakNet::BitStream& bitStream) { + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, audioGUID)); + VALIDATE_READ(bitStream.Read(result)); + return true; + } + + void Stop2DAmbientSound::Serialize(RakNet::BitStream& bitStream) const { + bitStream.Write(force); + BitStreamUtils::WriteLengthPrefixed(bitStream, audioGUID); + bitStream.Write(result); + } + + bool Stop2DAmbientSound::Deserialize(RakNet::BitStream& bitStream) { + VALIDATE_READ(bitStream.Read(force)); + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, audioGUID)); + VALIDATE_READ(bitStream.Read(result)); + return true; + } + + void UIMessageServerToSingleClient::Serialize(RakNet::BitStream& bitStream) const { + bitStream.Write(const_cast(args)); + BitStreamUtils::WriteLengthPrefixed(bitStream, strMessageName); + } + + bool UIMessageServerToSingleClient::Deserialize(RakNet::BitStream& bitStream) { + VALIDATE_READ(ReadAmfArray(bitStream, args)); + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, strMessageName)); + return true; + } + + void UIMessageServerToAllClients::Serialize(RakNet::BitStream& bitStream) const { + bitStream.Write(const_cast(args)); + BitStreamUtils::WriteLengthPrefixed(bitStream, strMessageName); + } + + bool UIMessageServerToAllClients::Deserialize(RakNet::BitStream& bitStream) { + VALIDATE_READ(ReadAmfArray(bitStream, args)); + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, strMessageName)); + return true; + } + + void StartCelebrationEffect::Serialize(RakNet::BitStream& bitStream) const { + BitStreamUtils::WriteLengthPrefixed(bitStream, animation); + BitStreamUtils::WriteOptional(bitStream, backgroundObject, 11164); + BitStreamUtils::WriteOptional(bitStream, cameraPathLOT, 12458); + BitStreamUtils::WriteOptional(bitStream, celeLeadIn, 1.0f); + BitStreamUtils::WriteOptional(bitStream, celeLeadOut, 0.8f); + bitStream.Write1(); // DLU always sends celebrationID + bitStream.Write(celebrationID); + bitStream.Write(duration); + bitStream.Write(iconID); + BitStreamUtils::WriteLengthPrefixed(bitStream, mainText); + BitStreamUtils::WriteLengthPrefixed(bitStream, mixerProgram); + BitStreamUtils::WriteLengthPrefixed(bitStream, musicCue); + BitStreamUtils::WriteLengthPrefixed(bitStream, pathNodeName); + BitStreamUtils::WriteLengthPrefixed(bitStream, soundGUID); + BitStreamUtils::WriteLengthPrefixed(bitStream, subText); + } + + bool StartCelebrationEffect::Deserialize(RakNet::BitStream& bitStream) { + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, animation)); + VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, backgroundObject, 11164)); + VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, cameraPathLOT, 12458)); + VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, celeLeadIn, 1.0f)); + VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, celeLeadOut, 0.8f)); + VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, celebrationID, -1)); + VALIDATE_READ(bitStream.Read(duration)); + VALIDATE_READ(bitStream.Read(iconID)); + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, mainText)); + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, mixerProgram)); + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, musicCue)); + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, pathNodeName)); + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, soundGUID)); + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, subText)); + return true; + } + + void DisplayMessageBox::Serialize(RakNet::BitStream& bitStream) const { + bitStream.Write(bShow); + bitStream.Write(callbackClient); + BitStreamUtils::WriteLengthPrefixed(bitStream, identifier); + bitStream.Write(imageID); + BitStreamUtils::WriteLengthPrefixed(bitStream, text); + BitStreamUtils::WriteLengthPrefixed(bitStream, userData); + } + + bool DisplayMessageBox::Deserialize(RakNet::BitStream& bitStream) { + VALIDATE_READ(bitStream.Read(bShow)); + VALIDATE_READ(bitStream.Read(callbackClient)); + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, identifier)); + VALIDATE_READ(bitStream.Read(imageID)); + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, text)); + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, userData)); + return true; + } + + void MessageBoxRespond::Serialize(RakNet::BitStream& bitStream) const { + bitStream.Write(iButton); + BitStreamUtils::WriteLengthPrefixed(bitStream, identifier); + BitStreamUtils::WriteLengthPrefixed(bitStream, userData); + } + + bool MessageBoxRespond::Deserialize(RakNet::BitStream& bitStream) { + VALIDATE_READ(bitStream.Read(iButton)); + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, identifier)); + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, userData)); + return true; + } + + void MessageBoxRespond::Handle(Entity& entityRef, const SystemAddress& sysAddr) { + Entity* entity = &entityRef; + LOG("Button: %d; LOT: %u identifier: %s; userData: %s", iButton, entity->GetLOT(), GeneralUtils::UTF16ToWTF8(identifier).c_str(), GeneralUtils::UTF16ToWTF8(userData).c_str()); + + auto* user = UserManager::Instance()->GetUser(sysAddr); + + if (user == nullptr) { + return; + } + + auto* userEntity = user->GetLastUsedChar()->GetEntity(); + + if (userEntity == nullptr) { + return; + } + + entity->OnMessageBoxResponse(userEntity, iButton, identifier, userData); + + auto* scriptedActivityComponent = entity->GetComponent(); + + if (scriptedActivityComponent != nullptr) { + scriptedActivityComponent->HandleMessageBoxResponse(userEntity, GeneralUtils::UTF16ToWTF8(identifier)); + } + + auto* racingControlComponent = entity->GetComponent(); + + if (racingControlComponent != nullptr) { + racingControlComponent->HandleMessageBoxResponse(userEntity, iButton, GeneralUtils::UTF16ToWTF8(identifier)); + } + + for (auto* shootingGallery : Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::SHOOTING_GALLERY)) { + shootingGallery->OnMessageBoxResponse(userEntity, iButton, identifier, userData); + } + } + + void ChoiceBoxRespond::Serialize(RakNet::BitStream& bitStream) const { + BitStreamUtils::WriteLengthPrefixed(bitStream, buttonIdentifier); + bitStream.Write(iButton); + BitStreamUtils::WriteLengthPrefixed(bitStream, identifier); + } + + bool ChoiceBoxRespond::Deserialize(RakNet::BitStream& bitStream) { + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, buttonIdentifier)); + VALIDATE_READ(bitStream.Read(iButton)); + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, identifier)); + return true; + } + + void ChoiceBoxRespond::Handle(Entity& entityRef, const SystemAddress& sysAddr) { + Entity* entity = &entityRef; + LOG("Button: %d; LOT: %u buttonIdentifier: %s; userData: %s", iButton, entity->GetLOT(), GeneralUtils::UTF16ToWTF8(buttonIdentifier).c_str(), GeneralUtils::UTF16ToWTF8(identifier).c_str()); + + auto* user = UserManager::Instance()->GetUser(sysAddr); + + if (user == nullptr) { + return; + } + + auto* userEntity = user->GetLastUsedChar()->GetEntity(); + + if (userEntity == nullptr) { + return; + } + + entity->OnChoiceBoxResponse(userEntity, iButton, buttonIdentifier, identifier); + } + + void DisplayChatBubble::Serialize(RakNet::BitStream& bitStream) const { + BitStreamUtils::WriteLengthPrefixed(bitStream, wsText); + } + + bool DisplayChatBubble::Deserialize(RakNet::BitStream& bitStream) { + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, wsText)); + return true; + } + + void ChangeIdleFlags::Serialize(RakNet::BitStream& bitStream) const { + BitStreamUtils::WriteOptional(bitStream, flagsOff, eAnimationFlags::IDLE_NONE); + BitStreamUtils::WriteOptional(bitStream, flagsOn, eAnimationFlags::IDLE_NONE); + } + + bool ChangeIdleFlags::Deserialize(RakNet::BitStream& bitStream) { + VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, flagsOff, eAnimationFlags::IDLE_NONE)); + VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, flagsOn, eAnimationFlags::IDLE_NONE)); + return true; + } + + void PlayCinematic::Serialize(RakNet::BitStream& bitStream) const { + bitStream.Write(allowGhostUpdates); + bitStream.Write(bCloseMultiInteract); + bitStream.Write(bSendServerNotify); + bitStream.Write(bUseControlledObjectForAudioListener); + BitStreamUtils::WriteOptional(bitStream, endBehavior, eEndBehavior::RETURN); + bitStream.Write(hidePlayerDuringCine); + BitStreamUtils::WriteOptional(bitStream, leadIn, -1.0f); + bitStream.Write(leavePlayerLockedWhenFinished); + bitStream.Write(lockPlayer); + BitStreamUtils::WriteLengthPrefixed(bitStream, pathName); + bitStream.Write(result); + bitStream.Write(skipIfSamePath); + bitStream.Write(startTimeAdvance); + } + + bool PlayCinematic::Deserialize(RakNet::BitStream& bitStream) { + VALIDATE_READ(bitStream.Read(allowGhostUpdates)); + VALIDATE_READ(bitStream.Read(bCloseMultiInteract)); + VALIDATE_READ(bitStream.Read(bSendServerNotify)); + VALIDATE_READ(bitStream.Read(bUseControlledObjectForAudioListener)); + VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, endBehavior, eEndBehavior::RETURN)); + VALIDATE_READ(bitStream.Read(hidePlayerDuringCine)); + VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, leadIn, -1.0f)); + VALIDATE_READ(bitStream.Read(leavePlayerLockedWhenFinished)); + VALIDATE_READ(bitStream.Read(lockPlayer)); + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, pathName)); + VALIDATE_READ(bitStream.Read(result)); + VALIDATE_READ(bitStream.Read(skipIfSamePath)); + VALIDATE_READ(bitStream.Read(startTimeAdvance)); + return true; + } + + void EndCinematic::Serialize(RakNet::BitStream& bitStream) const { + BitStreamUtils::WriteOptional(bitStream, leadOut, -1.0f); + bitStream.Write(leavePlayerLocked); + BitStreamUtils::WriteLengthPrefixed(bitStream, pathName); + } + + bool EndCinematic::Deserialize(RakNet::BitStream& bitStream) { + VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, leadOut, -1.0f)); + VALIDATE_READ(bitStream.Read(leavePlayerLocked)); + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, pathName)); + return true; + } + + void CinematicUpdate::Serialize(RakNet::BitStream& bitStream) const { + BitStreamUtils::WriteOptional(bitStream, event, eCinematicEvent::STARTED); + BitStreamUtils::WriteOptional(bitStream, overallTime, -1.0f); + BitStreamUtils::WriteLengthPrefixed(bitStream, pathName); + BitStreamUtils::WriteOptional(bitStream, pathTime, -1.0f); + BitStreamUtils::WriteOptional(bitStream, waypoint, -1); + } + + bool CinematicUpdate::Deserialize(RakNet::BitStream& bitStream) { + VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, event, eCinematicEvent::STARTED)); + VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, overallTime, -1.0f)); + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, pathName)); + VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, pathTime, -1.0f)); + VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, waypoint, -1)); + return true; + } + + void CinematicUpdate::Handle(Entity& entity, const SystemAddress& sysAddr) { + std::vector scriptedActs = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::SCRIPT); + for (Entity* scriptEntity : scriptedActs) { + scriptEntity->OnCinematicUpdate(scriptEntity, &entity, event, pathName, pathTime, overallTime, waypoint); + } + } + + void SlashCommandTextFeedback::Serialize(RakNet::BitStream& bitStream) const { + BitStreamUtils::WriteLengthPrefixed(bitStream, text); + } + + bool SlashCommandTextFeedback::Deserialize(RakNet::BitStream& bitStream) { + VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed(bitStream, text)); + return true; + } + + void PlayEmote::Serialize(RakNet::BitStream& bitStream) const { + bitStream.Write(emoteID); + bitStream.Write(targetID); + } + + bool PlayEmote::Deserialize(RakNet::BitStream& bitStream) { + VALIDATE_READ(bitStream.Read(emoteID)); + VALIDATE_READ(bitStream.Read(targetID)); + return true; + } + + void PlayEmote::Handle(Entity& entityRef, const SystemAddress& sysAddr) { + Entity* entity = &entityRef; + LOG_DEBUG("Emote (%i) (%llu)", emoteID, targetID); + + //TODO: If targetID != 0, and we have one of the "perform emote" missions, complete them. + + if (emoteID == 0) return; + std::string sAnimationName = "deaded"; //Default name in case we fail to get the emote + + CDEmoteTableTable* emotes = CDClientManager::GetTable(); + if (emotes) { + CDEmoteTable* emote = emotes->GetEmote(emoteID); + if (emote) sAnimationName = emote->animationName; + } + + GameMessages::EmotePlayed msg; + msg.target = entity->GetObjectID(); + msg.emoteID = emoteID; + msg.targetID = targetID; // The emote’s target entity or 0 if none + msg.Send(UNASSIGNED_SYSTEM_ADDRESS); // Broadcast to all clients + + MissionComponent* missionComponent = entity->GetComponent(); + if (!missionComponent) return; + + if (targetID != LWOOBJID_EMPTY) { + auto* targetEntity = Game::entityManager->GetEntity(targetID); + + LOG_DEBUG("Emote target found (%d)", targetEntity != nullptr); + + if (targetEntity != nullptr) { + targetEntity->OnEmoteReceived(emoteID, entity); + missionComponent->Progress(eMissionTaskType::EMOTE, emoteID, targetID); + } + } else { + LOG_DEBUG("Target ID is empty, using backup"); + const auto scriptedEntities = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::SCRIPT); + + const auto& referencePoint = entity->GetPosition(); + + for (auto* scripted : scriptedEntities) { + if (Vector3::DistanceSquared(scripted->GetPosition(), referencePoint) > 5.0f * 5.0f) continue; + + scripted->OnEmoteReceived(emoteID, entity); + missionComponent->Progress(eMissionTaskType::EMOTE, emoteID, scripted->GetObjectID()); + } + } + } + + void SetEmoteLockState::Serialize(RakNet::BitStream& bitStream) const { + bitStream.Write(bLock); + bitStream.Write(emoteID); + } + + bool SetEmoteLockState::Deserialize(RakNet::BitStream& bitStream) { + VALIDATE_READ(bitStream.Read(bLock)); + VALIDATE_READ(bitStream.Read(emoteID)); + return true; + } +} diff --git a/dGame/dGameMessages/EffectsMessages.h b/dGame/dGameMessages/EffectsMessages.h new file mode 100644 index 000000000..518603524 --- /dev/null +++ b/dGame/dGameMessages/EffectsMessages.h @@ -0,0 +1,327 @@ +#ifndef EFFECTSMESSAGES_H +#define EFFECTSMESSAGES_H + +#include "GameMessages.h" +#include "Amf3.h" +#include "eAnimationFlags.h" +#include "eCinematicEvent.h" +#include "eEndBehavior.h" + +#include + +// Game messages for effects, audio, animations, emotes, cinematics and UI text (message boxes, chat bubbles, +// billboards, UI messages, slash command feedback). +// Field names follow the client (legouniverse.exe 1.10.64); fields are listed in wire order. +namespace GameMessages { + // Server -> client, broadcast. + struct PlayAnimation : public NetGameMsg { + PlayAnimation() : NetGameMsg(MessageType::Game::PLAY_ANIMATION) {} + PlayAnimation(const LWOOBJID _target, const std::u16string& _animationID) : PlayAnimation() { + target = _target; + animationID = _animationID; + } + void Serialize(RakNet::BitStream& bitStream) const override; + bool Deserialize(RakNet::BitStream& bitStream) override; + + // Written as a u32 length followed by that many UTF-16 characters, where the length is the size of the + // name converted to UTF-8 (so a non-ASCII name is padded with null characters). This is what DLU has + // always sent. + std::u16string animationID{}; + bool bExpectAnimToExist{ true }; + bool bPlayImmediate{}; + bool bTriggerOnCompleteMsg{}; + float fPriority{ 0.0f }; // optional + float fScale{ 1.0f }; // optional + }; + + // Server -> client, broadcast. + struct PlayNDAudioEmitter : public NetGameMsg { + PlayNDAudioEmitter() : NetGameMsg(MessageType::Game::PLAY_ND_AUDIO_EMITTER) {} + PlayNDAudioEmitter(const LWOOBJID _target, const std::string& _NDAudioEventGUID) : PlayNDAudioEmitter() { + target = _target; + NDAudioEventGUID = _NDAudioEventGUID; + } + void Serialize(RakNet::BitStream& bitStream) const override; + bool Deserialize(RakNet::BitStream& bitStream) override; + + LWOOBJID NDAudioCallbackMessageData{}; // optional + uint32_t NDAudioEmitterID{}; // optional + std::string NDAudioEventGUID{}; + std::string NDAudioMetaEventName{}; + bool result{}; + LWOOBJID targetObjectIDForNDAudioCallbackMessages{ LWOOBJID_EMPTY }; // optional + }; + + // Server -> client, broadcast. + struct PlayEmbeddedEffectOnAllClientsNearObject : public NetGameMsg { + PlayEmbeddedEffectOnAllClientsNearObject() : NetGameMsg(MessageType::Game::PLAY_EMBEDDED_EFFECT_ON_ALL_CLIENTS_NEAR_OBJECT) {} + void Serialize(RakNet::BitStream& bitStream) const override; + bool Deserialize(RakNet::BitStream& bitStream) override; + + std::u16string effectName{}; + LWOOBJID fromObjectID{}; + float radius{}; + }; + + // Server -> client, broadcast. + struct PlayFXEffect : public NetGameMsg { + PlayFXEffect() : NetGameMsg(MessageType::Game::PLAY_FX_EFFECT) {} + PlayFXEffect(const LWOOBJID _target, const int32_t _effectID, const std::u16string& _effectType, const std::string& _name) : PlayFXEffect() { + target = _target; + effectID = _effectID; + effectType = _effectType; + name = _name; + } + void Serialize(RakNet::BitStream& bitStream) const override; + bool Deserialize(RakNet::BitStream& bitStream) override; + + int32_t effectID{ -1 }; // optional + std::u16string effectType{}; + float scale{ 1.0f }; // optional + std::string name{}; + float priority{ 1.0f }; // optional + LWOOBJID secondary{ LWOOBJID_EMPTY }; // optional + bool serialize{ true }; + }; + + // Server -> client, broadcast. + struct StopFXEffect : public NetGameMsg { + StopFXEffect() : NetGameMsg(MessageType::Game::STOP_FX_EFFECT) {} + StopFXEffect(const LWOOBJID _target, const bool _killImmediate, const std::string& _name) : StopFXEffect() { + target = _target; + killImmediate = _killImmediate; + name = _name; + } + void Serialize(RakNet::BitStream& bitStream) const override; + bool Deserialize(RakNet::BitStream& bitStream) override; + + bool killImmediate{}; + std::string name{}; + }; + + // Server -> client, broadcast. + struct BroadcastTextToChatbox : public NetGameMsg { + BroadcastTextToChatbox() : NetGameMsg(MessageType::Game::BROADCAST_TEXT_TO_CHATBOX) {} + void Serialize(RakNet::BitStream& bitStream) const override; + bool Deserialize(RakNet::BitStream& bitStream) override; + + // Name value text: u32 length, the characters, then a null character that DLU always writes (even when empty). + std::u16string attrs{}; + std::u16string wsText{}; + }; + + // Server -> client. + struct Play2DAmbientSound : public NetGameMsg { + Play2DAmbientSound() : NetGameMsg(MessageType::Game::PLAY2_D_AMBIENT_SOUND) {} + void Serialize(RakNet::BitStream& bitStream) const override; + bool Deserialize(RakNet::BitStream& bitStream) override; + + std::string audioGUID{}; + bool result{}; + }; + + // Server -> client. + struct Stop2DAmbientSound : public NetGameMsg { + Stop2DAmbientSound() : NetGameMsg(MessageType::Game::STOP2_D_AMBIENT_SOUND) {} + void Serialize(RakNet::BitStream& bitStream) const override; + bool Deserialize(RakNet::BitStream& bitStream) override; + + bool force{}; + std::string audioGUID{}; + bool result{}; + }; + + // Server -> client. + struct UIMessageServerToSingleClient : public NetGameMsg { + UIMessageServerToSingleClient() : NetGameMsg(MessageType::Game::UI_MESSAGE_SERVER_TO_SINGLE_CLIENT) {} + void Serialize(RakNet::BitStream& bitStream) const override; + bool Deserialize(RakNet::BitStream& bitStream) override; + + AMFArrayValue args{}; + std::string strMessageName{}; + }; + + // Server -> client. Broadcast, or sent to one client (DLU uses it to reach a client that may not have an + // entity yet; the target is then LWOOBJID_EMPTY). + struct UIMessageServerToAllClients : public NetGameMsg { + UIMessageServerToAllClients() : NetGameMsg(MessageType::Game::UI_MESSAGE_SERVER_TO_ALL_CLIENTS) {} + void Serialize(RakNet::BitStream& bitStream) const override; + bool Deserialize(RakNet::BitStream& bitStream) override; + + AMFArrayValue args{}; + std::string strMessageName{}; + }; + + // Server -> client. + struct StartCelebrationEffect : public NetGameMsg { + StartCelebrationEffect() : NetGameMsg(MessageType::Game::START_CELEBRATION_EFFECT) {} + void Serialize(RakNet::BitStream& bitStream) const override; + bool Deserialize(RakNet::BitStream& bitStream) override; + + std::u16string animation{}; + LOT backgroundObject{ 11164 }; // optional + LOT cameraPathLOT{ 12458 }; // optional + float celeLeadIn{ 1.0f }; // optional + float celeLeadOut{ 0.8f }; // optional + int32_t celebrationID{ -1 }; // optional; DLU always writes it, even when it has the default value + float duration{}; + uint32_t iconID{}; + std::u16string mainText{}; + std::string mixerProgram{}; + std::string musicCue{}; + std::string pathNodeName{}; + std::string soundGUID{}; + std::u16string subText{}; + }; + + // Server -> client. + struct DisplayMessageBox : public NetGameMsg { + DisplayMessageBox() : NetGameMsg(MessageType::Game::DISPLAY_MESSAGE_BOX) {} + void Serialize(RakNet::BitStream& bitStream) const override; + bool Deserialize(RakNet::BitStream& bitStream) override; + + bool bShow{}; + LWOOBJID callbackClient{}; + std::u16string identifier{}; + int32_t imageID{}; + std::u16string text{}; + std::u16string userData{}; + }; + + // Client -> server. Sent to the callbackClient of a DisplayMessageBox when the player presses a button. + struct MessageBoxRespond : public NetGameMsg { + MessageBoxRespond() : NetGameMsg(MessageType::Game::MESSAGE_BOX_RESPOND) {} + void Serialize(RakNet::BitStream& bitStream) const override; + bool Deserialize(RakNet::BitStream& bitStream) override; + void Handle(Entity& entity, const SystemAddress& sysAddr) override; + + int32_t iButton{}; + std::u16string identifier{}; + std::u16string userData{}; + }; + + // Client -> server. + struct ChoiceBoxRespond : public NetGameMsg { + ChoiceBoxRespond() : NetGameMsg(MessageType::Game::CHOICE_BOX_RESPOND) {} + void Serialize(RakNet::BitStream& bitStream) const override; + bool Deserialize(RakNet::BitStream& bitStream) override; + void Handle(Entity& entity, const SystemAddress& sysAddr) override; + + std::u16string buttonIdentifier{}; + int32_t iButton{}; + std::u16string identifier{}; + }; + + // Server -> client. + struct DisplayChatBubble : public NetGameMsg { + DisplayChatBubble() : NetGameMsg(MessageType::Game::DISPLAY_CHAT_BUBBLE) {} + void Serialize(RakNet::BitStream& bitStream) const override; + bool Deserialize(RakNet::BitStream& bitStream) override; + + std::u16string wsText{}; + }; + + // Server -> client, broadcast. + struct ChangeIdleFlags : public NetGameMsg { + ChangeIdleFlags() : NetGameMsg(MessageType::Game::CHANGE_IDLE_FLAGS) {} + void Serialize(RakNet::BitStream& bitStream) const override; + bool Deserialize(RakNet::BitStream& bitStream) override; + + eAnimationFlags flagsOff{ eAnimationFlags::IDLE_NONE }; // optional + eAnimationFlags flagsOn{ eAnimationFlags::IDLE_NONE }; // optional + }; + + // Server -> client. The client's message has two bools (overrideDefault, state), but the client never reads + // them, so DLU sends no payload; the message only turns the name billboard off. + struct SetNameBillboardState : public NetGameMsg { + SetNameBillboardState() : NetGameMsg(MessageType::Game::SET_NAME_BILLBOARD_STATE) {} + }; + + // Server -> client. No payload. + struct ShowBillboardInteractIcon : public NetGameMsg { + ShowBillboardInteractIcon() : NetGameMsg(MessageType::Game::SHOW_BILLBOARD_INTERACT_ICON) {} + }; + + // Server -> client. + struct PlayCinematic : public NetGameMsg { + PlayCinematic() : NetGameMsg(MessageType::Game::PLAY_CINEMATIC) {} + void Serialize(RakNet::BitStream& bitStream) const override; + bool Deserialize(RakNet::BitStream& bitStream) override; + + bool allowGhostUpdates{ true }; + bool bCloseMultiInteract{ true }; + bool bSendServerNotify{}; + bool bUseControlledObjectForAudioListener{}; + eEndBehavior endBehavior{ eEndBehavior::RETURN }; // optional + bool hidePlayerDuringCine{}; + float leadIn{ -1.0f }; // optional + bool leavePlayerLockedWhenFinished{}; + bool lockPlayer{ true }; + std::u16string pathName{}; + bool result{}; + bool skipIfSamePath{}; + float startTimeAdvance{}; + }; + + // Server -> client. + struct EndCinematic : public NetGameMsg { + EndCinematic() : NetGameMsg(MessageType::Game::END_CINEMATIC) {} + void Serialize(RakNet::BitStream& bitStream) const override; + bool Deserialize(RakNet::BitStream& bitStream) override; + + float leadOut{ -1.0f }; // optional + bool leavePlayerLocked{}; + std::u16string pathName{}; + }; + + // Client -> server. + struct CinematicUpdate : public NetGameMsg { + CinematicUpdate() : NetGameMsg(MessageType::Game::CINEMATIC_UPDATE) {} + void Serialize(RakNet::BitStream& bitStream) const override; + bool Deserialize(RakNet::BitStream& bitStream) override; + void Handle(Entity& entity, const SystemAddress& sysAddr) override; + + eCinematicEvent event{ eCinematicEvent::STARTED }; // optional + float overallTime{ -1.0f }; // optional + std::u16string pathName{}; + float pathTime{ -1.0f }; // optional + int32_t waypoint{ -1 }; // optional + }; + + // Server -> client. + struct SlashCommandTextFeedback : public NetGameMsg { + SlashCommandTextFeedback() : NetGameMsg(MessageType::Game::SLASH_COMMAND_TEXT_FEEDBACK) {} + SlashCommandTextFeedback(const LWOOBJID _target, const std::u16string& _text) : SlashCommandTextFeedback() { + target = _target; + text = _text; + } + void Serialize(RakNet::BitStream& bitStream) const override; + bool Deserialize(RakNet::BitStream& bitStream) override; + + std::u16string text{}; + }; + + // Both directions: the client asks to play an emote (handled here), and the server tells clients an object + // plays one. + struct PlayEmote : public NetGameMsg { + PlayEmote() : NetGameMsg(MessageType::Game::PLAY_EMOTE) {} + void Serialize(RakNet::BitStream& bitStream) const override; + bool Deserialize(RakNet::BitStream& bitStream) override; + void Handle(Entity& entity, const SystemAddress& sysAddr) override; + + int32_t emoteID{}; + LWOOBJID targetID{}; + }; + + // Server -> client. + struct SetEmoteLockState : public NetGameMsg { + SetEmoteLockState() : NetGameMsg(MessageType::Game::SET_EMOTE_LOCK_STATE) {} + void Serialize(RakNet::BitStream& bitStream) const override; + bool Deserialize(RakNet::BitStream& bitStream) override; + + bool bLock{}; + int32_t emoteID{}; + }; +}; + +#endif // EFFECTSMESSAGES_H diff --git a/dGame/dGameMessages/GameMessageHandler.cpp b/dGame/dGameMessages/GameMessageHandler.cpp index 3ea3c64e2..3fe8a82d3 100644 --- a/dGame/dGameMessages/GameMessageHandler.cpp +++ b/dGame/dGameMessages/GameMessageHandler.cpp @@ -35,6 +35,7 @@ #include "BuildingMessages.h" #include "RacingMessages.h" #include "MissionMessages.h" +#include "EffectsMessages.h" #include "PetMessages.h" #include "PropertyMessages.h" #include "eMissionTaskType.h" @@ -76,6 +77,12 @@ namespace { { SET_FLAG, []() { return std::make_unique(); } }, { HAS_BEEN_COLLECTED, []() { return std::make_unique(); } }, + // Effects, emotes, cinematics, UI + { PLAY_EMOTE, []() { return std::make_unique(); } }, + { MESSAGE_BOX_RESPOND, []() { return std::make_unique(); } }, + { CHOICE_BOX_RESPOND, []() { return std::make_unique(); } }, + { CINEMATIC_UPDATE, []() { return std::make_unique(); } }, + // Pets { PET_TAMING_TRY_BUILD, []() { return std::make_unique(); } }, { NOTIFY_TAMING_BUILD_SUCCESS, []() { return std::make_unique(); } }, @@ -166,11 +173,6 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream& inStream, const System switch (messageID) { - case MessageType::Game::PLAY_EMOTE: { - GameMessages::HandlePlayEmote(inStream, entity); - break; - } - case MessageType::Game::MOVE_ITEM_IN_INVENTORY: { GameMessages::HandleMoveItemInInventory(inStream, entity); break; @@ -287,7 +289,9 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream& inStream, const System || !entity->GetCharacter()->GetPlayerFlag(ePlayerFlag::DLU_SKIP_CINEMATICS)) return; entity->AddCallbackTimer(0.5f, [entity, sysAddr]() { if (!entity) return; - GameMessages::SendEndCinematic(entity->GetObjectID(), u"", sysAddr); + GameMessages::EndCinematic endCinematic; + endCinematic.target = entity->GetObjectID(); + endCinematic.Send(sysAddr); }); break; } @@ -520,14 +524,6 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream& inStream, const System GameMessages::HandleClientTradeUpdate(inStream, entity, sysAddr); break; - case MessageType::Game::MESSAGE_BOX_RESPOND: - GameMessages::HandleMessageBoxResponse(inStream, entity, sysAddr); - break; - - case MessageType::Game::CHOICE_BOX_RESPOND: - GameMessages::HandleChoiceBoxRespond(inStream, entity, sysAddr); - break; - // Racing: most racing messages are registered in g_MessageHandlers case MessageType::Game::ACKNOWLEDGE_POSSESSION: GameMessages::HandleAcknowledgePossession(inStream, entity, sysAddr); @@ -575,10 +571,6 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream& inStream, const System GameMessages::HandlePlayerRailArrivedNotification(inStream, entity, sysAddr); break; - case MessageType::Game::CINEMATIC_UPDATE: - GameMessages::HandleCinematicUpdate(inStream, entity, sysAddr); - break; - case MessageType::Game::MODIFY_PLAYER_ZONE_STATISTIC: GameMessages::HandleModifyPlayerZoneStatistic(inStream, entity); break; diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index 90feea390..8b930a1a1 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -1,4 +1,5 @@ #include "GameMessages.h" +#include "EffectsMessages.h" #include "DashboardNotify.h" #include "PlayerReports.h" #include "EconomyLedger.h" @@ -162,43 +163,6 @@ void GameMessages::SendTeleport(const LWOOBJID& objectID, const NiPoint3& pos, c SEND_PACKET; } -void GameMessages::SendPlayAnimation(Entity* entity, const std::u16string& animationName, float fPriority, float fScale) { - if (!entity) { - LOG("Trying to play animation, but entity var is nullptr!"); - return; - } - - //Stolen from the old DLU codebase as the new one's autogenerated code doesn't work properly for animationIDs longer than 6 characters. - CBITSTREAM; - CMSGHEADER; - std::string sAnimationID = GeneralUtils::UTF16ToWTF8(animationName); - - uint32_t animationIDLength = sAnimationID.size(); - bool bExpectAnimToExist = true; - bool bPlayImmediate = false; - bool bTriggerOnCompleteMsg = false; - - bitStream.Write(entity->GetObjectID()); - bitStream.Write(MessageType::Game::PLAY_ANIMATION); - - bitStream.Write(animationIDLength); - bitStream.Write(LUWString(animationName, animationIDLength)); - - bitStream.Write(bExpectAnimToExist); - - bitStream.Write(bPlayImmediate); - - bitStream.Write(bTriggerOnCompleteMsg); - - bitStream.Write(fPriority != 0.0f); - if (fPriority != 0.0f) bitStream.Write(fPriority); - - bitStream.Write(fScale != 1.0f); - if (fScale != 1.0f) bitStream.Write(fScale); - - SEND_PACKET_BROADCAST; -} - void GameMessages::SendPlayerReady(Entity* entity, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -283,28 +247,6 @@ void GameMessages::SendPlayerSetCameraCyclingMode(const LWOOBJID& objectID, cons SEND_PACKET; } -void GameMessages::SendPlayNDAudioEmitter(Entity* entity, const SystemAddress& sysAddr, std::string audioGUID) { - CBITSTREAM; - CMSGHEADER; - - bitStream.Write(entity->GetObjectID()); - bitStream.Write(MessageType::Game::PLAY_ND_AUDIO_EMITTER); - bitStream.Write0(); // callback message data {lwoobjid} - bitStream.Write0(); // audio emitterid {uint32_t} - - uint32_t length = audioGUID.size(); - bitStream.Write(length); - for (uint32_t k = 0; k < length; k++) { - bitStream.Write(audioGUID[k]); - } - - bitStream.Write(0); // size of NDAudioMetaEventName (then print the string like the guid) - bitStream.Write0(); // result {bool} - bitStream.Write0(); // m_TargetObjectIDForNDAudioCallbackMessages {lwoobjid} - - SEND_PACKET_BROADCAST; -} - void GameMessages::SendStartPathing(Entity* entity) { CBITSTREAM; CMSGHEADER; @@ -491,153 +433,6 @@ void GameMessages::SendModifyLEGOScore(Entity* entity, const SystemAddress& sysA SEND_PACKET; } -void GameMessages::SendUIMessageServerToSingleClient(Entity* entity, const SystemAddress& sysAddr, const std::string& message, AMFBaseValue& args) { - CBITSTREAM; - CMSGHEADER; - - bitStream.Write(entity->GetObjectID()); - bitStream.Write(MessageType::Game::UI_MESSAGE_SERVER_TO_SINGLE_CLIENT); - - bitStream.Write(args); - uint32_t strMessageNameLength = message.size(); - bitStream.Write(strMessageNameLength); - - for (uint32_t k = 0; k < strMessageNameLength; k++) { - bitStream.Write(message[k]); - } - - SEND_PACKET; -} - -void GameMessages::SendUIMessageServerToSingleClient(const std::string& message, AMFBaseValue& args, const SystemAddress& sysAddr) { - CBITSTREAM; - CMSGHEADER; - - LWOOBJID empty = 0; - bitStream.Write(empty); - bitStream.Write(MessageType::Game::UI_MESSAGE_SERVER_TO_ALL_CLIENTS); // This is intentional to allow the server to send a ui message to a client via their system address. - - bitStream.Write(args); - uint32_t strMessageNameLength = message.size(); - bitStream.Write(strMessageNameLength); - - for (uint32_t k = 0; k < strMessageNameLength; k++) { - bitStream.Write(message[k]); - } - - SEND_PACKET; -} - -void GameMessages::SendUIMessageServerToAllClients(const std::string& message, AMFBaseValue& args) { - CBITSTREAM; - CMSGHEADER; - - LWOOBJID empty = 0; - bitStream.Write(empty); - bitStream.Write(MessageType::Game::UI_MESSAGE_SERVER_TO_ALL_CLIENTS); - - bitStream.Write(args); - uint32_t strMessageNameLength = message.size(); - bitStream.Write(strMessageNameLength); - - for (uint32_t k = 0; k < strMessageNameLength; k++) { - bitStream.Write(message[k]); - } - - SEND_PACKET_BROADCAST; -} - -void GameMessages::SendPlayEmbeddedEffectOnAllClientsNearObject(Entity* entity, std::u16string effectName, const LWOOBJID& fromObjectID, float radius) { - CBITSTREAM; - CMSGHEADER; - - bitStream.Write(entity->GetObjectID()); - bitStream.Write(MessageType::Game::PLAY_EMBEDDED_EFFECT_ON_ALL_CLIENTS_NEAR_OBJECT); - - bitStream.Write(effectName.length()); - for (uint32_t k = 0; k < effectName.length(); k++) { - bitStream.Write(effectName[k]); - } - bitStream.Write(fromObjectID); - bitStream.Write(radius); - - SEND_PACKET_BROADCAST; -} - -void GameMessages::SendPlayFXEffect(Entity* entity, int32_t effectID, const std::u16string& effectType, const std::string& name, LWOOBJID secondary, float priority, float scale, bool serialize) { - SendPlayFXEffect(entity->GetObjectID(), effectID, effectType, name, secondary, priority, scale, serialize); -} - -void GameMessages::SendPlayFXEffect(const LWOOBJID& entity, int32_t effectID, const std::u16string& effectType, const std::string& name, LWOOBJID secondary, float priority, float scale, bool serialize) { - CBITSTREAM; - CMSGHEADER; - - bitStream.Write(entity); - bitStream.Write(MessageType::Game::PLAY_FX_EFFECT); - - bitStream.Write(effectID != -1); - if (effectID != -1) bitStream.Write(effectID); - - bitStream.Write(effectType.size()); - for (const auto& k : effectType) { - bitStream.Write(k); - } - - bitStream.Write(scale != 1.0f); - if (scale != 1.0f) bitStream.Write(scale); - - bitStream.Write(name.size()); - for (const auto& k : name) { - bitStream.Write(k); - } - - bitStream.Write(priority != 1.0); - if (priority != 1.0) bitStream.Write(priority); - - bitStream.Write(secondary != LWOOBJID_EMPTY); - if (secondary != LWOOBJID_EMPTY) bitStream.Write(secondary); - - bitStream.Write(serialize); - - SEND_PACKET_BROADCAST; -} - -void GameMessages::SendStopFXEffect(Entity* entity, bool killImmediate, std::string name) { - CBITSTREAM; - CMSGHEADER; - - bitStream.Write(entity->GetObjectID()); - bitStream.Write(MessageType::Game::STOP_FX_EFFECT); - - bitStream.Write(killImmediate); - bitStream.Write(name.size()); - bitStream.Write(name.c_str(), name.size()); - - SEND_PACKET_BROADCAST; -} - -void GameMessages::SendBroadcastTextToChatbox(Entity* entity, const SystemAddress& sysAddr, const std::u16string& attrs, const std::u16string& wsText) { - CBITSTREAM; - CMSGHEADER; - - bitStream.Write(entity->GetObjectID()); - bitStream.Write(MessageType::Game::BROADCAST_TEXT_TO_CHATBOX); - - bitStream.Write(attrs.size()); - for (uint32_t i = 0; i < attrs.size(); ++i) { - bitStream.Write(attrs[i]); - } - bitStream.Write(0x00); // Null Terminator - - uint32_t wsTextLength = wsText.size(); - bitStream.Write(wsTextLength); - for (uint32_t k = 0; k < wsTextLength; k++) { - bitStream.Write(wsText[k]); - } - - SEND_PACKET_BROADCAST; -} - void GameMessages::SendSetCurrency(Entity* entity, int64_t currency, int lootType, const LWOOBJID& sourceID, const LOT& sourceLOT, int sourceTradeID, bool overrideCurrent, eLootSourceType sourceType) { CBITSTREAM; CMSGHEADER; @@ -792,19 +587,6 @@ void GameMessages::SendSetInventorySize(Entity* entity, int invType, int size) { SEND_PACKET; } -void GameMessages::SendSetEmoteLockState(Entity* entity, bool bLock, int emoteID) { - CBITSTREAM; - CMSGHEADER; - - bitStream.Write(entity->GetObjectID()); - bitStream.Write(MessageType::Game::SET_EMOTE_LOCK_STATE); - bitStream.Write(bLock); - bitStream.Write(emoteID); - - SystemAddress sysAddr = entity->GetSystemAddress(); - SEND_PACKET; -} - void GameMessages::SendSetJetPackMode(Entity* entity, bool use, bool bypassChecks, bool doHover, int effectID, float airspeed, float maxAirspeed, float verticalVelocity, int warningEffectID) { /* historical jamesster jetpack values if (bIsJamessterPhysics) { @@ -880,47 +662,6 @@ void GameMessages::SendResurrect(Entity* entity) { SEND_PACKET_BROADCAST; } -void GameMessages::SendStop2DAmbientSound(Entity* entity, bool force, std::string audioGUID, bool result) { - CBITSTREAM; - CMSGHEADER; - - bitStream.Write(entity->GetObjectID()); - bitStream.Write(MessageType::Game::STOP2_D_AMBIENT_SOUND); - - uint32_t audioGUIDSize = audioGUID.size(); - - bitStream.Write(force); - bitStream.Write(audioGUIDSize); - - for (uint32_t k = 0; k < audioGUIDSize; k++) { - bitStream.Write(audioGUID[k]); - } - - bitStream.Write(result); - - SystemAddress sysAddr = entity->GetSystemAddress(); - - SEND_PACKET; -} - -void GameMessages::SendPlay2DAmbientSound(Entity* entity, std::string audioGUID, bool result) { - CBITSTREAM; - CMSGHEADER; - - bitStream.Write(entity->GetObjectID()); - bitStream.Write(MessageType::Game::PLAY2_D_AMBIENT_SOUND); - uint32_t audioGUIDSize = audioGUID.size(); - - bitStream.Write(audioGUIDSize); - for (uint32_t k = 0; k < audioGUIDSize; k++) { - bitStream.Write(audioGUID[k]); - } - bitStream.Write(result); - - SystemAddress sysAddr = entity->GetSystemAddress(); - SEND_PACKET; -} - void GameMessages::SendSetNetworkScriptVar(Entity* entity, const SystemAddress& sysAddr, std::string data) { CBITSTREAM; CMSGHEADER; @@ -1424,33 +1165,6 @@ void GameMessages::HandleActivityStateChangeRequest(RakNet::BitStream& inStream, entity->OnActivityStateChangeRequest(objectID, value1, value2, stringValue); } -void GameMessages::SendStartCelebrationEffect(Entity* entity, const SystemAddress& sysAddr, int celebrationID) { - CBITSTREAM; - CMSGHEADER; - - bitStream.Write(entity->GetObjectID()); - bitStream.Write(MessageType::Game::START_CELEBRATION_EFFECT); - - bitStream.Write(0); //animation - bitStream.Write0(); //No custom bg obj - bitStream.Write0(); //custom path - bitStream.Write0(); //leadin - bitStream.Write0(); //leadout - bitStream.Write1(); - bitStream.Write(celebrationID); - bitStream.Write(0.0f); //duration - bitStream.Write(0); //icon - bitStream.Write(0); //text - bitStream.Write(0); //mixer - bitStream.Write(0); //cue - bitStream.Write(0); //pathnodename - bitStream.Write(0); //soundguid - bitStream.Write(0); //subtext - - SEND_PACKET; -} - - void GameMessages::SendSetRailMovement(const LWOOBJID& objectID, bool pathGoForward, std::u16string pathName, uint32_t pathStart, const SystemAddress& sysAddr, int32_t railActivatorComponentID, LWOOBJID railActivatorObjectID) { @@ -1696,114 +1410,6 @@ void GameMessages::HandleSetConsumableItem(RakNet::BitStream& inStream, Entity* inventory->SetConsumable(lot); } -void GameMessages::SendPlayCinematic(LWOOBJID objectId, std::u16string pathName, const SystemAddress& sysAddr, - bool allowGhostUpdates, bool bCloseMultiInteract, bool bSendServerNotify, bool bUseControlledObjectForAudioListener, - eEndBehavior endBehavior, bool hidePlayerDuringCine, float leadIn, bool leavePlayerLockedWhenFinished, - bool lockPlayer, bool result, bool skipIfSamePath, float startTimeAdvance) { - CBITSTREAM; - CMSGHEADER; - - bitStream.Write(objectId); - bitStream.Write(MessageType::Game::PLAY_CINEMATIC); - - bitStream.Write(allowGhostUpdates); - bitStream.Write(bCloseMultiInteract); - bitStream.Write(bSendServerNotify); - bitStream.Write(bUseControlledObjectForAudioListener); - - bitStream.Write(endBehavior != eEndBehavior::RETURN); - if (endBehavior != eEndBehavior::RETURN) bitStream.Write(endBehavior); - - bitStream.Write(hidePlayerDuringCine); - - bitStream.Write(leadIn != -1); - if (leadIn != -1) bitStream.Write(leadIn); - - bitStream.Write(leavePlayerLockedWhenFinished); - bitStream.Write(lockPlayer); - - bitStream.Write(pathName.size()); - for (char16_t c : pathName) { - bitStream.Write(c); - } - - bitStream.Write(result); - - bitStream.Write(skipIfSamePath); - - bitStream.Write(startTimeAdvance); - - if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST; - SEND_PACKET; -} - -void GameMessages::SendEndCinematic(LWOOBJID objectId, std::u16string pathName, const SystemAddress& sysAddr, - float leadOut, bool leavePlayerLocked) { - CBITSTREAM; - CMSGHEADER; - - bitStream.Write(objectId); - bitStream.Write(MessageType::Game::END_CINEMATIC); - - bitStream.Write(leadOut != -1); - if (leadOut != -1) bitStream.Write(leadOut); - - bitStream.Write(leavePlayerLocked); - - bitStream.Write(pathName.size()); - for (uint32_t i = 0; i < pathName.size(); i++) { - bitStream.Write(pathName[i]); - } - - if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST; - SEND_PACKET; -} - -void GameMessages::HandleCinematicUpdate(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr) { - eCinematicEvent event; - if (!inStream.ReadBit()) { - event = eCinematicEvent::STARTED; - } else { - inStream.Read(event); - } - - float_t overallTime; - if (!inStream.ReadBit()) { - overallTime = -1.0f; - } else { - inStream.Read(overallTime); - } - - uint32_t pathNameLength; - inStream.Read(pathNameLength); - - std::u16string pathName; - for (size_t i = 0; i < pathNameLength; i++) { - char16_t character; - inStream.Read(character); - pathName.push_back(character); - } - - float_t pathTime; - if (!inStream.ReadBit()) { - pathTime = -1.0f; - } else { - inStream.Read(pathTime); - } - - int32_t waypoint; - if (!inStream.ReadBit()) { - waypoint = -1; - } else { - inStream.Read(waypoint); - } - - std::vector scriptedActs = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::SCRIPT); - for (Entity* scriptEntity : scriptedActs) { - scriptEntity->OnCinematicUpdate(scriptEntity, entity, event, pathName, pathTime, overallTime, waypoint); - } -} - void GameMessages::SendSetStunned(LWOOBJID objectId, eStateChangeType stateChangeType, const SystemAddress& sysAddr, LWOOBJID originator, bool bCantAttack, bool bCantEquip, bool bCantInteract, bool bCantJump, bool bCantMove, bool bCantTurn, @@ -2296,20 +1902,6 @@ void GameMessages::SendMarkInventoryItemAsActive(LWOOBJID objectId, bool bActive SEND_PACKET; } -void GameMessages::SendPlayEmote(LWOOBJID objectId, int32_t emoteID, LWOOBJID target, const SystemAddress& sysAddr) { - CBITSTREAM; - CMSGHEADER; - - bitStream.Write(objectId); - bitStream.Write(MessageType::Game::PLAY_EMOTE); - - bitStream.Write(emoteID); - bitStream.Write(target); - - if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST; - SEND_PACKET; -} - void GameMessages::SendRemoveBuff(Entity* entity, bool fromUnEquip, bool removeImmunity, uint32_t buffId) { CBITSTREAM; CMSGHEADER; @@ -2325,106 +1917,6 @@ void GameMessages::SendRemoveBuff(Entity* entity, bool fromUnEquip, bool removeI SEND_PACKET_BROADCAST; } -void GameMessages::HandleMessageBoxResponse(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr) { - int32_t iButton; - uint32_t identifierLength; - std::u16string identifier; - uint32_t userDataLength; - std::u16string userData; - - inStream.Read(iButton); - - inStream.Read(identifierLength); - if (identifierLength > MAX_MESSAGE_LENGTH) return; - for (size_t i = 0; i < identifierLength; i++) { - char16_t character; - inStream.Read(character); - identifier.push_back(character); - } - - inStream.Read(userDataLength); - if (userDataLength > MAX_MESSAGE_LENGTH) return; - for (size_t i = 0; i < userDataLength; i++) { - char16_t character; - inStream.Read(character); - userData.push_back(character); - } - - LOG("Button: %d; LOT: %u identifier: %s; userData: %s", iButton, entity->GetLOT(), GeneralUtils::UTF16ToWTF8(identifier).c_str(), GeneralUtils::UTF16ToWTF8(userData).c_str()); - - auto* user = UserManager::Instance()->GetUser(sysAddr); - - if (user == nullptr) { - return; - } - - auto* userEntity = user->GetLastUsedChar()->GetEntity(); - - if (userEntity == nullptr) { - return; - } - - entity->OnMessageBoxResponse(userEntity, iButton, identifier, userData); - - auto* scriptedActivityComponent = entity->GetComponent(); - - if (scriptedActivityComponent != nullptr) { - scriptedActivityComponent->HandleMessageBoxResponse(userEntity, GeneralUtils::UTF16ToWTF8(identifier)); - } - - auto* racingControlComponent = entity->GetComponent(); - - if (racingControlComponent != nullptr) { - racingControlComponent->HandleMessageBoxResponse(userEntity, iButton, GeneralUtils::UTF16ToWTF8(identifier)); - } - - for (auto* shootingGallery : Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::SHOOTING_GALLERY)) { - shootingGallery->OnMessageBoxResponse(userEntity, iButton, identifier, userData); - } -} - -void GameMessages::HandleChoiceBoxRespond(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr) { - int32_t iButton; - uint32_t buttonIdentifierLength; - std::u16string buttonIdentifier; - uint32_t identifierLength; - std::u16string identifier; - - inStream.Read(buttonIdentifierLength); - if (buttonIdentifierLength > MAX_MESSAGE_LENGTH) return; - for (size_t i = 0; i < buttonIdentifierLength; i++) { - char16_t character; - inStream.Read(character); - buttonIdentifier.push_back(character); - } - - inStream.Read(iButton); - - inStream.Read(identifierLength); - if (identifierLength > MAX_MESSAGE_LENGTH) return; - for (size_t i = 0; i < identifierLength; i++) { - char16_t character; - inStream.Read(character); - identifier.push_back(character); - } - - LOG("Button: %d; LOT: %u buttonIdentifier: %s; userData: %s", iButton, entity->GetLOT(), GeneralUtils::UTF16ToWTF8(buttonIdentifier).c_str(), GeneralUtils::UTF16ToWTF8(identifier).c_str()); - - auto* user = UserManager::Instance()->GetUser(sysAddr); - - if (user == nullptr) { - return; - } - - auto* userEntity = user->GetLastUsedChar()->GetEntity(); - - if (userEntity == nullptr) { - return; - } - - entity->OnChoiceBoxResponse(userEntity, iButton, buttonIdentifier, identifier); -} - void GameMessages::SendDisplayZoneSummary(LWOOBJID objectId, const SystemAddress& sysAddr, bool isPropertyMap, bool isZoneStart, LWOOBJID sender) { CBITSTREAM; CMSGHEADER; @@ -2458,68 +1950,6 @@ void GameMessages::SendNotifyNotEnoughInvSpace(LWOOBJID objectId, uint32_t freeS SEND_PACKET; } -void GameMessages::SendDisplayMessageBox(LWOOBJID objectId, bool bShow, LWOOBJID callbackClient, const std::u16string& identifier, int32_t imageID, const std::u16string& text, const std::u16string& userData, const SystemAddress& sysAddr) { - CBITSTREAM; - CMSGHEADER; - - bitStream.Write(objectId); - bitStream.Write(MessageType::Game::DISPLAY_MESSAGE_BOX); - - bitStream.Write(bShow); - bitStream.Write(callbackClient); - - bitStream.Write(identifier.size()); - for (const auto character : identifier) { - bitStream.Write(character); - } - - bitStream.Write(imageID); - - bitStream.Write(text.size()); - for (const auto character : text) { - bitStream.Write(character); - } - - bitStream.Write(userData.size()); - for (const auto character : userData) { - bitStream.Write(character); - } - - if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST; - SEND_PACKET; -} - -void GameMessages::SendDisplayChatBubble(LWOOBJID objectId, const std::u16string& text, const SystemAddress& sysAddr) { - // MessageType::Game::DISPLAY_CHAT_BUBBLE - CBITSTREAM; - CMSGHEADER; - - bitStream.Write(objectId); - bitStream.Write(MessageType::Game::DISPLAY_CHAT_BUBBLE); - - bitStream.Write(text.size()); - for (const auto character : text) { - bitStream.Write(character); - } - - if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST; - SEND_PACKET; -} - - -void GameMessages::SendChangeIdleFlags(LWOOBJID objectId, eAnimationFlags flagsOn, eAnimationFlags flagsOff, const SystemAddress& sysAddr) { - CBITSTREAM; - CMSGHEADER; - - bitStream.Write(objectId); - bitStream.Write(MessageType::Game::CHANGE_IDLE_FLAGS); - bitStream.Write(flagsOff != eAnimationFlags::IDLE_NONE); - if (flagsOff != eAnimationFlags::IDLE_NONE) bitStream.Write(flagsOff); - bitStream.Write(flagsOn != eAnimationFlags::IDLE_NONE); - if (flagsOn != eAnimationFlags::IDLE_NONE) bitStream.Write(flagsOn); - - SEND_PACKET_BROADCAST; -} // Mounts void GameMessages::SendSetMountInventoryID(Entity* entity, const LWOOBJID& objectID, const SystemAddress& sysAddr) { @@ -3143,59 +2573,6 @@ void GameMessages::HandleQuickBuildCancel(RakNet::BitStream& inStream, Entity* e quickBuildComponent->CancelQuickBuild(Game::entityManager->GetEntity(userID), eQuickBuildFailReason::CANCELED_EARLY); } -void GameMessages::HandlePlayEmote(RakNet::BitStream& inStream, Entity* entity) { - int32_t emoteID; - LWOOBJID targetID; - - inStream.Read(emoteID); - inStream.Read(targetID); - - LOG_DEBUG("Emote (%i) (%llu)", emoteID, targetID); - - //TODO: If targetID != 0, and we have one of the "perform emote" missions, complete them. - - if (emoteID == 0) return; - std::string sAnimationName = "deaded"; //Default name in case we fail to get the emote - - CDEmoteTableTable* emotes = CDClientManager::GetTable(); - if (emotes) { - CDEmoteTable* emote = emotes->GetEmote(emoteID); - if (emote) sAnimationName = emote->animationName; - } - - GameMessages::EmotePlayed msg; - msg.target = entity->GetObjectID(); - msg.emoteID = emoteID; - msg.targetID = targetID; // The emote’s target entity or 0 if none - msg.Send(UNASSIGNED_SYSTEM_ADDRESS); // Broadcast to all clients - - MissionComponent* missionComponent = entity->GetComponent(); - if (!missionComponent) return; - - if (targetID != LWOOBJID_EMPTY) { - auto* targetEntity = Game::entityManager->GetEntity(targetID); - - LOG_DEBUG("Emote target found (%d)", targetEntity != nullptr); - - if (targetEntity != nullptr) { - targetEntity->OnEmoteReceived(emoteID, entity); - missionComponent->Progress(eMissionTaskType::EMOTE, emoteID, targetID); - } - } else { - LOG_DEBUG("Target ID is empty, using backup"); - const auto scriptedEntities = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::SCRIPT); - - const auto& referencePoint = entity->GetPosition(); - - for (auto* scripted : scriptedEntities) { - if (Vector3::DistanceSquared(scripted->GetPosition(), referencePoint) > 5.0f * 5.0f) continue; - - scripted->OnEmoteReceived(emoteID, entity); - missionComponent->Progress(eMissionTaskType::EMOTE, emoteID, scripted->GetObjectID()); - } - } -} - void GameMessages::HandleNotifyServerLevelProcessingComplete(RakNet::BitStream& inStream, Entity* entity) { auto* levelComp = entity->GetComponent(); if (!levelComp) return; @@ -3218,7 +2595,7 @@ void GameMessages::HandleNotifyServerLevelProcessingComplete(RakNet::BitStream& } //Play the level up effect: - GameMessages::SendPlayFXEffect(entity, 7074, u"create", "7074", LWOOBJID_EMPTY, 1.0f, 1.0f, true); + GameMessages::PlayFXEffect(entity->GetObjectID(), 7074, u"create", "7074").Send(UNASSIGNED_SYSTEM_ADDRESS); //Send a notification in chat: std::stringstream wss; @@ -3232,7 +2609,11 @@ void GameMessages::HandleNotifyServerLevelProcessingComplete(RakNet::BitStream& std::u16string attrs = GeneralUtils::UTF8ToUTF16(wss.str()); std::u16string wsText = u"UI_LEVEL_PROGRESSION_LEVELUP_MESSAGE"; - GameMessages::SendBroadcastTextToChatbox(entity, UNASSIGNED_SYSTEM_ADDRESS, attrs, wsText); + GameMessages::BroadcastTextToChatbox chatboxText; + chatboxText.target = entity->GetObjectID(); + chatboxText.attrs = attrs; + chatboxText.wsText = wsText; + chatboxText.Send(UNASSIGNED_SYSTEM_ADDRESS); } void GameMessages::HandlePickupCurrency(RakNet::BitStream& inStream, Entity* entity) { @@ -3809,35 +3190,6 @@ void GameMessages::HandleZoneSummaryDismissed(RakNet::BitStream& inStream, Entit entity->TriggerEvent(eTriggerEventType::ZONE_SUMMARY_DISMISSED, target); }; -void GameMessages::SendSetNamebillboardState(const SystemAddress& sysAddr, LWOOBJID objectId) { - CBITSTREAM; - CMSGHEADER; - - bitStream.Write(objectId); - bitStream.Write(MessageType::Game::SET_NAME_BILLBOARD_STATE); - - // Technically these bits would be written, however the client does not - // contain a deserialize method to actually deserialize, so we are leaving it out. - // As such this GM only turns the billboard off. - - // bitStream.Write(overrideDefault); - // bitStream.Write(state); - - if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST - else SEND_PACKET -} - -void GameMessages::SendShowBillboardInteractIcon(const SystemAddress& sysAddr, LWOOBJID objectId) { - CBITSTREAM; - CMSGHEADER; - - bitStream.Write(objectId); - bitStream.Write(MessageType::Game::SHOW_BILLBOARD_INTERACT_ICON); - - if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST - else SEND_PACKET -} - void GameMessages::HandleAddDonationItem(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr) { uint32_t count = 1; bool hasCount = false; @@ -3937,18 +3289,6 @@ void GameMessages::HandleCancelDonationOnPlayer(RakNet::BitStream& inStream, Ent characterComponent->SetCurrentInteracting(LWOOBJID_EMPTY); } -void GameMessages::SendSlashCommandFeedbackText(Entity* entity, std::u16string text) { - CBITSTREAM; - CMSGHEADER; - - bitStream.Write(entity->GetObjectID()); - bitStream.Write(MessageType::Game::SLASH_COMMAND_TEXT_FEEDBACK); - bitStream.Write(text.size()); - bitStream.Write(text); - auto sysAddr = entity->GetSystemAddress(); - SEND_PACKET; -} - void GameMessages::HandleUpdateInventoryGroup(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr) { std::string action; std::u16string groupName; diff --git a/dGame/dGameMessages/GameMessages.h b/dGame/dGameMessages/GameMessages.h index 22d52fb95..798909a29 100644 --- a/dGame/dGameMessages/GameMessages.h +++ b/dGame/dGameMessages/GameMessages.h @@ -127,7 +127,6 @@ namespace GameMessages { void SendFireEventClientSide(const LWOOBJID& objectID, const SystemAddress& sysAddr, std::u16string args, const LWOOBJID& object, int64_t param1, int param2, const LWOOBJID& sender); void SendTeleport(const LWOOBJID& objectID, const NiPoint3& pos, const NiQuaternion& rot, const SystemAddress& sysAddr, bool bSetRotation = false); - void SendPlayAnimation(Entity* entity, const std::u16string& animationName, float fPriority = 0.0f, float fScale = 1.0f); void SendPlayerReady(Entity* entity, const SystemAddress& sysAddr); void SendPlayerAllowedRespawn(LWOOBJID entityID, bool doNotPromptRespawn, const SystemAddress& systemAddress); void SendInvalidZoneTransferList(Entity* entity, const SystemAddress& sysAddr, const std::u16string& feedbackURL, const std::u16string& invalidMapTransferList, bool feedbackOnExit, bool feedbackOnInvalidTransfer); @@ -135,8 +134,6 @@ namespace GameMessages { void SendPlayerSetCameraCyclingMode(const LWOOBJID& objectID, const SystemAddress& sysAddr, bool bAllowCyclingWhileDeadOnly = true, eCyclingMode cyclingMode = eCyclingMode::ALLOW_CYCLE_TEAMMATES); - void SendPlayNDAudioEmitter(Entity* entity, const SystemAddress& sysAddr, std::string audioGUID); - void SendStartPathing(Entity* entity); // special is for the FV tree platform, feature is complete if we just do that so meh @@ -153,17 +150,7 @@ namespace GameMessages { void SendChangeObjectWorldState(const LWOOBJID& objectID, eObjectWorldState state, const SystemAddress& sysAddr); void SendModifyLEGOScore(Entity* entity, const SystemAddress& sysAddr, int64_t score, eLootSourceType sourceType); - void SendUIMessageServerToSingleClient(Entity* entity, const SystemAddress& sysAddr, const std::string& message, AMFBaseValue& args); - // Specify sysAddr if you need to send a flash message to a client who you dont know the objectID of. - void SendUIMessageServerToSingleClient(const std::string& message, AMFBaseValue& args, const SystemAddress& sysAddr); - void SendUIMessageServerToAllClients(const std::string& message, AMFBaseValue& args); - - void SendPlayEmbeddedEffectOnAllClientsNearObject(Entity* entity, std::u16string effectName, const LWOOBJID& fromObjectID, float radius); - void SendPlayFXEffect(Entity* entity, int32_t effectID, const std::u16string& effectType, const std::string& name, LWOOBJID secondary, float priority = 1, float scale = 1, bool serialize = true); - void SendPlayFXEffect(const LWOOBJID& entity, int32_t effectID, const std::u16string& effectType, const std::string& name, LWOOBJID secondary = LWOOBJID_EMPTY, float priority = 1, float scale = 1, bool serialize = true); - void SendStopFXEffect(Entity* entity, bool killImmediate, std::string name); - void SendBroadcastTextToChatbox(Entity* entity, const SystemAddress& sysAddr, const std::u16string& attrs, const std::u16string& wsText); void SendSetCurrency(Entity* entity, int64_t currency, int lootType, const LWOOBJID& sourceID, const LOT& sourceLOT, int sourceTradeID, bool overrideCurrent, eLootSourceType sourceType); void SendQuickBuildNotifyState(Entity* entity, eQuickBuildState prevState, eQuickBuildState state, const LWOOBJID& playerID); @@ -178,11 +165,8 @@ namespace GameMessages { void SendSetGravityScale(const LWOOBJID& target, const float effectScale, const SystemAddress& sysAddr); - void SendSetEmoteLockState(Entity* entity, bool bLock, int emoteID); void SendSetJetPackMode(Entity* entity, bool use, bool bypassChecks = false, bool doHover = false, int effectID = -1, float airspeed = 10, float maxAirspeed = 15, float verticalVelocity = 1, int warningEffectID = -1); void SendResurrect(Entity* entity); - void SendStop2DAmbientSound(Entity* entity, bool force, std::string audioGUID, bool result = false); - void SendPlay2DAmbientSound(Entity* entity, std::string audioGUID, bool result = false); void SendSetNetworkScriptVar(Entity* entity, const SystemAddress& sysAddr, std::string data); void SendSetPlayerControlScheme(Entity* entity, eControlScheme controlScheme); @@ -203,8 +187,6 @@ namespace GameMessages { void SendMatchResponse(Entity* entity, const SystemAddress& sysAddr, int response); void SendMatchUpdate(Entity* entity, const SystemAddress& sysAddr, std::string data, eMatchUpdate type); - void SendStartCelebrationEffect(Entity* entity, const SystemAddress& sysAddr, int celebrationID); - // https://lcdruniverse.org/lu_packets/lu_packets/world/gm/client/struct.SetResurrectRestoreValues.html void SendSetResurrectRestoreValues(Entity* targetEntity, int32_t armorRestore, int32_t healthRestore, int32_t imaginationRestore); @@ -260,15 +242,6 @@ namespace GameMessages { void HandleSetConsumableItem(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr); - void SendPlayCinematic(LWOOBJID objectId, std::u16string pathName, const SystemAddress& sysAddr, - bool allowGhostUpdates = true, bool bCloseMultiInteract = true, bool bSendServerNotify = false, bool bUseControlledObjectForAudioListener = false, - eEndBehavior endBehavior = eEndBehavior::RETURN, bool hidePlayerDuringCine = false, float leadIn = -1, bool leavePlayerLockedWhenFinished = false, - bool lockPlayer = true, bool result = false, bool skipIfSamePath = false, float startTimeAdvance = 0); - - void SendEndCinematic(LWOOBJID objectID, std::u16string pathName, const SystemAddress& sysAddr = UNASSIGNED_SYSTEM_ADDRESS, - float leadOut = -1.0f, bool leavePlayerLocked = false); - void HandleCinematicUpdate(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr); - void SendSetStunned(LWOOBJID objectId, eStateChangeType stateChangeType, const SystemAddress& sysAddr, LWOOBJID originator = LWOOBJID_EMPTY, bool bCantAttack = false, bool bCantEquip = false, bool bCantInteract = false, bool bCantJump = false, bool bCantMove = false, bool bCantTurn = false, @@ -343,30 +316,11 @@ namespace GameMessages { //Pets: void SendMarkInventoryItemAsActive(LWOOBJID objectId, bool bActive, eUnequippableActiveType iType, LWOOBJID itemID, const SystemAddress& sysAddr); - void SendPlayEmote(LWOOBJID objectId, int32_t emoteID, LWOOBJID target, const SystemAddress& sysAddr); - - void HandleMessageBoxResponse(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr); - - void HandleChoiceBoxRespond(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr); - void SendDisplayZoneSummary(LWOOBJID objectId, const SystemAddress& sysAddr, bool isPropertyMap = false, bool isZoneStart = false, LWOOBJID sender = LWOOBJID_EMPTY); //UI: void SendNotifyNotEnoughInvSpace(LWOOBJID objectId, uint32_t freeSlotsNeeded, eInventoryType inventoryType, const SystemAddress& sysAddr); - void SendDisplayMessageBox(LWOOBJID objectId, bool bShow, LWOOBJID callbackClient, const std::u16string& identifier, int32_t imageID, const std::u16string& text, const std::u16string& userData, const SystemAddress& sysAddr); - - void SendDisplayChatBubble(LWOOBJID objectId, const std::u16string& text, const SystemAddress& sysAddr); - - /** - * @brief - * - * @param objectId ID of the entity to set idle flags - * @param FlagsOn Flag to turn on - * @param FlagsOff Flag to turn off - */ - void SendChangeIdleFlags(LWOOBJID objectId, eAnimationFlags FlagsOn, eAnimationFlags FlagsOff, const SystemAddress& sysAddr); - // Mounts /** * @brief Set the Inventory LWOOBJID of the mount @@ -445,8 +399,6 @@ namespace GameMessages { void HandleToggleGhostReferenceOverride(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr); void HandleSetGhostReferencePosition(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr); - void SendSetNamebillboardState(const SystemAddress& sysAddr, LWOOBJID objectId); - void SendShowBillboardInteractIcon(const SystemAddress& sysAddr, LWOOBJID objectId); void HandleBuyFromVendor(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr); void HandleSellToVendor(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr); void HandleBuybackFromVendor(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr); @@ -456,7 +408,6 @@ namespace GameMessages { void HandleFireEventServerSide(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr); void HandleRequestPlatformResync(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr); void HandleQuickBuildCancel(RakNet::BitStream& inStream, Entity* entity); - void HandlePlayEmote(RakNet::BitStream& inStream, Entity* entity); void HandleNotifyServerLevelProcessingComplete(RakNet::BitStream& inStream, Entity* entity); void HandlePickupCurrency(RakNet::BitStream& inStream, Entity* entity); void HandleRequestDie(RakNet::BitStream& inStream, Entity* entity); @@ -501,8 +452,6 @@ namespace GameMessages { void HandleConfirmDonationOnPlayer(RakNet::BitStream& inStream, Entity* entity); void HandleCancelDonationOnPlayer(RakNet::BitStream& inStream, Entity* entity); - void SendSlashCommandFeedbackText(Entity* entity, std::u16string text); - void HandleUpdateInventoryGroup(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr); void HandleUpdateInventoryGroupContents(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr); void SendForceCameraTargetCycle(Entity* entity, bool bForceCycling, eCameraTargetCyclingMode cyclingMode, LWOOBJID optionalTargetID); diff --git a/dGame/dGameMessages/MissionMessages.cpp b/dGame/dGameMessages/MissionMessages.cpp index 410c2d2f5..f4cf041b0 100644 --- a/dGame/dGameMessages/MissionMessages.cpp +++ b/dGame/dGameMessages/MissionMessages.cpp @@ -15,6 +15,7 @@ #include "Mission.h" #include "MissionComponent.h" #include "MissionOfferComponent.h" +#include "EffectsMessages.h" namespace GameMessages { void OfferMission::Serialize(RakNet::BitStream& bitStream) const { @@ -150,7 +151,9 @@ namespace GameMessages { || !player->GetCharacter()->GetPlayerFlag(ePlayerFlag::DLU_SKIP_CINEMATICS)) return; player->AddCallbackTimer(0.5f, [player]() { if (!player) return; - GameMessages::SendEndCinematic(player->GetObjectID(), u"", player->GetSystemAddress()); + GameMessages::EndCinematic endCinematic; + endCinematic.target = player->GetObjectID(); + endCinematic.Send(player->GetSystemAddress()); }); } diff --git a/dGame/dPropertyBehaviors/ControlBehaviors.cpp b/dGame/dPropertyBehaviors/ControlBehaviors.cpp index 0b180979d..d7c00b934 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviors.cpp +++ b/dGame/dPropertyBehaviors/ControlBehaviors.cpp @@ -4,6 +4,7 @@ #include "Entity.h" #include "Game.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "ModelComponent.h" #include "ObjectIDManager.h" #include "Logger.h" @@ -46,7 +47,11 @@ void ControlBehaviors::RequestUpdatedID(ControlBehaviorContext& context) { args.Insert("behaviorID", std::to_string(persistentIdBig)); args.Insert("objectID", std::to_string(context.modelComponent->GetParent()->GetObjectID())); - GameMessages::SendUIMessageServerToSingleClient(context.modelOwner, context.modelOwner->GetSystemAddress(), "UpdateBehaviorID", args); + GameMessages::UIMessageServerToSingleClient uiMessage; + uiMessage.target = context.modelOwner->GetObjectID(); + uiMessage.strMessageName = "UpdateBehaviorID"; + uiMessage.args = std::move(args); + uiMessage.SendToClient(context.modelOwner->GetSystemAddress()); context.modelComponent->UpdatePendingBehaviorId(persistentIdBig, oldBehaviorID); ControlBehaviors::Instance().SendBehaviorListToClient(context); @@ -58,7 +63,11 @@ void ControlBehaviors::SendBehaviorListToClient(const ControlBehaviorContext& co AMFArrayValue behaviorsToSerialize; context.modelComponent->SendBehaviorListToClient(behaviorsToSerialize); - GameMessages::SendUIMessageServerToSingleClient(context.modelOwner, context.modelOwner->GetSystemAddress(), "UpdateBehaviorList", behaviorsToSerialize); + GameMessages::UIMessageServerToSingleClient uiMessage; + uiMessage.target = context.modelOwner->GetObjectID(); + uiMessage.strMessageName = "UpdateBehaviorList"; + uiMessage.args = std::move(behaviorsToSerialize); + uiMessage.SendToClient(context.modelOwner->GetSystemAddress()); } // TODO This is also supposed to serialize the state of the behaviors in progress but those aren't implemented yet @@ -69,7 +78,11 @@ void ControlBehaviors::SendBehaviorBlocksToClient(ControlBehaviorContext& contex context.modelComponent->VerifyBehaviors(); AMFArrayValue behavior; context.modelComponent->SendBehaviorBlocksToClient(behaviorMsg.GetBehaviorId(), behavior); - GameMessages::SendUIMessageServerToSingleClient(context.modelOwner, context.modelOwner->GetSystemAddress(), "UpdateBehaviorBlocks", behavior); + GameMessages::UIMessageServerToSingleClient uiMessage; + uiMessage.target = context.modelOwner->GetObjectID(); + uiMessage.strMessageName = "UpdateBehaviorBlocks"; + uiMessage.args = std::move(behavior); + uiMessage.SendToClient(context.modelOwner->GetSystemAddress()); } void ControlBehaviors::UpdateAction(const AMFArrayValue& arguments) { @@ -156,7 +169,11 @@ void ControlBehaviors::ProcessCommand(Entity* const modelEntity, const AMFArrayV if (!isRemove) { AMFArrayValue args; args.Insert("BehaviorID", std::to_string(msg.GetBehaviorId())); - GameMessages::SendUIMessageServerToSingleClient(modelOwner, characterComponent->GetSystemAddress(), "BehaviorRemoved", args); + GameMessages::UIMessageServerToSingleClient uiMessage; + uiMessage.target = modelOwner->GetObjectID(); + uiMessage.strMessageName = "BehaviorRemoved"; + uiMessage.args = std::move(args); + uiMessage.SendToClient(characterComponent->GetSystemAddress()); } SendBehaviorListToClient(context); diff --git a/dGame/dUtilities/DashboardActions.cpp b/dGame/dUtilities/DashboardActions.cpp index 3dbb05969..8e66532a1 100644 --- a/dGame/dUtilities/DashboardActions.cpp +++ b/dGame/dUtilities/DashboardActions.cpp @@ -11,6 +11,7 @@ #include "CharacterComponent.h" #include "ChatPackets.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "PlayerManager.h" #include "User.h" #include "UserManager.h" @@ -70,7 +71,7 @@ namespace { GameMessages::ToggleGMInvisEvent msg; msg.Send(entity->GetObjectID()); } - GameMessages::SendSlashCommandFeedbackText(entity, u"Your game master level has been changed."); + GameMessages::SlashCommandTextFeedback(entity->GetObjectID(), u"Your game master level has been changed.").SendToClient(entity->GetSystemAddress()); LOG("Dashboard lowered GM level of %s to %i", user->GetUsername().c_str(), static_cast(info->maxGmLevel)); } return static_cast(users.size()); @@ -96,7 +97,11 @@ namespace { AMFArrayValue args; args.Insert("title", std::string("Warning from a moderator")); args.Insert("message", text); - GameMessages::SendUIMessageServerToSingleClient(player, player->GetSystemAddress(), "ToggleAnnounce", args); + GameMessages::UIMessageServerToSingleClient uiMessage; + uiMessage.target = player->GetObjectID(); + uiMessage.strMessageName = "ToggleAnnounce"; + uiMessage.args = std::move(args); + uiMessage.SendToClient(player->GetSystemAddress()); ChatPackets::SendSystemMessage(player->GetSystemAddress(), u"Warning from a moderator: " + GeneralUtils::UTF8ToUTF16(text)); affected++; } diff --git a/dGame/dUtilities/DashboardNotify.cpp b/dGame/dUtilities/DashboardNotify.cpp index 408e17f68..19475c295 100644 --- a/dGame/dUtilities/DashboardNotify.cpp +++ b/dGame/dUtilities/DashboardNotify.cpp @@ -16,6 +16,7 @@ #include "Character.h" #include "dZoneManager.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "ChatPackets.h" #include "Amf3.h" #include "GeneralUtils.h" @@ -87,7 +88,10 @@ namespace DashboardNotify { AMFArrayValue args; args.Insert("title", title); args.Insert("message", message); - GameMessages::SendUIMessageServerToAllClients("ToggleAnnounce", args); + GameMessages::UIMessageServerToAllClients uiMessage; + uiMessage.strMessageName = "ToggleAnnounce"; + uiMessage.args = std::move(args); + uiMessage.Send(UNASSIGNED_SYSTEM_ADDRESS); // Also in chat, for anyone who closes the popup without reading it const auto text = GeneralUtils::UTF8ToUTF16(ChatLine(title, message)); for (const auto* player : PlayerManager::GetAllPlayers()) { diff --git a/dGame/dUtilities/LiveEvents.cpp b/dGame/dUtilities/LiveEvents.cpp index 0a75d6b3d..0f9b047bd 100644 --- a/dGame/dUtilities/LiveEvents.cpp +++ b/dGame/dUtilities/LiveEvents.cpp @@ -27,6 +27,7 @@ #include "InventoryComponent.h" #include "DestroyableComponent.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "ChatPackets.h" #include "DashboardNotify.h" #include "CDClientManager.h" @@ -218,7 +219,7 @@ namespace { const auto itemCount = std::clamp(event.config.value("itemCount", 1u), 1, 999); if (auto* inventory = player->GetComponent(); inventory && item > 0) inventory->AddItem(item, itemCount, eLootSourceType::ACTIVITY); if (const auto effect = event.config.value("foundEffectId", 0); effect > 0) { - GameMessages::SendPlayFXEffect(player->GetObjectID(), effect, GeneralUtils::UTF8ToUTF16(event.config.value("foundEffectType", std::string{})), "live_event_found"); + GameMessages::PlayFXEffect(player->GetObjectID(), effect, GeneralUtils::UTF8ToUTF16(event.config.value("foundEffectType", std::string{})), "live_event_found").Send(UNASSIGNED_SYSTEM_ADDRESS); } const auto left = std::ranges::count_if(event.treasures, [](const Treasure& t) { return !t.gone; }); TellAll(PlayerName(player) + " found a treasure! " + (left == 0 ? "That was the last one." : std::to_string(left) + " left to find.")); @@ -353,7 +354,7 @@ namespace { if (effect <= 0) return; const auto name = "live_event_" + std::to_string(event.row.id); for (auto* player : PlayerManager::GetAllPlayers()) { - if (player) GameMessages::SendPlayFXEffect(player->GetObjectID(), effect, type, name); + if (player) GameMessages::PlayFXEffect(player->GetObjectID(), effect, type, name).Send(UNASSIGNED_SYSTEM_ADDRESS); } event.bursts++; event.dirty = true; @@ -458,7 +459,7 @@ namespace { event.alive.clear(); if (event.type == eEventType::CELEBRATION) { const auto name = "live_event_" + std::to_string(event.row.id); - for (auto* player : PlayerManager::GetAllPlayers()) if (player) GameMessages::SendStopFXEffect(player, true, name); + for (auto* player : PlayerManager::GetAllPlayers()) if (player) GameMessages::StopFXEffect(player->GetObjectID(), true, name).Send(UNASSIGNED_SYSTEM_ADDRESS); } FlushScores(event); WriteStatus(event, true); diff --git a/dGame/dUtilities/SlashCommandHandler.cpp b/dGame/dUtilities/SlashCommandHandler.cpp index 14b13761f..58859a592 100644 --- a/dGame/dUtilities/SlashCommandHandler.cpp +++ b/dGame/dUtilities/SlashCommandHandler.cpp @@ -31,6 +31,7 @@ #include "PlayerManager.h" #include "User.h" #include "eObjectBits.h" +#include "EffectsMessages.h" namespace { // Each command once, by the first alias it got @@ -259,7 +260,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& chat, Entity* } if (!error.empty()) { - GameMessages::SendSlashCommandFeedbackText(entity, GeneralUtils::ASCIIToUTF16(error)); + GameMessages::SlashCommandTextFeedback(entity->GetObjectID(), GeneralUtils::ASCIIToUTF16(error)).SendToClient(entity->GetSystemAddress()); } } @@ -290,7 +291,7 @@ void GMZeroCommands::Help(Entity* entity, const SystemAddress& sysAddr, const st if (page < 1 || page > totalPages) { feedback << "Invalid page number. Total pages: " << totalPages; - GameMessages::SendSlashCommandFeedbackText(entity, GeneralUtils::ASCIIToUTF16(feedback.str())); + GameMessages::SlashCommandTextFeedback(entity->GetObjectID(), GeneralUtils::ASCIIToUTF16(feedback.str())).SendToClient(entity->GetSystemAddress()); return; } @@ -305,7 +306,7 @@ void GMZeroCommands::Help(Entity* entity, const SystemAddress& sysAddr, const st const auto feedbackStr = feedback.str(); if (!feedbackStr.empty()) { - GameMessages::SendSlashCommandFeedbackText(entity, GeneralUtils::ASCIIToUTF16(feedbackStr)); + GameMessages::SlashCommandTextFeedback(entity->GetObjectID(), GeneralUtils::ASCIIToUTF16(feedbackStr)).SendToClient(entity->GetSystemAddress()); } return; } @@ -328,7 +329,7 @@ void GMZeroCommands::Help(Entity* entity, const SystemAddress& sysAddr, const st const auto feedbackStr = feedback.str(); if (!feedbackStr.empty()) { - GameMessages::SendSlashCommandFeedbackText(entity, GeneralUtils::ASCIIToUTF16(feedbackStr)); + GameMessages::SlashCommandTextFeedback(entity->GetObjectID(), GeneralUtils::ASCIIToUTF16(feedbackStr)).SendToClient(entity->GetSystemAddress()); } } @@ -338,7 +339,10 @@ void SlashCommandHandler::SendAnnouncement(const std::string& title, const std:: args.Insert("title", title); args.Insert("message", message); - GameMessages::SendUIMessageServerToAllClients("ToggleAnnounce", args); + GameMessages::UIMessageServerToAllClients uiMessage; + uiMessage.strMessageName = "ToggleAnnounce"; + uiMessage.args = std::move(args); + uiMessage.Send(UNASSIGNED_SYSTEM_ADDRESS); //Notify chat about it ChatPackets::Announcement announcement; diff --git a/dGame/dUtilities/SlashCommands/DEVGMCommands.cpp b/dGame/dUtilities/SlashCommands/DEVGMCommands.cpp index 8d325953b..5a1b67049 100644 --- a/dGame/dUtilities/SlashCommands/DEVGMCommands.cpp +++ b/dGame/dUtilities/SlashCommands/DEVGMCommands.cpp @@ -57,6 +57,7 @@ #include "ePlayerFlag.h" #include "StringifiedEnum.h" #include "BinaryPathFinder.h" +#include "EffectsMessages.h" namespace DEVGMCommands { void SetGMLevel(Entity* entity, const SystemAddress& sysAddr, const std::string args) { @@ -64,7 +65,7 @@ namespace DEVGMCommands { const auto level_intermed = GeneralUtils::TryParse(args); if (!level_intermed) { - GameMessages::SendSlashCommandFeedbackText(entity, u"Invalid GM level."); + GameMessages::SlashCommandTextFeedback(entity->GetObjectID(), u"Invalid GM level.").SendToClient(entity->GetSystemAddress()); return; } eGameMasterLevel level = static_cast(level_intermed.value()); @@ -106,7 +107,7 @@ namespace DEVGMCommands { GameMessages::ToggleGMInvisEvent msg; msg.Send(entity->GetObjectID()); - GameMessages::SendSlashCommandFeedbackText(entity, u"Your game master level has been changed, you may not be able to use all commands."); + GameMessages::SlashCommandTextFeedback(entity->GetObjectID(), u"Your game master level has been changed, you may not be able to use all commands.").SendToClient(entity->GetSystemAddress()); } #endif } @@ -118,10 +119,10 @@ namespace DEVGMCommands { auto* character = entity->GetCharacter(); if (character && character->GetBillboardVisible()) { character->SetBillboardVisible(false); - GameMessages::SendSlashCommandFeedbackText(entity, u"Your nameplate has been turned off and is not visible to players currently in this zone."); + GameMessages::SlashCommandTextFeedback(entity->GetObjectID(), u"Your nameplate has been turned off and is not visible to players currently in this zone.").SendToClient(entity->GetSystemAddress()); } else { character->SetBillboardVisible(true); - GameMessages::SendSlashCommandFeedbackText(entity, u"Your nameplate is now on and visible to all players."); + GameMessages::SlashCommandTextFeedback(entity->GetObjectID(), u"Your nameplate is now on and visible to all players.").SendToClient(entity->GetSystemAddress()); } } @@ -132,9 +133,9 @@ namespace DEVGMCommands { bool current = character->GetPlayerFlag(ePlayerFlag::DLU_SKIP_CINEMATICS); character->SetPlayerFlag(ePlayerFlag::DLU_SKIP_CINEMATICS, !current); if (!current) { - GameMessages::SendSlashCommandFeedbackText(entity, u"You have elected to skip cinematics. Note that not all cinematics can be skipped, but most will be skipped now."); + GameMessages::SlashCommandTextFeedback(entity->GetObjectID(), u"You have elected to skip cinematics. Note that not all cinematics can be skipped, but most will be skipped now.").SendToClient(entity->GetSystemAddress()); } else { - GameMessages::SendSlashCommandFeedbackText(entity, u"Cinematics will no longer be skipped."); + GameMessages::SlashCommandTextFeedback(entity->GetObjectID(), u"Cinematics will no longer be skipped.").SendToClient(entity->GetSystemAddress()); } } @@ -327,7 +328,11 @@ namespace DEVGMCommands { uiState.Insert("state", splitArgs[0]); - GameMessages::SendUIMessageServerToSingleClient(entity, sysAddr, "pushGameState", uiState); + GameMessages::UIMessageServerToSingleClient uiMessage; + uiMessage.target = entity->GetObjectID(); + uiMessage.strMessageName = "pushGameState"; + uiMessage.args = std::move(uiState); + uiMessage.SendToClient(sysAddr); ChatPackets::SendSystemMessage(sysAddr, u"Switched UI state."); } @@ -340,7 +345,11 @@ namespace DEVGMCommands { amfArgs.Insert("visible", true); - GameMessages::SendUIMessageServerToSingleClient(entity, sysAddr, splitArgs[0], amfArgs); + GameMessages::UIMessageServerToSingleClient uiMessage; + uiMessage.target = entity->GetObjectID(); + uiMessage.strMessageName = splitArgs[0]; + uiMessage.args = std::move(amfArgs); + uiMessage.SendToClient(sysAddr); ChatPackets::SendSystemMessage(sysAddr, u"Toggled UI state."); } @@ -499,14 +508,14 @@ namespace DEVGMCommands { if (!effectID) return; // FIXME: use fallible ASCIIToUTF16 conversion, because non-ascii isn't valid anyway - GameMessages::SendPlayFXEffect(entity->GetObjectID(), effectID.value(), GeneralUtils::ASCIIToUTF16(splitArgs.at(1)), splitArgs.at(2)); + GameMessages::PlayFXEffect(entity->GetObjectID(), effectID.value(), GeneralUtils::ASCIIToUTF16(splitArgs.at(1)), splitArgs.at(2)).Send(UNASSIGNED_SYSTEM_ADDRESS); } void StopEffect(Entity* entity, const SystemAddress& sysAddr, const std::string args) { const auto splitArgs = GeneralUtils::SplitString(args, ' '); if (splitArgs.empty()) return; - GameMessages::SendStopFXEffect(entity, true, splitArgs[0]); + GameMessages::StopFXEffect(entity->GetObjectID(), true, splitArgs[0]).Send(UNASSIGNED_SYSTEM_ADDRESS); } void SetAnnTitle(Entity* entity, const SystemAddress& sysAddr, const std::string args) { @@ -739,7 +748,10 @@ namespace DEVGMCommands { return; } - GameMessages::SendStartCelebrationEffect(entity, entity->GetSystemAddress(), celebration.value()); + GameMessages::StartCelebrationEffect celebrationEffect; + celebrationEffect.target = entity->GetObjectID(); + celebrationEffect.celebrationID = celebration.value(); + celebrationEffect.SendToClient(entity->GetSystemAddress()); } void BuffMed(Entity* entity, const SystemAddress& sysAddr, const std::string args) { @@ -807,7 +819,10 @@ namespace DEVGMCommands { for (const auto& [name, lot] : nameToLot) { auto& entry = nameSort.PushDebug(name) = std::to_string(lot); } - GameMessages::SendUIMessageServerToSingleClient("ToggleObjectDebugger", response, sysAddr); + GameMessages::UIMessageServerToAllClients uiMessage; + uiMessage.strMessageName = "ToggleObjectDebugger"; + uiMessage.args = std::move(response); + uiMessage.SendToClient(sysAddr); } } @@ -1021,11 +1036,11 @@ namespace DEVGMCommands { } void PlayLvlFx(Entity* entity, const SystemAddress& sysAddr, const std::string args) { - GameMessages::SendPlayFXEffect(entity, 7074, u"create", "7074", LWOOBJID_EMPTY, 1.0f, 1.0f, true); + GameMessages::PlayFXEffect(entity->GetObjectID(), 7074, u"create", "7074").Send(UNASSIGNED_SYSTEM_ADDRESS); } void PlayRebuildFx(Entity* entity, const SystemAddress& sysAddr, const std::string args) { - GameMessages::SendPlayFXEffect(entity, 230, u"rebuild", "230", LWOOBJID_EMPTY, 1.0f, 1.0f, true); + GameMessages::PlayFXEffect(entity->GetObjectID(), 230, u"rebuild", "230").Send(UNASSIGNED_SYSTEM_ADDRESS); } void FreeMoney(Entity* entity, const SystemAddress& sysAddr, const std::string args) { @@ -1354,7 +1369,10 @@ namespace DEVGMCommands { processInfo.PushDebug("Peak RSS") = std::to_string(static_cast(Metrics::GetPeakRSS()) / 1.024e6) + "MB"; processInfo.PushDebug("Current RSS") = std::to_string(static_cast(Metrics::GetCurrentRSS()) / 1.024e6) + "MB"; processInfo.PushDebug("Process ID") = Metrics::GetProcessID(); - GameMessages::SendUIMessageServerToSingleClient("ToggleObjectDebugger", response, sysAddr); + GameMessages::UIMessageServerToAllClients uiMessage; + uiMessage.strMessageName = "ToggleObjectDebugger"; + uiMessage.args = std::move(response); + uiMessage.SendToClient(sysAddr); } void ReloadConfig(Entity* entity, const SystemAddress& sysAddr, const std::string args) { diff --git a/dGame/dUtilities/SlashCommands/GMGreaterThanZeroCommands.cpp b/dGame/dUtilities/SlashCommands/GMGreaterThanZeroCommands.cpp index 9754ade79..e2d47184c 100644 --- a/dGame/dUtilities/SlashCommands/GMGreaterThanZeroCommands.cpp +++ b/dGame/dUtilities/SlashCommands/GMGreaterThanZeroCommands.cpp @@ -21,6 +21,7 @@ #include "MessageType/Chat.h" #include "eServerDisconnectIdentifiers.h" #include "eObjectBits.h" +#include "EffectsMessages.h" namespace GMGreaterThanZeroCommands { @@ -288,7 +289,7 @@ namespace GMGreaterThanZeroCommands { void FindPlayer(Entity* entity, const SystemAddress& sysAddr, const std::string args) { if (args.empty()) { - GameMessages::SendSlashCommandFeedbackText(entity, u"No player Given"); + GameMessages::SlashCommandTextFeedback(entity->GetObjectID(), u"No player Given").SendToClient(entity->GetSystemAddress()); return; } @@ -306,10 +307,10 @@ namespace GMGreaterThanZeroCommands { auto player = PlayerManager::GetPlayer(args); if (!player) { - GameMessages::SendSlashCommandFeedbackText(entity, u"Player not found"); + GameMessages::SlashCommandTextFeedback(entity->GetObjectID(), u"Player not found").SendToClient(entity->GetSystemAddress()); return; } - GameMessages::SendSlashCommandFeedbackText(entity, u"Spectating Player"); + GameMessages::SlashCommandTextFeedback(entity->GetObjectID(), u"Spectating Player").SendToClient(entity->GetSystemAddress()); GameMessages::SendForceCameraTargetCycle(entity, false, eCameraTargetCyclingMode::DISALLOW_CYCLING, player->GetObjectID()); } } diff --git a/dGame/dUtilities/SlashCommands/GMZeroCommands.cpp b/dGame/dUtilities/SlashCommands/GMZeroCommands.cpp index bb5291d3f..92b189960 100644 --- a/dGame/dUtilities/SlashCommands/GMZeroCommands.cpp +++ b/dGame/dUtilities/SlashCommands/GMZeroCommands.cpp @@ -23,6 +23,7 @@ // Emuns #include "eGameMasterLevel.h" +#include "EffectsMessages.h" namespace GMZeroCommands { void Pvp(Entity* entity, const SystemAddress& sysAddr, const std::string args) { @@ -101,7 +102,11 @@ namespace GMZeroCommands { args.Insert("state", "Story"); - GameMessages::SendUIMessageServerToSingleClient(entity, entity->GetSystemAddress(), "pushGameState", args); + GameMessages::UIMessageServerToSingleClient uiMessage; + uiMessage.target = entity->GetObjectID(); + uiMessage.strMessageName = "pushGameState"; + uiMessage.args = std::move(args); + uiMessage.SendToClient(entity->GetSystemAddress()); } entity->AddCallbackTimer(0.5f, [customText, entity]() { @@ -112,7 +117,11 @@ namespace GMZeroCommands { LOG("Sending %s", customText.c_str()); - GameMessages::SendUIMessageServerToSingleClient(entity, entity->GetSystemAddress(), "ToggleStoryBox", args); + GameMessages::UIMessageServerToSingleClient uiMessage; + uiMessage.target = entity->GetObjectID(); + uiMessage.strMessageName = "ToggleStoryBox"; + uiMessage.args = std::move(args); + uiMessage.SendToClient(entity->GetSystemAddress()); }); } @@ -124,7 +133,11 @@ namespace GMZeroCommands { args.Insert("state", "Story"); - GameMessages::SendUIMessageServerToSingleClient(entity, entity->GetSystemAddress(), "pushGameState", args); + GameMessages::UIMessageServerToSingleClient uiMessage; + uiMessage.target = entity->GetObjectID(); + uiMessage.strMessageName = "pushGameState"; + uiMessage.args = std::move(args); + uiMessage.SendToClient(entity->GetSystemAddress()); } entity->AddCallbackTimer(0.5f, [customText, entity]() { @@ -135,7 +148,11 @@ namespace GMZeroCommands { LOG("Sending %s", customText.c_str()); - GameMessages::SendUIMessageServerToSingleClient(entity, entity->GetSystemAddress(), "ToggleStoryBox", args); + GameMessages::UIMessageServerToSingleClient uiMessage; + uiMessage.target = entity->GetObjectID(); + uiMessage.strMessageName = "ToggleStoryBox"; + uiMessage.args = std::move(args); + uiMessage.SendToClient(entity->GetSystemAddress()); }); } diff --git a/dScripts/02_server/DLU/DLUVanityTeleportingObject.cpp b/dScripts/02_server/DLU/DLUVanityTeleportingObject.cpp index 0908bbdca..f9f96bf65 100644 --- a/dScripts/02_server/DLU/DLUVanityTeleportingObject.cpp +++ b/dScripts/02_server/DLU/DLUVanityTeleportingObject.cpp @@ -1,5 +1,6 @@ #include "DLUVanityTeleportingObject.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "dServer.h" #include "VanityUtilities.h" #include "RenderComponent.h" @@ -17,14 +18,14 @@ void DLUVanityTeleportingObject::OnStartup(Entity* self) { void DLUVanityTeleportingObject::OnTimerDone(Entity* self, std::string timerName) { if (timerName == "setupTeleport") { RenderComponent::PlayAnimation(self, u"interact"); - GameMessages::SendPlayFXEffect(self->GetObjectID(), 6478, u"teleportBeam", "teleportBeam"); - GameMessages::SendPlayFXEffect(self->GetObjectID(), 6478, u"teleportRings", "teleportRings"); + GameMessages::PlayFXEffect(self->GetObjectID(), 6478, u"teleportBeam", "teleportBeam").Send(UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::PlayFXEffect(self->GetObjectID(), 6478, u"teleportRings", "teleportRings").Send(UNASSIGNED_SYSTEM_ADDRESS); self->AddTimer("teleport", 2.0f); self->AddTimer("stopFX", 2.0f); } else if (timerName == "stopFX") { - GameMessages::SendStopFXEffect(self, true, "teleportBeam"); - GameMessages::SendStopFXEffect(self, true, "teleportRings"); + GameMessages::StopFXEffect(self->GetObjectID(), true, "teleportBeam").Send(UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::StopFXEffect(self->GetObjectID(), true, "teleportRings").Send(UNASSIGNED_SYSTEM_ADDRESS); } else if (timerName == "teleport") { std::vector& locations = m_Object->m_Locations[Game::server->GetZoneID()]; @@ -37,8 +38,8 @@ void DLUVanityTeleportingObject::OnTimerDone(Entity* self, std::string timerName self->SetPosition(newLocation.m_Position); self->SetRotation(newLocation.m_Rotation); - GameMessages::SendPlayFXEffect(self->GetObjectID(), 6478, u"teleportBeam", "teleportBeam"); - GameMessages::SendPlayFXEffect(self->GetObjectID(), 6478, u"teleportRings", "teleportRings"); + GameMessages::PlayFXEffect(self->GetObjectID(), 6478, u"teleportBeam", "teleportBeam").Send(UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::PlayFXEffect(self->GetObjectID(), 6478, u"teleportRings", "teleportRings").Send(UNASSIGNED_SYSTEM_ADDRESS); self->AddTimer("stopFX", 2.0f); self->AddTimer("setupTeleport", m_TeleportInterval); } diff --git a/dScripts/02_server/Enemy/AG/BossSpiderQueenEnemyServer.cpp b/dScripts/02_server/Enemy/AG/BossSpiderQueenEnemyServer.cpp index 1e772d66e..188098e80 100644 --- a/dScripts/02_server/Enemy/AG/BossSpiderQueenEnemyServer.cpp +++ b/dScripts/02_server/Enemy/AG/BossSpiderQueenEnemyServer.cpp @@ -12,6 +12,7 @@ #include "BaseCombatAIComponent.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "SkillComponent.h" #include "eReplicaComponentType.h" #include "RenderComponent.h" @@ -527,7 +528,12 @@ void BossSpiderQueenEnemyServer::OnTimerDone(Entity* self, const std::string tim } } - GameMessages::SendPlayEmbeddedEffectOnAllClientsNearObject(self, u"camshake-bridge", self->GetObjectID(), 100.0f); + GameMessages::PlayEmbeddedEffectOnAllClientsNearObject embeddedEffect; + embeddedEffect.target = self->GetObjectID(); + embeddedEffect.effectName = u"camshake-bridge"; + embeddedEffect.fromObjectID = self->GetObjectID(); + embeddedEffect.radius = 100.0f; + embeddedEffect.Send(UNASSIGNED_SYSTEM_ADDRESS); } else if (timerName == "AdvanceComplete") { GameMessages::SendNotifyClientObject(self->GetObjectID(), u"SetColGroup", 11, 0, 0, "", UNASSIGNED_SYSTEM_ADDRESS); diff --git a/dScripts/02_server/Enemy/AM/AmDarklingDragon.cpp b/dScripts/02_server/Enemy/AM/AmDarklingDragon.cpp index 5fbbda20b..eb384ec27 100644 --- a/dScripts/02_server/Enemy/AM/AmDarklingDragon.cpp +++ b/dScripts/02_server/Enemy/AM/AmDarklingDragon.cpp @@ -3,6 +3,7 @@ #include "DestroyableComponent.h" #include "EntityManager.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "SkillComponent.h" #include "BaseCombatAIComponent.h" #include "EntityInfo.h" @@ -36,7 +37,7 @@ void AmDarklingDragon::OnDie(Entity* self, Entity* killer) { } void AmDarklingDragon::OnHitOrHealResult(Entity* self, Entity* attacker, int32_t damage) { - GameMessages::SendPlayFXEffect(self, -1, u"gothit", "", LWOOBJID_EMPTY, 1, 1, true); + GameMessages::PlayFXEffect(self->GetObjectID(), -1, u"gothit", "").Send(UNASSIGNED_SYSTEM_ADDRESS); if (true) { auto weakpoint = self->GetVar(u"weakspot"); @@ -70,7 +71,11 @@ 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::ChangeIdleFlags idleFlags; + idleFlags.target = self->GetObjectID(); + idleFlags.flagsOn = eAnimationFlags::IDLE_NONE; + idleFlags.flagsOff = eAnimationFlags::IDLE_COMBAT; + idleFlags.Send(UNASSIGNED_SYSTEM_ADDRESS); float animationTime = RenderComponent::PlayAnimation(self, u"stunstart", 1.7f); self->AddTimer("timeToStunLoop", 1.0f); @@ -134,7 +139,11 @@ void AmDarklingDragon::OnTimerDone(Entity* self, std::string timerName) { skillComponent->Interrupt(); skillComponent->Reset(); } - GameMessages::SendChangeIdleFlags(self->GetObjectID(), eAnimationFlags::IDLE_COMBAT, eAnimationFlags::IDLE_NONE, UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::ChangeIdleFlags idleFlags; + idleFlags.target = self->GetObjectID(); + idleFlags.flagsOn = eAnimationFlags::IDLE_COMBAT; + idleFlags.flagsOff = eAnimationFlags::IDLE_NONE; + idleFlags.Send(UNASSIGNED_SYSTEM_ADDRESS); self->SetVar(u"weakspot", -1); GameMessages::SendNotifyObject(self->GetObjectID(), self->GetObjectID(), u"DragonRevive", UNASSIGNED_SYSTEM_ADDRESS); } diff --git a/dScripts/02_server/Enemy/FV/FvMaelstromDragon.cpp b/dScripts/02_server/Enemy/FV/FvMaelstromDragon.cpp index 2ddc63099..88eb57a9c 100644 --- a/dScripts/02_server/Enemy/FV/FvMaelstromDragon.cpp +++ b/dScripts/02_server/Enemy/FV/FvMaelstromDragon.cpp @@ -6,6 +6,7 @@ #include "eAnimationFlags.h" #include "EntityInfo.h" #include "RenderComponent.h" +#include "EffectsMessages.h" void FvMaelstromDragon::OnStartup(Entity* self) { self->SetVar(u"weakspot", 0); @@ -49,7 +50,7 @@ void FvMaelstromDragon::OnDie(Entity* self, Entity* killer) { } void FvMaelstromDragon::OnHitOrHealResult(Entity* self, Entity* attacker, int32_t damage) { - GameMessages::SendPlayFXEffect(self, -1, u"gothit", "", LWOOBJID_EMPTY, 1, 1, true); + GameMessages::PlayFXEffect(self->GetObjectID(), -1, u"gothit", "").Send(UNASSIGNED_SYSTEM_ADDRESS); if (true) { auto weakpoint = self->GetVar(u"weakspot"); @@ -86,7 +87,11 @@ 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::ChangeIdleFlags idleFlags; + idleFlags.target = self->GetObjectID(); + idleFlags.flagsOn = eAnimationFlags::IDLE_NONE; + idleFlags.flagsOff = eAnimationFlags::IDLE_COMBAT; + idleFlags.Send(UNASSIGNED_SYSTEM_ADDRESS); RenderComponent::PlayAnimation(self, u"stunstart", 1.7f); self->AddTimer("timeToStunLoop", 1.0f); @@ -152,7 +157,11 @@ void FvMaelstromDragon::OnTimerDone(Entity* self, std::string timerName) { skillComponent->Interrupt(); skillComponent->Reset(); } - GameMessages::SendChangeIdleFlags(self->GetObjectID(), eAnimationFlags::IDLE_COMBAT, eAnimationFlags::IDLE_NONE, UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::ChangeIdleFlags idleFlags; + idleFlags.target = self->GetObjectID(); + idleFlags.flagsOn = eAnimationFlags::IDLE_COMBAT; + idleFlags.flagsOff = eAnimationFlags::IDLE_NONE; + idleFlags.Send(UNASSIGNED_SYSTEM_ADDRESS); self->SetVar(u"weakspot", -1); GameMessages::SendNotifyObject(self->GetObjectID(), self->GetObjectID(), u"DragonRevive", UNASSIGNED_SYSTEM_ADDRESS); diff --git a/dScripts/02_server/Enemy/General/BaseEnemyApe.cpp b/dScripts/02_server/Enemy/General/BaseEnemyApe.cpp index 26948c571..8c38cbceb 100644 --- a/dScripts/02_server/Enemy/General/BaseEnemyApe.cpp +++ b/dScripts/02_server/Enemy/General/BaseEnemyApe.cpp @@ -2,6 +2,7 @@ #include "BaseCombatAIComponent.h" #include "DestroyableComponent.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "EntityManager.h" #include "EntityInfo.h" #include "SkillComponent.h" @@ -40,7 +41,11 @@ void BaseEnemyApe::OnHit(Entity* self, Entity* attacker) { skillComponent->Reset(); } RenderComponent::PlayAnimation(self, u"disable", 1.7f); - GameMessages::SendChangeIdleFlags(self->GetObjectID(), eAnimationFlags::IDLE_NONE, eAnimationFlags::IDLE_COMBAT, UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::ChangeIdleFlags idleFlags; + idleFlags.target = self->GetObjectID(); + idleFlags.flagsOn = eAnimationFlags::IDLE_NONE; + idleFlags.flagsOff = eAnimationFlags::IDLE_COMBAT; + idleFlags.Send(UNASSIGNED_SYSTEM_ADDRESS); const auto reviveTime = self->GetVar(u"reviveTime") != 0.0f ? self->GetVar(u"reviveTime") : 12.0f; self->AddTimer("reviveTime", reviveTime); @@ -57,7 +62,11 @@ void BaseEnemyApe::OnTimerDone(Entity* self, std::string timerName) { destroyableComponent->SetArmor(destroyableComponent->GetMaxArmor() / timesStunned); } Game::entityManager->SerializeEntity(self); - GameMessages::SendChangeIdleFlags(self->GetObjectID(), eAnimationFlags::IDLE_COMBAT, eAnimationFlags::IDLE_NONE, UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::ChangeIdleFlags idleFlags; + idleFlags.target = self->GetObjectID(); + idleFlags.flagsOn = eAnimationFlags::IDLE_COMBAT; + idleFlags.flagsOff = eAnimationFlags::IDLE_NONE; + idleFlags.Send(UNASSIGNED_SYSTEM_ADDRESS); self->SetVar(u"timesStunned", timesStunned + 1); StunApe(self, false); diff --git a/dScripts/02_server/Map/AG/NpcEpsilonServer.cpp b/dScripts/02_server/Map/AG/NpcEpsilonServer.cpp index a928e9d96..2ccd6738f 100644 --- a/dScripts/02_server/Map/AG/NpcEpsilonServer.cpp +++ b/dScripts/02_server/Map/AG/NpcEpsilonServer.cpp @@ -1,10 +1,14 @@ #include "NpcEpsilonServer.h" #include "GameMessages.h" +#include "EffectsMessages.h" void NpcEpsilonServer::OnMissionDialogueOK(Entity* self, Entity* target, int missionID, eMissionState missionState) { //If we are completing the Nexus Force join mission, play the celebration for it: if (missionID == 1851) { - GameMessages::SendStartCelebrationEffect(target, target->GetSystemAddress(), 22); + GameMessages::StartCelebrationEffect celebration; + celebration.target = target->GetObjectID(); + celebration.celebrationID = 22; + celebration.SendToClient(target->GetSystemAddress()); } } diff --git a/dScripts/02_server/Map/AM/AmShieldGenerator.cpp b/dScripts/02_server/Map/AM/AmShieldGenerator.cpp index da0b65d72..55bc315e8 100644 --- a/dScripts/02_server/Map/AM/AmShieldGenerator.cpp +++ b/dScripts/02_server/Map/AM/AmShieldGenerator.cpp @@ -2,6 +2,7 @@ #include "EntityManager.h" #include "DestroyableComponent.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "EntityInfo.h" #include "MovementAIComponent.h" #include "BaseCombatAIComponent.h" @@ -62,7 +63,7 @@ void AmShieldGenerator::OnTimerDone(Entity* self, std::string timerName) { self->AddTimer("BuffPlayers", 3.0f); } else if (timerName == "PlayFX") { - GameMessages::SendPlayFXEffect(self->GetObjectID(), 5351, u"generatorOn", "generatorOn"); + GameMessages::PlayFXEffect(self->GetObjectID(), 5351, u"generatorOn", "generatorOn").Send(UNASSIGNED_SYSTEM_ADDRESS); self->AddTimer("PlayFX", 1.5f); } else if (timerName == "RefreshEnemies") { diff --git a/dScripts/02_server/Map/AM/AmShieldGeneratorQuickbuild.cpp b/dScripts/02_server/Map/AM/AmShieldGeneratorQuickbuild.cpp index 029322959..9fa606dca 100644 --- a/dScripts/02_server/Map/AM/AmShieldGeneratorQuickbuild.cpp +++ b/dScripts/02_server/Map/AM/AmShieldGeneratorQuickbuild.cpp @@ -2,6 +2,7 @@ #include "EntityManager.h" #include "DestroyableComponent.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "MovementAIComponent.h" #include "BaseCombatAIComponent.h" #include "SkillComponent.h" @@ -82,7 +83,7 @@ void AmShieldGeneratorQuickbuild::OnTimerDone(Entity* self, std::string timerNam self->AddTimer("BuffPlayers", 3.0f); } else if (timerName == "PlayFX") { - GameMessages::SendPlayFXEffect(self->GetObjectID(), 5351, u"generatorOn", "generatorOn"); + GameMessages::PlayFXEffect(self->GetObjectID(), 5351, u"generatorOn", "generatorOn").Send(UNASSIGNED_SYSTEM_ADDRESS); self->AddTimer("PlayFX", 1.5f); } else if (timerName == "RefreshEnemies") { diff --git a/dScripts/02_server/Map/AM/AmSkullkinDrill.cpp b/dScripts/02_server/Map/AM/AmSkullkinDrill.cpp index 93b876cf8..bf0eb6f7e 100644 --- a/dScripts/02_server/Map/AM/AmSkullkinDrill.cpp +++ b/dScripts/02_server/Map/AM/AmSkullkinDrill.cpp @@ -1,5 +1,6 @@ #include "AmSkullkinDrill.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "MovingPlatformComponent.h" #include "DestroyableComponent.h" #include "ProximityMonitorComponent.h" @@ -12,7 +13,7 @@ void AmSkullkinDrill::OnStartup(Entity* self) { self->SetNetworkVar(u"bIsInUse", false); self->SetVar(u"bActive", true); - GameMessages::SendPlayFXEffect(self->GetObjectID(), -1, u"spin", "active"); + GameMessages::PlayFXEffect(self->GetObjectID(), -1, u"spin", "active").Send(UNASSIGNED_SYSTEM_ADDRESS); auto* movingPlatformComponent = self->GetComponent(); @@ -135,8 +136,8 @@ void AmSkullkinDrill::OnUse(Entity* self, Entity* user) { self->SetNetworkVar(u"bIsInUse", true); - GameMessages::SendPlayFXEffect(user->GetObjectID(), 5499, u"on-anim", "tornado"); - GameMessages::SendPlayFXEffect(user->GetObjectID(), 5502, u"on-anim", "staff"); + GameMessages::PlayFXEffect(user->GetObjectID(), 5499, u"on-anim", "tornado").Send(UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::PlayFXEffect(user->GetObjectID(), 5502, u"on-anim", "staff").Send(UNASSIGNED_SYSTEM_ADDRESS); const auto userID = user->GetObjectID(); @@ -174,8 +175,8 @@ void AmSkullkinDrill::OnArrived(Entity* self, uint32_t waypointIndex) { if (waypointIndex == 1) { RenderComponent::PlayAnimation(self, u"no-spin"); - GameMessages::SendStopFXEffect(self, true, "active"); - GameMessages::SendPlayFXEffect(self->GetObjectID(), -1, u"indicator", "indicator"); + GameMessages::StopFXEffect(self->GetObjectID(), true, "active").Send(UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::PlayFXEffect(self->GetObjectID(), -1, u"indicator", "indicator").Send(UNASSIGNED_SYSTEM_ADDRESS); self->SetVar(u"bActive", false); @@ -194,8 +195,8 @@ void AmSkullkinDrill::OnArrived(Entity* self, uint32_t waypointIndex) { return; } else { RenderComponent::PlayAnimation(self, u"idle"); - GameMessages::SendPlayFXEffect(self->GetObjectID(), -1, u"spin", "active"); - GameMessages::SendStopFXEffect(self, true, "indicator"); + GameMessages::PlayFXEffect(self->GetObjectID(), -1, u"spin", "active").Send(UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::StopFXEffect(self->GetObjectID(), true, "indicator").Send(UNASSIGNED_SYSTEM_ADDRESS); } } @@ -212,7 +213,10 @@ void AmSkullkinDrill::PlayCinematic(Entity* self) { return; } - GameMessages::SendPlayCinematic(player->GetObjectID(), cine, player->GetSystemAddress()); + GameMessages::PlayCinematic cinematic; + cinematic.target = player->GetObjectID(); + cinematic.pathName = cine; + cinematic.Send(player->GetSystemAddress()); } void AmSkullkinDrill::PlayAnim(Entity* self, Entity* player, const std::string& animName) { @@ -259,7 +263,7 @@ void AmSkullkinDrill::OnHitOrHealResult(Entity* self, Entity* attacker, int32_t auto* standObj = GetStandObj(self); if (standObj != nullptr) { - GameMessages::SendPlayFXEffect(standObj->GetObjectID(), 4946, u"explode", "explode"); + GameMessages::PlayFXEffect(standObj->GetObjectID(), 4946, u"explode", "explode").Send(UNASSIGNED_SYSTEM_ADDRESS); } } @@ -320,8 +324,8 @@ void AmSkullkinDrill::OnTimerDone(Entity* self, std::string timerName) { self->SetVar(u"userID", LWOOBJID_EMPTY); - GameMessages::SendStopFXEffect(player, true, "tornado"); - GameMessages::SendStopFXEffect(player, true, "staff"); + GameMessages::StopFXEffect(player->GetObjectID(), true, "tornado").Send(UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::StopFXEffect(player->GetObjectID(), true, "staff").Send(UNASSIGNED_SYSTEM_ADDRESS); } } else if (data[0] == "TryUnFreezeAgain") { diff --git a/dScripts/02_server/Map/AM/AmSkullkinDrillStand.cpp b/dScripts/02_server/Map/AM/AmSkullkinDrillStand.cpp index 5493dc24d..f1919ac9d 100644 --- a/dScripts/02_server/Map/AM/AmSkullkinDrillStand.cpp +++ b/dScripts/02_server/Map/AM/AmSkullkinDrillStand.cpp @@ -1,5 +1,6 @@ #include "AmSkullkinDrillStand.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "dpEntity.h" #include "Entity.h" #include "RenderComponent.h" @@ -31,7 +32,7 @@ void AmSkullkinDrillStand::OnProximityUpdate(Entity* self, Entity* entering, std GameMessages::SendKnockback(entering->GetObjectID(), self->GetObjectID(), self->GetObjectID(), 0, newVec); - GameMessages::SendPlayFXEffect(entering->GetObjectID(), 1378, u"create", "pushBack"); + GameMessages::PlayFXEffect(entering->GetObjectID(), 1378, u"create", "pushBack").Send(UNASSIGNED_SYSTEM_ADDRESS); RenderComponent::PlayAnimation(entering, u"knockback-recovery"); } diff --git a/dScripts/02_server/Map/FV/ImgBrickConsoleQB.cpp b/dScripts/02_server/Map/FV/ImgBrickConsoleQB.cpp index db235f8e3..8c35de312 100644 --- a/dScripts/02_server/Map/FV/ImgBrickConsoleQB.cpp +++ b/dScripts/02_server/Map/FV/ImgBrickConsoleQB.cpp @@ -3,6 +3,7 @@ #include "dZoneManager.h" #include "EntityManager.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "MissionComponent.h" #include "eMissionState.h" #include "InventoryComponent.h" @@ -62,8 +63,8 @@ void ImgBrickConsoleQB::OnUse(Entity* self, Entity* user) { const auto& facility = Game::entityManager->GetEntitiesInGroup("FacilityPipes"); if (!facility.empty()) { - GameMessages::SendStopFXEffect(facility[0], true, location + "PipeEnergy"); - GameMessages::SendPlayFXEffect(facility[0]->GetObjectID(), onFX, u"create", location + "PipeOn"); + GameMessages::StopFXEffect(facility[0]->GetObjectID(), true, location + "PipeEnergy").Send(UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::PlayFXEffect(facility[0]->GetObjectID(), onFX, u"create", location + "PipeOn").Send(UNASSIGNED_SYSTEM_ADDRESS); } } @@ -108,8 +109,8 @@ void ImgBrickConsoleQB::SpawnBrick(Entity* self) { void ImgBrickConsoleQB::SmashCanister(Entity* self) { const auto brick = Game::entityManager->GetEntitiesInGroup("Imagination"); if (!brick.empty()) { - GameMessages::SendPlayFXEffect(brick[0]->GetObjectID(), 122, u"create", "bluebrick"); - GameMessages::SendPlayFXEffect(brick[0]->GetObjectID(), 1034, u"cast", "imaginationexplosion"); + GameMessages::PlayFXEffect(brick[0]->GetObjectID(), 122, u"create", "bluebrick").Send(UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::PlayFXEffect(brick[0]->GetObjectID(), 1034, u"cast", "imaginationexplosion").Send(UNASSIGNED_SYSTEM_ADDRESS); } const auto canisters = Game::entityManager->GetEntitiesInGroup("Canister"); @@ -138,8 +139,8 @@ void ImgBrickConsoleQB::OnQuickBuildComplete(Entity* self, Entity* target) { const auto& facility = Game::entityManager->GetEntitiesInGroup("FacilityPipes"); if (!facility.empty()) { - GameMessages::SendStopFXEffect(facility[0], true, location + "PipeOff"); - GameMessages::SendPlayFXEffect(facility[0]->GetObjectID(), energyFX, u"create", location + "PipeEnergy"); + GameMessages::StopFXEffect(facility[0]->GetObjectID(), true, location + "PipeOff").Send(UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::PlayFXEffect(facility[0]->GetObjectID(), energyFX, u"create", location + "PipeEnergy").Send(UNASSIGNED_SYSTEM_ADDRESS); } const auto consoles = Game::entityManager->GetEntitiesInGroup("Console"); @@ -182,10 +183,10 @@ void ImgBrickConsoleQB::OnDie(Entity* self, Entity* killer) { const auto& facility = Game::entityManager->GetEntitiesInGroup("FacilityPipes"); if (!facility.empty()) { - GameMessages::SendStopFXEffect(facility[0], true, location + "PipeEnergy"); - GameMessages::SendStopFXEffect(facility[0], true, location + "PipeOn"); - GameMessages::SendPlayFXEffect(facility[0]->GetObjectID(), offFX, u"create", location + "PipeOff"); - GameMessages::SendPlayFXEffect(facility[0]->GetObjectID(), 2750, u"create", location + "imagination_canister"); + GameMessages::StopFXEffect(facility[0]->GetObjectID(), true, location + "PipeEnergy").Send(UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::StopFXEffect(facility[0]->GetObjectID(), true, location + "PipeOn").Send(UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::PlayFXEffect(facility[0]->GetObjectID(), offFX, u"create", location + "PipeOff").Send(UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::PlayFXEffect(facility[0]->GetObjectID(), 2750, u"create", location + "imagination_canister").Send(UNASSIGNED_SYSTEM_ADDRESS); } } diff --git a/dScripts/02_server/Map/FV/Racing/RaceMaelstromGeiser.cpp b/dScripts/02_server/Map/FV/Racing/RaceMaelstromGeiser.cpp index 48d1b2553..2866f7c8e 100644 --- a/dScripts/02_server/Map/FV/Racing/RaceMaelstromGeiser.cpp +++ b/dScripts/02_server/Map/FV/Racing/RaceMaelstromGeiser.cpp @@ -1,5 +1,6 @@ #include "RaceMaelstromGeiser.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "PossessableComponent.h" #include "PossessorComponent.h" #include "EntityManager.h" @@ -68,7 +69,7 @@ void RaceMaelstromGeiser::OnProximityUpdate(Entity* self, Entity* entering, std: void RaceMaelstromGeiser::OnTimerDone(Entity* self, std::string timerName) { if (timerName == "downTime") { - GameMessages::SendPlayFXEffect(self->GetObjectID(), 4048, u"rebuild_medium", "geiser", LWOOBJID_EMPTY, 1, 1, true); + GameMessages::PlayFXEffect(self->GetObjectID(), 4048, u"rebuild_medium", "geiser").Send(UNASSIGNED_SYSTEM_ADDRESS); self->AddTimer("buildUpTime", 1); } else if (timerName == "buildUpTime") { @@ -76,7 +77,7 @@ void RaceMaelstromGeiser::OnTimerDone(Entity* self, std::string timerName) { self->AddTimer("killTime", 1.5f); } else if (timerName == "killTime") { - GameMessages::SendStopFXEffect(self, true, "geiser"); + GameMessages::StopFXEffect(self->GetObjectID(), true, "geiser").Send(UNASSIGNED_SYSTEM_ADDRESS); self->SetVar(u"AmFiring", false); diff --git a/dScripts/02_server/Map/GF/GfCaptainsCannon.cpp b/dScripts/02_server/Map/GF/GfCaptainsCannon.cpp index f0f3099b1..759d8817e 100644 --- a/dScripts/02_server/Map/GF/GfCaptainsCannon.cpp +++ b/dScripts/02_server/Map/GF/GfCaptainsCannon.cpp @@ -1,5 +1,6 @@ #include "GfCaptainsCannon.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "EntityManager.h" #include "MissionComponent.h" #include "RenderComponent.h" @@ -32,7 +33,7 @@ void GfCaptainsCannon::OnUse(Entity* self, Entity* user) { RenderComponent::PlayAnimation(user, u"cannon-strike-no-equip"); - GameMessages::SendPlayFXEffect(user->GetObjectID(), 6039, u"hook", "hook", LWOOBJID_EMPTY, 1, 1, true); + GameMessages::PlayFXEffect(user->GetObjectID(), 6039, u"hook", "hook").Send(UNASSIGNED_SYSTEM_ADDRESS); self->AddTimer("FireCannon", 1.667f); } @@ -52,7 +53,10 @@ void GfCaptainsCannon::OnTimerDone(Entity* self, std::string timerName) { if (timerName == "FireCannon") { float cinematicTime = 6.3f; - GameMessages::SendPlayCinematic(playerId, u"Cannon_Cam", player->GetSystemAddress()); + GameMessages::PlayCinematic cinematic; + cinematic.target = playerId; + cinematic.pathName = u"Cannon_Cam"; + cinematic.Send(player->GetSystemAddress()); self->AddTimer("cinematicTimer", cinematicTime); @@ -64,7 +68,10 @@ void GfCaptainsCannon::OnTimerDone(Entity* self, std::string timerName) { RenderComponent::PlayAnimation(shark, u"cannon"); } - GameMessages::SendPlay2DAmbientSound(player, "{7457d85c-4537-4317-ac9d-2f549219ea87}"); + GameMessages::Play2DAmbientSound ambientSound; + ambientSound.target = player->GetObjectID(); + ambientSound.audioGUID = "{7457d85c-4537-4317-ac9d-2f549219ea87}"; + ambientSound.SendToClient(player->GetSystemAddress()); } else if (timerName == "cinematicTimer") { GameMessages::SendSetStunned(playerId, eStateChangeType::POP, player->GetSystemAddress(), LWOOBJID_EMPTY, true, true, true, true, true, true, true, true @@ -73,7 +80,7 @@ void GfCaptainsCannon::OnTimerDone(Entity* self, std::string timerName) { self->SetVar(u"bIsInUse", false); self->SetNetworkVar(u"bIsInUse", false); - GameMessages::SendStopFXEffect(player, true, "hook"); + GameMessages::StopFXEffect(player->GetObjectID(), true, "hook").Send(UNASSIGNED_SYSTEM_ADDRESS); auto* missionComponent = player->GetComponent(); diff --git a/dScripts/02_server/Map/GF/MastTeleport.cpp b/dScripts/02_server/Map/GF/MastTeleport.cpp index f2adc80fd..7c1633846 100644 --- a/dScripts/02_server/Map/GF/MastTeleport.cpp +++ b/dScripts/02_server/Map/GF/MastTeleport.cpp @@ -1,6 +1,7 @@ #include "MastTeleport.h" #include "EntityManager.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "Preconditions.h" #include "eEndBehavior.h" #include "DestroyableComponent.h" @@ -49,12 +50,20 @@ void MastTeleport::OnTimerDone(Entity* self, std::string timerName) { const auto leanIn = self->GetVar(u"LeanIn"); if (!cinematic.empty()) { - GameMessages::SendPlayCinematic(playerId, GeneralUtils::ASCIIToUTF16(cinematic), player->GetSystemAddress(), - true, true, false, false, eEndBehavior::RETURN, false, leanIn - ); + GameMessages::PlayCinematic playCinematic; + playCinematic.target = playerId; + playCinematic.pathName = GeneralUtils::ASCIIToUTF16(cinematic); + playCinematic.allowGhostUpdates = true; + playCinematic.bCloseMultiInteract = true; + playCinematic.bSendServerNotify = false; + playCinematic.bUseControlledObjectForAudioListener = false; + playCinematic.endBehavior = eEndBehavior::RETURN; + playCinematic.hidePlayerDuringCine = false; + playCinematic.leadIn = leanIn; + playCinematic.Send(player->GetSystemAddress()); } - GameMessages::SendPlayFXEffect(playerId, 6039, u"hook", "hook", LWOOBJID_EMPTY, 1, 1, true); + GameMessages::PlayFXEffect(playerId, 6039, u"hook", "hook").Send(UNASSIGNED_SYSTEM_ADDRESS); float animationTime = 6.25f; animationTime = RenderComponent::PlayAnimation(player, "crow-swing-no-equip", 4.0f); @@ -63,7 +72,7 @@ void MastTeleport::OnTimerDone(Entity* self, std::string timerName) { self->AddTimer("PlayerAnimDone", animationTime); } else if (timerName == "PlayerAnimDone") { - GameMessages::SendStopFXEffect(player, true, "hook"); + GameMessages::StopFXEffect(player->GetObjectID(), true, "hook").Send(UNASSIGNED_SYSTEM_ADDRESS); auto forward = QuatUtils::Forward(self->GetRotation()); diff --git a/dScripts/02_server/Map/General/BankInteractServer.cpp b/dScripts/02_server/Map/General/BankInteractServer.cpp index 9b5634917..e87185752 100644 --- a/dScripts/02_server/Map/General/BankInteractServer.cpp +++ b/dScripts/02_server/Map/General/BankInteractServer.cpp @@ -1,5 +1,6 @@ #include "BankInteractServer.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "Entity.h" #include "Amf3.h" @@ -8,7 +9,11 @@ void BankInteractServer::OnUse(Entity* self, Entity* user) { args.Insert("state", "bank"); - GameMessages::SendUIMessageServerToSingleClient(user, user->GetSystemAddress(), "pushGameState", args); + GameMessages::UIMessageServerToSingleClient uiMessage; + uiMessage.target = user->GetObjectID(); + uiMessage.strMessageName = "pushGameState"; + uiMessage.args = std::move(args); + uiMessage.SendToClient(user->GetSystemAddress()); } void BankInteractServer::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, @@ -18,7 +23,11 @@ void BankInteractServer::OnFireEventServerSide(Entity* self, Entity* sender, std args.Insert("visible", false); - GameMessages::SendUIMessageServerToSingleClient(sender, sender->GetSystemAddress(), "ToggleBank", args); + GameMessages::UIMessageServerToSingleClient uiMessage; + uiMessage.target = sender->GetObjectID(); + uiMessage.strMessageName = "ToggleBank"; + uiMessage.args = std::move(args); + uiMessage.SendToClient(sender->GetSystemAddress()); GameMessages::SendNotifyClientObject(self->GetObjectID(), u"CloseBank", 0, 0, LWOOBJID_EMPTY, "", sender->GetSystemAddress()); } diff --git a/dScripts/02_server/Map/General/BaseInteractDropLootServer.cpp b/dScripts/02_server/Map/General/BaseInteractDropLootServer.cpp index 6b037ca55..4a327a553 100644 --- a/dScripts/02_server/Map/General/BaseInteractDropLootServer.cpp +++ b/dScripts/02_server/Map/General/BaseInteractDropLootServer.cpp @@ -1,6 +1,7 @@ #include "BaseInteractDropLootServer.h" #include "Loot.h" #include "GameMessages.h" +#include "EffectsMessages.h" void BaseInteractDropLootServer::OnUse(Entity* self, Entity* user) { BaseUse(self, user); @@ -17,7 +18,7 @@ void BaseInteractDropLootServer::BaseUse(Entity* self, Entity* user) { auto useSound = self->GetVar(u"sound1"); if (!useSound.empty()) { - GameMessages::SendPlayNDAudioEmitter(self, user->GetSystemAddress(), useSound); + GameMessages::PlayNDAudioEmitter(self->GetObjectID(), useSound).Send(UNASSIGNED_SYSTEM_ADDRESS); } self->SetNetworkVar(u"bInUse", true); diff --git a/dScripts/02_server/Map/General/ExplodingAsset.cpp b/dScripts/02_server/Map/General/ExplodingAsset.cpp index f4902a2ce..b3b1af5ce 100644 --- a/dScripts/02_server/Map/General/ExplodingAsset.cpp +++ b/dScripts/02_server/Map/General/ExplodingAsset.cpp @@ -1,6 +1,7 @@ #include "ExplodingAsset.h" #include "DestroyableComponent.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "MissionComponent.h" #include "SkillComponent.h" #include "eMissionTaskType.h" @@ -59,7 +60,12 @@ void ExplodingAsset::OnHit(Entity* self, Entity* attacker) { self->SetBoolean(u"bIsHit", true); self->SetOwnerOverride(attacker->GetObjectID()); - GameMessages::SendPlayEmbeddedEffectOnAllClientsNearObject(self, u"camshake", self->GetObjectID(), 16); + GameMessages::PlayEmbeddedEffectOnAllClientsNearObject embeddedEffect; + embeddedEffect.target = self->GetObjectID(); + embeddedEffect.effectName = u"camshake"; + embeddedEffect.fromObjectID = self->GetObjectID(); + embeddedEffect.radius = 16; + embeddedEffect.Send(UNASSIGNED_SYSTEM_ADDRESS); self->Smash(attacker->GetObjectID()); auto* skillComponent = self->GetComponent(); @@ -92,14 +98,14 @@ void ExplodingAsset::OnProximityUpdate(Entity* self, Entity* entering, std::stri if (status == "ENTER") { RenderComponent::PlayAnimation(self, u"bounce"); - GameMessages::SendPlayFXEffect(self, -1, u"anim", "bouncin", LWOOBJID_EMPTY, 1, 1, true); + GameMessages::PlayFXEffect(self->GetObjectID(), -1, u"anim", "bouncin").Send(UNASSIGNED_SYSTEM_ADDRESS); 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) { RenderComponent::PlayAnimation(self, u"idle"); - GameMessages::SendStopFXEffect(self, true, "bouncin"); + GameMessages::StopFXEffect(self->GetObjectID(), true, "bouncin").Send(UNASSIGNED_SYSTEM_ADDRESS); self->SetVar(u"playersNearChest", 0); } } diff --git a/dScripts/02_server/Map/General/MailBoxServer.cpp b/dScripts/02_server/Map/General/MailBoxServer.cpp index 53f3b3a26..25eac7663 100644 --- a/dScripts/02_server/Map/General/MailBoxServer.cpp +++ b/dScripts/02_server/Map/General/MailBoxServer.cpp @@ -1,6 +1,7 @@ #include "MailBoxServer.h" #include "Amf3.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "Entity.h" void MailBoxServer::OnUse(Entity* self, Entity* user) { @@ -8,13 +9,21 @@ void MailBoxServer::OnUse(Entity* self, Entity* user) { args.Insert("state", "Mail"); - GameMessages::SendUIMessageServerToSingleClient(user, user->GetSystemAddress(), "pushGameState", args); + GameMessages::UIMessageServerToSingleClient uiMessage; + uiMessage.target = user->GetObjectID(); + uiMessage.strMessageName = "pushGameState"; + uiMessage.args = std::move(args); + uiMessage.SendToClient(user->GetSystemAddress()); } void MailBoxServer::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2, int32_t param3) { if (args == "toggleMail") { AMFArrayValue args; args.Insert("visible", false); - GameMessages::SendUIMessageServerToSingleClient(sender, sender->GetSystemAddress(), "ToggleMail", args); + GameMessages::UIMessageServerToSingleClient uiMessage; + uiMessage.target = sender->GetObjectID(); + uiMessage.strMessageName = "ToggleMail"; + uiMessage.args = std::move(args); + uiMessage.SendToClient(sender->GetSystemAddress()); } } diff --git a/dScripts/02_server/Map/General/PropertyDevice.cpp b/dScripts/02_server/Map/General/PropertyDevice.cpp index df13a3255..bc3c17751 100644 --- a/dScripts/02_server/Map/General/PropertyDevice.cpp +++ b/dScripts/02_server/Map/General/PropertyDevice.cpp @@ -1,5 +1,6 @@ #include "PropertyDevice.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "EntityManager.h" #include "MissionComponent.h" #include "eMissionState.h" @@ -19,7 +20,7 @@ void PropertyDevice::OnQuickBuildComplete(Entity* self, Entity* target) { auto* missionComponent = target->GetComponent(); if (missionComponent != nullptr) { if (missionComponent->GetMissionState(m_PropertyMissionID) == eMissionState::ACTIVE) { - GameMessages::SendPlayFXEffect(self->GetObjectID(), 641, u"create", "callhome"); + GameMessages::PlayFXEffect(self->GetObjectID(), 641, u"create", "callhome").Send(UNASSIGNED_SYSTEM_ADDRESS); missionComponent->ForceProgress(m_PropertyMissionID, 1793, self->GetLOT()); } } diff --git a/dScripts/02_server/Map/General/StoryBoxInteractServer.cpp b/dScripts/02_server/Map/General/StoryBoxInteractServer.cpp index a5ce92cd4..05aadf8f8 100644 --- a/dScripts/02_server/Map/General/StoryBoxInteractServer.cpp +++ b/dScripts/02_server/Map/General/StoryBoxInteractServer.cpp @@ -1,6 +1,7 @@ #include "StoryBoxInteractServer.h" #include "Character.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "dServer.h" #include "Amf3.h" #include "Entity.h" @@ -14,7 +15,11 @@ void StoryBoxInteractServer::OnUse(Entity* self, Entity* user) { args.Insert("state", "Story"); - GameMessages::SendUIMessageServerToSingleClient(user, user->GetSystemAddress(), "pushGameState", args); + GameMessages::UIMessageServerToSingleClient uiMessage; + uiMessage.target = user->GetObjectID(); + uiMessage.strMessageName = "pushGameState"; + uiMessage.args = std::move(args); + uiMessage.SendToClient(user->GetSystemAddress()); } user->AddCallbackTimer(0.1f, [user, customText]() { @@ -23,7 +28,11 @@ void StoryBoxInteractServer::OnUse(Entity* self, Entity* user) { args.Insert("visible", true); args.Insert("text", customText); - GameMessages::SendUIMessageServerToSingleClient(user, user->GetSystemAddress(), "ToggleStoryBox", args); + GameMessages::UIMessageServerToSingleClient uiMessage; + uiMessage.target = user->GetObjectID(); + uiMessage.strMessageName = "ToggleStoryBox"; + uiMessage.args = std::move(args); + uiMessage.SendToClient(user->GetSystemAddress()); }); return; diff --git a/dScripts/02_server/Map/General/TokenConsoleServer.cpp b/dScripts/02_server/Map/General/TokenConsoleServer.cpp index 68f4130fe..d8d5ba177 100644 --- a/dScripts/02_server/Map/General/TokenConsoleServer.cpp +++ b/dScripts/02_server/Map/General/TokenConsoleServer.cpp @@ -1,6 +1,7 @@ #include "TokenConsoleServer.h" #include "InventoryComponent.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "Character.h" #include "eReplicaComponentType.h" #include "eTerminateType.h" @@ -18,7 +19,7 @@ void TokenConsoleServer::OnUse(Entity* self, Entity* user) { //play sound if (self->HasVar(u"sound1")) { - GameMessages::SendPlayNDAudioEmitter(self, user->GetSystemAddress(), self->GetVarAsString(u"sound1")); + GameMessages::PlayNDAudioEmitter(self->GetObjectID(), self->GetVarAsString(u"sound1")).Send(UNASSIGNED_SYSTEM_ADDRESS); } //figure out which faction the player belongs to: diff --git a/dScripts/02_server/Map/General/WishingWellServer.cpp b/dScripts/02_server/Map/General/WishingWellServer.cpp index 160282d3f..2efa6ee21 100644 --- a/dScripts/02_server/Map/General/WishingWellServer.cpp +++ b/dScripts/02_server/Map/General/WishingWellServer.cpp @@ -1,6 +1,7 @@ #include "WishingWellServer.h" #include "ScriptedActivityComponent.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "Loot.h" #include "EntityManager.h" #include "eTerminateType.h" @@ -18,7 +19,7 @@ void WishingWellServer::OnUse(Entity* self, Entity* user) { const auto audio = self->GetVar(u"sound1"); if (!audio.empty()) { - GameMessages::SendPlayNDAudioEmitter(self, user->GetSystemAddress(), audio); + GameMessages::PlayNDAudioEmitter(self->GetObjectID(), audio).Send(UNASSIGNED_SYSTEM_ADDRESS); } Loot::DropActivityLoot( diff --git a/dScripts/02_server/Map/NS/NsLegoClubDoor.cpp b/dScripts/02_server/Map/NS/NsLegoClubDoor.cpp index 1cafe67c9..3b532755d 100644 --- a/dScripts/02_server/Map/NS/NsLegoClubDoor.cpp +++ b/dScripts/02_server/Map/NS/NsLegoClubDoor.cpp @@ -1,6 +1,7 @@ #include "NsLegoClubDoor.h" #include "dZoneManager.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "Amf3.h" void NsLegoClubDoor::OnStartup(Entity* self) { @@ -41,7 +42,11 @@ void NsLegoClubDoor::OnUse(Entity* self, Entity* user) { auto* player = user; if (CheckChoice(self, player)) { - GameMessages::SendUIMessageServerToSingleClient(player, player->GetSystemAddress(), "QueueChoiceBox", teleportArgs); + GameMessages::UIMessageServerToSingleClient uiMessage; + uiMessage.target = player->GetObjectID(); + uiMessage.strMessageName = "QueueChoiceBox"; + uiMessage.args = std::move(teleportArgs); + uiMessage.SendToClient(player->GetSystemAddress()); } else if (self->GetVar(u"currentZone") != m_ChoiceZoneID) { AMFArrayValue multiArgs; multiArgs.Insert("state", "Lobby"); @@ -52,7 +57,11 @@ void NsLegoClubDoor::OnUse(Entity* self, Entity* user) { context->Insert("HelpVisible", "show"); context->Insert("type", "Lego_Club_Valid"); - GameMessages::SendUIMessageServerToSingleClient(player, player->GetSystemAddress(), "pushGameState", multiArgs); + GameMessages::UIMessageServerToSingleClient uiMessage; + uiMessage.target = player->GetObjectID(); + uiMessage.strMessageName = "pushGameState"; + uiMessage.args = std::move(multiArgs); + uiMessage.SendToClient(player->GetSystemAddress()); } else { BaseOnUse(self, player); } diff --git a/dScripts/02_server/Map/NS/NsLupTeleport.cpp b/dScripts/02_server/Map/NS/NsLupTeleport.cpp index 6886b4cdc..a07ef8987 100644 --- a/dScripts/02_server/Map/NS/NsLupTeleport.cpp +++ b/dScripts/02_server/Map/NS/NsLupTeleport.cpp @@ -1,6 +1,7 @@ #include "NsLupTeleport.h" #include "dZoneManager.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "Amf3.h" void NsLupTeleport::OnStartup(Entity* self) { @@ -41,7 +42,11 @@ void NsLupTeleport::OnUse(Entity* self, Entity* user) { auto* player = user; if (CheckChoice(self, player)) { - GameMessages::SendUIMessageServerToSingleClient(player, player->GetSystemAddress(), "QueueChoiceBox", args); + GameMessages::UIMessageServerToSingleClient uiMessage; + uiMessage.target = player->GetObjectID(); + uiMessage.strMessageName = "QueueChoiceBox"; + uiMessage.args = std::move(args); + uiMessage.SendToClient(player->GetSystemAddress()); } else { BaseOnUse(self, player); } diff --git a/dScripts/02_server/Map/NS/NsTokenConsoleServer.cpp b/dScripts/02_server/Map/NS/NsTokenConsoleServer.cpp index 39bda78bf..df0fe7b68 100644 --- a/dScripts/02_server/Map/NS/NsTokenConsoleServer.cpp +++ b/dScripts/02_server/Map/NS/NsTokenConsoleServer.cpp @@ -1,6 +1,7 @@ #include "NsTokenConsoleServer.h" #include "InventoryComponent.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "Character.h" #include "MissionComponent.h" #include "QuickBuildComponent.h" @@ -39,7 +40,7 @@ void NsTokenConsoleServer::OnUse(Entity* self, Entity* user) { const auto useSound = self->GetVar(u"sound1"); if (!useSound.empty()) { - GameMessages::SendPlayNDAudioEmitter(self, user->GetSystemAddress(), useSound); + GameMessages::PlayNDAudioEmitter(self->GetObjectID(), useSound).Send(UNASSIGNED_SYSTEM_ADDRESS); } // Player must be in faction to interact with this entity. diff --git a/dScripts/02_server/Map/NT/NtAssemblyTubeServer.cpp b/dScripts/02_server/Map/NT/NtAssemblyTubeServer.cpp index 6ae4c7679..9d30ccd60 100644 --- a/dScripts/02_server/Map/NT/NtAssemblyTubeServer.cpp +++ b/dScripts/02_server/Map/NT/NtAssemblyTubeServer.cpp @@ -1,5 +1,6 @@ #include "NtAssemblyTubeServer.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "EntityManager.h" #include "MissionComponent.h" #include "eMissionTaskType.h" @@ -47,9 +48,19 @@ void NtAssemblyTubeServer::RunAssemblyTube(Entity* self, Entity* player) { if (!teleCinematic.empty()) { const auto teleCinematicUname = teleCinematic; - GameMessages::SendPlayCinematic(player->GetObjectID(), teleCinematicUname, player->GetSystemAddress(), - true, true, true, false, eEndBehavior::RETURN, false, -1, false, true - ); + GameMessages::PlayCinematic cinematic; + cinematic.target = player->GetObjectID(); + cinematic.pathName = teleCinematicUname; + cinematic.allowGhostUpdates = true; + cinematic.bCloseMultiInteract = true; + cinematic.bSendServerNotify = true; + cinematic.bUseControlledObjectForAudioListener = false; + cinematic.endBehavior = eEndBehavior::RETURN; + cinematic.hidePlayerDuringCine = false; + cinematic.leadIn = -1; + cinematic.leavePlayerLockedWhenFinished = false; + cinematic.lockPlayer = true; + cinematic.Send(player->GetSystemAddress()); } RenderComponent::PlayAnimation(player, u"tube-sucker", 4.0f); @@ -104,7 +115,7 @@ void NtAssemblyTubeServer::TeleportPlayer(Entity* self, Entity* player) { const auto useSound = self->GetVar(u"sound1"); if (!useSound.empty()) { - GameMessages::SendPlayNDAudioEmitter(player, player->GetSystemAddress(), useSound); + GameMessages::PlayNDAudioEmitter(player->GetObjectID(), useSound).Send(UNASSIGNED_SYSTEM_ADDRESS); } } diff --git a/dScripts/02_server/Map/NT/NtBeamImaginationCollectors.cpp b/dScripts/02_server/Map/NT/NtBeamImaginationCollectors.cpp index b8036c896..b49f07c26 100644 --- a/dScripts/02_server/Map/NT/NtBeamImaginationCollectors.cpp +++ b/dScripts/02_server/Map/NT/NtBeamImaginationCollectors.cpp @@ -1,6 +1,7 @@ #include "NtBeamImaginationCollectors.h" #include "GeneralUtils.h" #include "GameMessages.h" +#include "EffectsMessages.h" void NtBeamImaginationCollectors::OnStartup(Entity* self) { self->AddTimer("PlayFX", GetRandomNum()); @@ -23,7 +24,7 @@ void NtBeamImaginationCollectors::OnTimerDone(Entity* self, std::string timerNam return; } - GameMessages::SendPlayFXEffect(self->GetObjectID(), -1, m_FxName, "Beam"); + GameMessages::PlayFXEffect(self->GetObjectID(), -1, m_FxName, "Beam").Send(UNASSIGNED_SYSTEM_ADDRESS); self->AddTimer("PlayFX", GetRandomNum()); } diff --git a/dScripts/02_server/Map/NT/NtCombatChallengeExplodingDummy.cpp b/dScripts/02_server/Map/NT/NtCombatChallengeExplodingDummy.cpp index c384b26d5..d9201f17a 100644 --- a/dScripts/02_server/Map/NT/NtCombatChallengeExplodingDummy.cpp +++ b/dScripts/02_server/Map/NT/NtCombatChallengeExplodingDummy.cpp @@ -2,6 +2,7 @@ #include "EntityManager.h" #include "SkillComponent.h" #include "DestroyableComponent.h" +#include "EffectsMessages.h" void NtCombatChallengeExplodingDummy::OnDie(Entity* self, Entity* killer) { const auto challengeObjectID = self->GetVar(u"challengeObjectID"); @@ -36,6 +37,11 @@ void NtCombatChallengeExplodingDummy::OnHitOrHealResult(Entity* self, Entity* at if (skillComponent != nullptr) { skillComponent->CalculateBehavior(1338, 30875, attacker->GetObjectID()); } - GameMessages::SendPlayEmbeddedEffectOnAllClientsNearObject(self, u"camshake", self->GetObjectID(), 16.0f); + GameMessages::PlayEmbeddedEffectOnAllClientsNearObject embeddedEffect; + embeddedEffect.target = self->GetObjectID(); + embeddedEffect.effectName = u"camshake"; + embeddedEffect.fromObjectID = self->GetObjectID(); + embeddedEffect.radius = 16.0f; + embeddedEffect.Send(UNASSIGNED_SYSTEM_ADDRESS); self->Smash(attacker->GetObjectID()); } diff --git a/dScripts/02_server/Map/NT/NtCombatChallengeServer.cpp b/dScripts/02_server/Map/NT/NtCombatChallengeServer.cpp index 6e05112c5..51d7ebd8d 100644 --- a/dScripts/02_server/Map/NT/NtCombatChallengeServer.cpp +++ b/dScripts/02_server/Map/NT/NtCombatChallengeServer.cpp @@ -1,5 +1,6 @@ #include "NtCombatChallengeServer.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "ActivityMessages.h" #include "EntityManager.h" #include "EntityInfo.h" @@ -33,7 +34,7 @@ void NtCombatChallengeServer::OnHitOrHealResult(Entity* self, Entity* attacker, self->SetVar(u"totalDmg", totalDmg); self->SetNetworkVar(u"totalDmg", totalDmg); - GameMessages::SendPlayNDAudioEmitter(self, attacker->GetSystemAddress(), scoreSound); + GameMessages::PlayNDAudioEmitter(self->GetObjectID(), scoreSound).Send(UNASSIGNED_SYSTEM_ADDRESS); } @@ -55,7 +56,7 @@ void NtCombatChallengeServer::OnMessageBoxResponse(Entity* self, Entity* sender, inventoryComponent->RemoveItem(3039, 1, eInventoryType::ALL); } - GameMessages::SendPlayNDAudioEmitter(self, sender->GetSystemAddress(), startSound); + GameMessages::PlayNDAudioEmitter(self->GetObjectID(), startSound).Send(UNASSIGNED_SYSTEM_ADDRESS); self->AddTimer("start_delay", 2.0f); @@ -164,9 +165,9 @@ void NtCombatChallengeServer::OnActivityTimerUpdate(Entity* self, float timeRema self->SetNetworkVar(u"update_time", std::ceil(timeRemaining)); if (timeRemaining <= 3) { - GameMessages::SendPlayNDAudioEmitter(self, UNASSIGNED_SYSTEM_ADDRESS, timerLowSound); + GameMessages::PlayNDAudioEmitter(self->GetObjectID(), timerLowSound).Send(UNASSIGNED_SYSTEM_ADDRESS); } else { - GameMessages::SendPlayNDAudioEmitter(self, UNASSIGNED_SYSTEM_ADDRESS, timerSound); + GameMessages::PlayNDAudioEmitter(self->GetObjectID(), timerSound).Send(UNASSIGNED_SYSTEM_ADDRESS); } } @@ -189,7 +190,7 @@ void NtCombatChallengeServer::OnTimerDone(Entity* self, std::string timerName) { if (gameTick <= 0) { ResetGame(self); - GameMessages::SendPlayNDAudioEmitter(self, UNASSIGNED_SYSTEM_ADDRESS, stopSound); + GameMessages::PlayNDAudioEmitter(self->GetObjectID(), stopSound).Send(UNASSIGNED_SYSTEM_ADDRESS); self->AddTimer("reset_tick", 5); } else { diff --git a/dScripts/02_server/Map/NT/NtParadoxPanelServer.cpp b/dScripts/02_server/Map/NT/NtParadoxPanelServer.cpp index f182c8a5f..1d81a1192 100644 --- a/dScripts/02_server/Map/NT/NtParadoxPanelServer.cpp +++ b/dScripts/02_server/Map/NT/NtParadoxPanelServer.cpp @@ -1,5 +1,6 @@ #include "NtParadoxPanelServer.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "MissionComponent.h" #include "EntityManager.h" #include "Character.h" @@ -53,7 +54,7 @@ void NtParadoxPanelServer::OnUse(Entity* self, Entity* user) { GameMessages::SendKnockback(user->GetObjectID(), self->GetObjectID(), self->GetObjectID(), 0, { dir.x * 15, 5, dir.z * 15 }); - GameMessages::SendPlayFXEffect(self, 6432, u"create", "console_sparks", LWOOBJID_EMPTY, 1.0, 1.0, true); + GameMessages::PlayFXEffect(self->GetObjectID(), 6432, u"create", "console_sparks").Send(UNASSIGNED_SYSTEM_ADDRESS); self->AddCallbackTimer(2, [this, self, playerID]() { auto* player = Game::entityManager->GetEntity(playerID); @@ -64,7 +65,7 @@ void NtParadoxPanelServer::OnUse(Entity* self, Entity* user) { GameMessages::SendNotifyClientObject(self->GetObjectID(), u"bActive", 0, 0, player->GetObjectID(), "", player->GetSystemAddress()); - GameMessages::SendStopFXEffect(self, true, "console_sparks"); + GameMessages::StopFXEffect(self->GetObjectID(), true, "console_sparks").Send(UNASSIGNED_SYSTEM_ADDRESS); self->SetVar(u"bActive", false); }); diff --git a/dScripts/02_server/Map/NT/NtParadoxTeleServer.cpp b/dScripts/02_server/Map/NT/NtParadoxTeleServer.cpp index 67ff4bec7..65670fb28 100644 --- a/dScripts/02_server/Map/NT/NtParadoxTeleServer.cpp +++ b/dScripts/02_server/Map/NT/NtParadoxTeleServer.cpp @@ -1,5 +1,6 @@ #include "NtParadoxTeleServer.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "EntityManager.h" #include "MissionComponent.h" #include "eMissionTaskType.h" @@ -69,7 +70,10 @@ void NtParadoxTeleServer::TeleportPlayer(Entity* self, Entity* player) { if (!teleCinematic.empty()) { const auto teleCinematicUname = teleCinematic; - GameMessages::SendPlayCinematic(player->GetObjectID(), teleCinematicUname, player->GetSystemAddress()); + GameMessages::PlayCinematic cinematic; + cinematic.target = player->GetObjectID(); + cinematic.pathName = teleCinematicUname; + cinematic.Send(player->GetSystemAddress()); } GameMessages::SendTeleport(player->GetObjectID(), destPosition, destRotation, player->GetSystemAddress(), true); @@ -93,7 +97,7 @@ void NtParadoxTeleServer::TeleportPlayer(Entity* self, Entity* player) { const auto useSound = self->GetVar(u"sound1"); if (!useSound.empty()) { - GameMessages::SendPlayNDAudioEmitter(player, player->GetSystemAddress(), useSound); + GameMessages::PlayNDAudioEmitter(player->GetObjectID(), useSound).Send(UNASSIGNED_SYSTEM_ADDRESS); } } @@ -110,6 +114,9 @@ void NtParadoxTeleServer::UnlockPlayer(Entity* self, Entity* player) { if (!teleCinematic.empty()) { const auto teleCinematicUname = teleCinematic; - GameMessages::SendEndCinematic(player->GetObjectID(), teleCinematicUname, player->GetSystemAddress()); + GameMessages::EndCinematic endCinematic; + endCinematic.target = player->GetObjectID(); + endCinematic.pathName = teleCinematicUname; + endCinematic.Send(player->GetSystemAddress()); } } diff --git a/dScripts/02_server/Map/NT/NtVentureCannonServer.cpp b/dScripts/02_server/Map/NT/NtVentureCannonServer.cpp index 7e38ac12f..d35950f9d 100644 --- a/dScripts/02_server/Map/NT/NtVentureCannonServer.cpp +++ b/dScripts/02_server/Map/NT/NtVentureCannonServer.cpp @@ -1,5 +1,6 @@ #include "NtVentureCannonServer.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "EntityManager.h" #include "Entity.h" #include "GeneralUtils.h" @@ -35,9 +36,12 @@ void NtVentureCannonServer::OnUse(Entity* self, Entity* user) { RenderComponent::PlayAnimation(player, u"scale-down", 4.0f); const auto enterCinematicUname = enterCinematic; - GameMessages::SendPlayCinematic(player->GetObjectID(), enterCinematicUname, player->GetSystemAddress()); + GameMessages::PlayCinematic cinematic; + cinematic.target = player->GetObjectID(); + cinematic.pathName = enterCinematicUname; + cinematic.Send(player->GetSystemAddress()); - GameMessages::SendPlayNDAudioEmitter(player, player->GetSystemAddress(), "{e8bf79ce-7453-4a7d-b872-fee65e97ff15}"); + GameMessages::PlayNDAudioEmitter(player->GetObjectID(), "{e8bf79ce-7453-4a7d-b872-fee65e97ff15}").Send(UNASSIGNED_SYSTEM_ADDRESS); self->AddCallbackTimer(3, [this, self]() { self->SetNetworkVar(u"bIsInUse", false); @@ -62,9 +66,14 @@ void NtVentureCannonServer::EnterCannonEnded(Entity* self, Entity* player) { if (!cannonEffectGroup.empty()) { auto* cannonEffect = cannonEffectGroup[0]; - GameMessages::SendPlayFXEffect(cannonEffect, 6036, u"create", "cannon_blast", LWOOBJID_EMPTY, 1, 1, true); + GameMessages::PlayFXEffect(cannonEffect->GetObjectID(), 6036, u"create", "cannon_blast").Send(UNASSIGNED_SYSTEM_ADDRESS); - GameMessages::SendPlayEmbeddedEffectOnAllClientsNearObject(cannonEffect, u"camshake-bridge", cannonEffect->GetObjectID(), 100); + GameMessages::PlayEmbeddedEffectOnAllClientsNearObject embeddedEffect; + embeddedEffect.target = cannonEffect->GetObjectID(); + embeddedEffect.effectName = u"camshake-bridge"; + embeddedEffect.fromObjectID = cannonEffect->GetObjectID(); + embeddedEffect.radius = 100; + embeddedEffect.Send(UNASSIGNED_SYSTEM_ADDRESS); } FirePlayer(self, player); @@ -78,9 +87,19 @@ void NtVentureCannonServer::EnterCannonEnded(Entity* self, Entity* player) { } const auto exitCinematicUname = exitCinematic; - GameMessages::SendPlayCinematic(player->GetObjectID(), exitCinematicUname, player->GetSystemAddress(), - true, true, true, false, eEndBehavior::RETURN, false, 0, false, false - ); + GameMessages::PlayCinematic cinematic; + cinematic.target = player->GetObjectID(); + cinematic.pathName = exitCinematicUname; + cinematic.allowGhostUpdates = true; + cinematic.bCloseMultiInteract = true; + cinematic.bSendServerNotify = true; + cinematic.bUseControlledObjectForAudioListener = false; + cinematic.endBehavior = eEndBehavior::RETURN; + cinematic.hidePlayerDuringCine = false; + cinematic.leadIn = 0; + cinematic.leavePlayerLockedWhenFinished = false; + cinematic.lockPlayer = false; + cinematic.Send(player->GetSystemAddress()); self->AddCallbackTimer(1.5f, [this, self, playerID]() { auto* player = Game::entityManager->GetEntity(playerID); diff --git a/dScripts/02_server/Map/PR/HydrantBroken.cpp b/dScripts/02_server/Map/PR/HydrantBroken.cpp index c1702cc26..daaee04b7 100644 --- a/dScripts/02_server/Map/PR/HydrantBroken.cpp +++ b/dScripts/02_server/Map/PR/HydrantBroken.cpp @@ -2,6 +2,7 @@ #include "PetMessages.h" #include "EntityManager.h" #include "GameMessages.h" +#include "EffectsMessages.h" void HydrantBroken::OnStartup(Entity* self) { self->AddTimer("playEffect", 1); @@ -39,6 +40,6 @@ void HydrantBroken::OnTimerDone(Entity* self, std::string timerName) { self->Kill(); } else if (timerName == "playEffect") { - GameMessages::SendPlayFXEffect(self->GetObjectID(), 384, u"water", "water", LWOOBJID_EMPTY, 1, 1, true); + GameMessages::PlayFXEffect(self->GetObjectID(), 384, u"water", "water").Send(UNASSIGNED_SYSTEM_ADDRESS); } } diff --git a/dScripts/02_server/Map/Property/AG_Small/EnemySpiderSpawner.cpp b/dScripts/02_server/Map/Property/AG_Small/EnemySpiderSpawner.cpp index 2d526a257..4b5e74fe1 100644 --- a/dScripts/02_server/Map/Property/AG_Small/EnemySpiderSpawner.cpp +++ b/dScripts/02_server/Map/Property/AG_Small/EnemySpiderSpawner.cpp @@ -1,5 +1,6 @@ #include "EnemySpiderSpawner.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "EntityManager.h" #include "EntityInfo.h" #include "DestroyableComponent.h" @@ -12,7 +13,7 @@ void EnemySpiderSpawner::OnFireEventServerSide(Entity* self, Entity* sender, std int32_t param2, int32_t param3) { if (args == "prepEgg") { // Highlight eggs about to hatch with Maelstrom effect - GameMessages::SendPlayFXEffect(self->GetObjectID(), 2856, u"maelstrom", "test", LWOOBJID_EMPTY, 1.0f, 1.0f, true); + GameMessages::PlayFXEffect(self->GetObjectID(), 2856, u"maelstrom", "test").Send(UNASSIGNED_SYSTEM_ADDRESS); // Make indestructible auto dest = static_cast(self->GetComponent(eReplicaComponentType::DESTROYABLE)); @@ -37,7 +38,7 @@ void EnemySpiderSpawner::OnTimerDone(Entity* self, std::string timerName) { if (timerName == "StartSpawnTime") { SpawnSpiderling(self); } else if (timerName == "SpawnSpiderling") { - GameMessages::SendPlayFXEffect(self->GetObjectID(), 644, u"create", "egg_puff_b", LWOOBJID_EMPTY, 1.0f, 1.0f, true); + GameMessages::PlayFXEffect(self->GetObjectID(), 644, u"create", "egg_puff_b").Send(UNASSIGNED_SYSTEM_ADDRESS); //TODO: set the aggro radius larger @@ -63,6 +64,6 @@ void EnemySpiderSpawner::OnTimerDone(Entity* self, std::string timerName) { //-------------------------------------------------------------- void EnemySpiderSpawner::SpawnSpiderling(Entity* self) { //Initiate the actual spawning - GameMessages::SendPlayFXEffect(self->GetObjectID(), 2260, u"rebuild_medium", "dropdustmedium", LWOOBJID_EMPTY, 1.0f, 1.0f, true); + GameMessages::PlayFXEffect(self->GetObjectID(), 2260, u"rebuild_medium", "dropdustmedium").Send(UNASSIGNED_SYSTEM_ADDRESS); self->AddTimer("SpawnSpiderling", spawnTime); } diff --git a/dScripts/02_server/Map/Property/AG_Small/ZoneAgProperty.cpp b/dScripts/02_server/Map/Property/AG_Small/ZoneAgProperty.cpp index 180543650..dc260c7c8 100644 --- a/dScripts/02_server/Map/Property/AG_Small/ZoneAgProperty.cpp +++ b/dScripts/02_server/Map/Property/AG_Small/ZoneAgProperty.cpp @@ -3,6 +3,7 @@ #include "Character.h" #include "Entity.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "dZoneManager.h" #include "RenderComponent.h" #include "MissionComponent.h" @@ -62,7 +63,10 @@ void ZoneAgProperty::OnPlayerLoaded(Entity* self, Entity* player) { } if (Game::zoneManager->GetZone()->GetZoneID().GetMapID() == 1102) { - GameMessages::SendPlay2DAmbientSound(player, GUIDMaelstrom); + GameMessages::Play2DAmbientSound ambientSound; + ambientSound.target = player->GetObjectID(); + ambientSound.audioGUID = GUIDMaelstrom; + ambientSound.SendToClient(player->GetSystemAddress()); GameMessages::SendNotifyClientObject(self->GetObjectID(), u"maelstromSkyOn", 0, 0, LWOOBJID_EMPTY, "", player->GetSystemAddress()); @@ -256,8 +260,15 @@ void ZoneAgProperty::BaseTimerDone(Entity* self, const std::string& timerName) { DestroySpawner(self->GetVar(SpiderScreamSpawner)); for (auto* player : Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::CHARACTER)) { - GameMessages::SendStop2DAmbientSound(player, true, GUIDMaelstrom); - GameMessages::SendPlay2DAmbientSound(player, GUIDPeaceful); + GameMessages::Stop2DAmbientSound stopAmbientSound; + stopAmbientSound.target = player->GetObjectID(); + stopAmbientSound.force = true; + stopAmbientSound.audioGUID = GUIDMaelstrom; + stopAmbientSound.SendToClient(player->GetSystemAddress()); + GameMessages::Play2DAmbientSound ambientSound; + ambientSound.target = player->GetObjectID(); + ambientSound.audioGUID = GUIDPeaceful; + ambientSound.SendToClient(player->GetSystemAddress()); } } else if (timerName == "ShowVendor") { GameMessages::SendNotifyClientObject(self->GetObjectID(), u"vendorOn", 0, 0, LWOOBJID_EMPTY, "", UNASSIGNED_SYSTEM_ADDRESS); diff --git a/dScripts/02_server/Map/Property/PropertyBankInteract.cpp b/dScripts/02_server/Map/Property/PropertyBankInteract.cpp index 50fea9a05..16ee02fd1 100644 --- a/dScripts/02_server/Map/Property/PropertyBankInteract.cpp +++ b/dScripts/02_server/Map/Property/PropertyBankInteract.cpp @@ -1,6 +1,7 @@ #include "PropertyBankInteract.h" #include "EntityManager.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "Amf3.h" #include "Entity.h" @@ -24,7 +25,11 @@ void PropertyBankInteract::OnUse(Entity* self, Entity* user) { args.Insert("state", "bank"); - GameMessages::SendUIMessageServerToSingleClient(user, user->GetSystemAddress(), "pushGameState", args); + GameMessages::UIMessageServerToSingleClient uiMessage; + uiMessage.target = user->GetObjectID(); + uiMessage.strMessageName = "pushGameState"; + uiMessage.args = std::move(args); + uiMessage.SendToClient(user->GetSystemAddress()); GameMessages::SendNotifyClientObject(self->GetObjectID(), u"OpenBank", 0, 0, LWOOBJID_EMPTY, "", user->GetSystemAddress()); @@ -37,7 +42,11 @@ void PropertyBankInteract::OnFireEventServerSide(Entity* self, Entity* sender, s amfArgs.Insert("visible", false); - GameMessages::SendUIMessageServerToSingleClient(sender, sender->GetSystemAddress(), "ToggleBank", amfArgs); + GameMessages::UIMessageServerToSingleClient uiMessage; + uiMessage.target = sender->GetObjectID(); + uiMessage.strMessageName = "ToggleBank"; + uiMessage.args = std::move(amfArgs); + uiMessage.SendToClient(sender->GetSystemAddress()); GameMessages::SendNotifyClientObject(self->GetObjectID(), u"CloseBank", 0, 0, LWOOBJID_EMPTY, "", sender->GetSystemAddress()); diff --git a/dScripts/02_server/Map/njhub/CatapultBaseServer.cpp b/dScripts/02_server/Map/njhub/CatapultBaseServer.cpp index 45b6f99af..033da0e86 100644 --- a/dScripts/02_server/Map/njhub/CatapultBaseServer.cpp +++ b/dScripts/02_server/Map/njhub/CatapultBaseServer.cpp @@ -1,6 +1,7 @@ #include "CatapultBaseServer.h" #include "PetMessages.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "EntityManager.h" #include "Entity.h" #include "RenderComponent.h" @@ -28,7 +29,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) { RenderComponent::PlayAnimation(obj, u"idle-platform"); - GameMessages::SendPlayNDAudioEmitter(obj, UNASSIGNED_SYSTEM_ADDRESS, "{8cccf912-69e3-4041-a20b-63e4afafc993}"); + GameMessages::PlayNDAudioEmitter(obj->GetObjectID(), "{8cccf912-69e3-4041-a20b-63e4afafc993}").Send(UNASSIGNED_SYSTEM_ADDRESS); // set the art so we can use it again self->SetVar(u"Arm", obj->GetObjectID()); break; diff --git a/dScripts/02_server/Map/njhub/FallingTile.cpp b/dScripts/02_server/Map/njhub/FallingTile.cpp index 7804c8bcb..fe99e09cf 100644 --- a/dScripts/02_server/Map/njhub/FallingTile.cpp +++ b/dScripts/02_server/Map/njhub/FallingTile.cpp @@ -1,6 +1,7 @@ #include "FallingTile.h" #include "MovingPlatformComponent.h" #include "GameMessages.h" +#include "EffectsMessages.h" void FallingTile::OnStartup(Entity* self) { auto* movingPlatfromComponent = self->GetComponent(); @@ -44,12 +45,12 @@ void FallingTile::OnTimerDone(Entity* self, std::string timerName) { movingPlatfromComponent->GotoWaypoint(1); - GameMessages::SendPlayFXEffect(self->GetObjectID(), -1, u"down", "down"); + GameMessages::PlayFXEffect(self->GetObjectID(), -1, u"down", "down").Send(UNASSIGNED_SYSTEM_ADDRESS); } else if (timerName == "flipBack") { self->SetVar(u"AboutToFall", false); movingPlatfromComponent->GotoWaypoint(0); - GameMessages::SendPlayFXEffect(self->GetObjectID(), -1, u"up", "up"); + GameMessages::PlayFXEffect(self->GetObjectID(), -1, u"up", "up").Send(UNASSIGNED_SYSTEM_ADDRESS); } } diff --git a/dScripts/02_server/Map/njhub/NjGarmadonCelebration.cpp b/dScripts/02_server/Map/njhub/NjGarmadonCelebration.cpp index d3e54be13..a61a7fba0 100644 --- a/dScripts/02_server/Map/njhub/NjGarmadonCelebration.cpp +++ b/dScripts/02_server/Map/njhub/NjGarmadonCelebration.cpp @@ -1,6 +1,7 @@ #include "NjGarmadonCelebration.h" #include "Character.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "ePlayerFlag.h" void NjGarmadonCelebration::OnCollisionPhantom(Entity* self, Entity* target) { @@ -13,6 +14,9 @@ void NjGarmadonCelebration::OnCollisionPhantom(Entity* self, Entity* target) { if (!character->GetPlayerFlag(ePlayerFlag::NJ_GARMADON_CINEMATIC_SEEN)) { character->SetPlayerFlag(ePlayerFlag::NJ_GARMADON_CINEMATIC_SEEN, true); - GameMessages::SendStartCelebrationEffect(target, target->GetSystemAddress(), GarmadonCelebrationID); + GameMessages::StartCelebrationEffect celebration; + celebration.target = target->GetObjectID(); + celebration.celebrationID = GarmadonCelebrationID; + celebration.SendToClient(target->GetSystemAddress()); } } diff --git a/dScripts/02_server/Map/njhub/NjWuNPC.cpp b/dScripts/02_server/Map/njhub/NjWuNPC.cpp index 1a5d30fd6..53658aa4a 100644 --- a/dScripts/02_server/Map/njhub/NjWuNPC.cpp +++ b/dScripts/02_server/Map/njhub/NjWuNPC.cpp @@ -3,6 +3,7 @@ #include "Character.h" #include "EntityManager.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "eMissionState.h" #include "ePlayerFlag.h" @@ -54,7 +55,7 @@ void NjWuNPC::OnMissionDialogueOK(Entity* self, Entity* target, int missionID, e // Stop the dragon effects for (auto* dragon : Game::entityManager->GetEntitiesInGroup(m_DragonStatueGroup)) { - GameMessages::SendStopFXEffect(dragon, true, "on"); + GameMessages::StopFXEffect(dragon->GetObjectID(), true, "on").Send(UNASSIGNED_SYSTEM_ADDRESS); } }); } diff --git a/dScripts/02_server/Map/njhub/RainOfArrows.cpp b/dScripts/02_server/Map/njhub/RainOfArrows.cpp index 2fc73eb61..65a01b65c 100644 --- a/dScripts/02_server/Map/njhub/RainOfArrows.cpp +++ b/dScripts/02_server/Map/njhub/RainOfArrows.cpp @@ -3,6 +3,7 @@ #include "SkillComponent.h" #include "EntityInfo.h" #include "GameMessages.h" +#include "EffectsMessages.h" void RainOfArrows::OnStartup(Entity* self) { @@ -60,7 +61,7 @@ void RainOfArrows::OnTimerDone(Entity* self, std::string timerName) { self->AddTimer("FireSkill", 0.7f); } else if (timerName == "PlayArrowSound") { - GameMessages::SendPlayNDAudioEmitter(self, UNASSIGNED_SYSTEM_ADDRESS, m_ArrowsGUID); + GameMessages::PlayNDAudioEmitter(self->GetObjectID(), m_ArrowsGUID).Send(UNASSIGNED_SYSTEM_ADDRESS); } else if (timerName == "FireSkill") { if (child != nullptr) { child->Smash(); diff --git a/dScripts/02_server/Map/njhub/boss_instance/NjMonastryBossInstance.cpp b/dScripts/02_server/Map/njhub/boss_instance/NjMonastryBossInstance.cpp index be47b53b3..9e20078ff 100644 --- a/dScripts/02_server/Map/njhub/boss_instance/NjMonastryBossInstance.cpp +++ b/dScripts/02_server/Map/njhub/boss_instance/NjMonastryBossInstance.cpp @@ -4,6 +4,7 @@ #include "EntityManager.h" #include "dZoneManager.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "BaseCombatAIComponent.h" #include "BuffComponent.h" #include "SkillComponent.h" @@ -265,7 +266,7 @@ void NjMonastryBossInstance::HandleCounterWeightSpawned(Entity* self, Entity* co } RenderComponent::PlayAnimation(frakjaw, StunnedAnimation); - GameMessages::SendPlayNDAudioEmitter(frakjaw, UNASSIGNED_SYSTEM_ADDRESS, CounterSmashAudio); + GameMessages::PlayNDAudioEmitter(frakjaw->GetObjectID(), CounterSmashAudio).Send(UNASSIGNED_SYSTEM_ADDRESS); // Before wave 4 we should lower frakjaw from the ledge if (self->GetVar(WaveNumberVariable) == 3) { diff --git a/dScripts/BaseConsoleTeleportServer.cpp b/dScripts/BaseConsoleTeleportServer.cpp index 7392f7590..896cc24a7 100644 --- a/dScripts/BaseConsoleTeleportServer.cpp +++ b/dScripts/BaseConsoleTeleportServer.cpp @@ -1,5 +1,6 @@ #include "BaseConsoleTeleportServer.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "CharacterComponent.h" #include "RenderComponent.h" #include "EntityManager.h" @@ -11,7 +12,15 @@ void BaseConsoleTeleportServer::BaseOnUse(Entity* self, Entity* user) { const auto& teleportLocString = self->GetVar(u"teleportString"); - GameMessages::SendDisplayMessageBox(player->GetObjectID(), true, self->GetObjectID(), u"TransferBox", 0, teleportLocString, u"", player->GetSystemAddress()); + GameMessages::DisplayMessageBox messageBox; + messageBox.target = player->GetObjectID(); + messageBox.bShow = true; + messageBox.callbackClient = self->GetObjectID(); + messageBox.identifier = u"TransferBox"; + messageBox.imageID = 0; + messageBox.text = teleportLocString; + messageBox.userData = u""; + messageBox.Send(player->GetSystemAddress()); } void BaseConsoleTeleportServer::BaseOnMessageBoxResponse(Entity* self, Entity* sender, int32_t button, const std::u16string& identifier, const std::u16string& userData) { @@ -30,7 +39,7 @@ void BaseConsoleTeleportServer::BaseOnMessageBoxResponse(Entity* self, Entity* s const auto& teleportFXs = self->GetVar>(u"teleportEffectTypes"); for (const auto& type : teleportFXs) { - GameMessages::SendPlayFXEffect(player->GetObjectID(), teleportFXID, type, "FX" + GeneralUtils::UTF16ToWTF8(type)); + GameMessages::PlayFXEffect(player->GetObjectID(), teleportFXID, type, "FX" + GeneralUtils::UTF16ToWTF8(type)).Send(UNASSIGNED_SYSTEM_ADDRESS); } } diff --git a/dScripts/BasePropertyServer.cpp b/dScripts/BasePropertyServer.cpp index 69b839f3c..ddd5bdda2 100644 --- a/dScripts/BasePropertyServer.cpp +++ b/dScripts/BasePropertyServer.cpp @@ -1,5 +1,6 @@ #include "BasePropertyServer.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "EntityManager.h" #include "dZoneManager.h" #include "Character.h" @@ -106,8 +107,15 @@ void BasePropertyServer::BasePlayerLoaded(Entity* self, Entity* player) { } } - GameMessages::SendStop2DAmbientSound(player, true, GUIDMaelstrom); - GameMessages::SendPlay2DAmbientSound(player, GUIDPeaceful); + GameMessages::Stop2DAmbientSound stopAmbientSound; + stopAmbientSound.target = player->GetObjectID(); + stopAmbientSound.force = true; + stopAmbientSound.audioGUID = GUIDMaelstrom; + stopAmbientSound.SendToClient(player->GetSystemAddress()); + GameMessages::Play2DAmbientSound ambientSound; + ambientSound.target = player->GetObjectID(); + ambientSound.audioGUID = GUIDPeaceful; + ambientSound.SendToClient(player->GetSystemAddress()); self->AddTimer(TurnSkyOffTimer, 1.5f); @@ -116,7 +124,7 @@ void BasePropertyServer::BasePlayerLoaded(Entity* self, Entity* player) { self->AddTimer(KillFXObjectTimer, 1.0f); } - GameMessages::SendPlay2DAmbientSound(player, GUIDPeaceful); + ambientSound.SendToClient(player->GetSystemAddress()); // activate property safe spawner network ActivateSpawner(self->GetVar(PropObjsSpawner)); @@ -138,10 +146,20 @@ void BasePropertyServer::BasePlayerLoaded(Entity* self, Entity* player) { if (!flagMsg.flag) { StartMaelstrom(self, player); SpawnSpots(self); - GameMessages::SendPlay2DAmbientSound(player, GUIDMaelstrom); + GameMessages::Play2DAmbientSound ambientSound; + ambientSound.target = player->GetObjectID(); + ambientSound.audioGUID = GUIDMaelstrom; + ambientSound.SendToClient(player->GetSystemAddress()); } else { - GameMessages::SendStop2DAmbientSound(player, true, GUIDMaelstrom); - GameMessages::SendPlay2DAmbientSound(player, GUIDPeaceful); + GameMessages::Stop2DAmbientSound stopAmbientSound; + stopAmbientSound.target = player->GetObjectID(); + stopAmbientSound.force = true; + stopAmbientSound.audioGUID = GUIDMaelstrom; + stopAmbientSound.SendToClient(player->GetSystemAddress()); + GameMessages::Play2DAmbientSound ambientSound; + ambientSound.target = player->GetObjectID(); + ambientSound.audioGUID = GUIDPeaceful; + ambientSound.SendToClient(player->GetSystemAddress()); self->AddTimer(TurnSkyOffTimer, 1.5f); self->AddTimer(KillFXObjectTimer, 1.0f); @@ -385,8 +403,15 @@ void BasePropertyServer::BaseTimerDone(Entity* self, const std::string& timerNam if (player == nullptr) return; - GameMessages::SendStop2DAmbientSound(player, true, GUIDMaelstrom); - GameMessages::SendPlay2DAmbientSound(player, GUIDPeaceful); + GameMessages::Stop2DAmbientSound stopAmbientSound; + stopAmbientSound.target = player->GetObjectID(); + stopAmbientSound.force = true; + stopAmbientSound.audioGUID = GUIDMaelstrom; + stopAmbientSound.SendToClient(player->GetSystemAddress()); + GameMessages::Play2DAmbientSound ambientSound; + ambientSound.target = player->GetObjectID(); + ambientSound.audioGUID = GUIDPeaceful; + ambientSound.SendToClient(player->GetSystemAddress()); self->AddTimer(ShowVendorTimer, 5.0f); } else if (timerName == KillMarkerTimer) { diff --git a/dScripts/BaseSurvivalServer.cpp b/dScripts/BaseSurvivalServer.cpp index d82c1499d..2a41b6e98 100644 --- a/dScripts/BaseSurvivalServer.cpp +++ b/dScripts/BaseSurvivalServer.cpp @@ -1,5 +1,6 @@ #include "BaseSurvivalServer.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "ActivityMessages.h" #include "DestroyableComponent.h" #include "EntityManager.h" @@ -219,7 +220,7 @@ void BaseSurvivalServer::OnActivityTimerDone(Entity* self, const std::string& na for (const auto& playerID : state.players) { auto* player = Game::entityManager->GetEntity(playerID); if (player != nullptr) { - GameMessages::SendPlayNDAudioEmitter(player, player->GetSystemAddress(), spawnSoundGUID); + GameMessages::PlayNDAudioEmitter(player->GetObjectID(), spawnSoundGUID).Send(UNASSIGNED_SYSTEM_ADDRESS); } } } diff --git a/dScripts/BaseWavesServer.cpp b/dScripts/BaseWavesServer.cpp index b92987e86..5c287e1bd 100644 --- a/dScripts/BaseWavesServer.cpp +++ b/dScripts/BaseWavesServer.cpp @@ -1,5 +1,6 @@ #include "BaseWavesServer.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "ActivityMessages.h" #include "DestroyableComponent.h" #include "EntityManager.h" @@ -198,7 +199,7 @@ void BaseWavesServer::OnActivityTimerDone(Entity* self, const std::string& name) for (const auto& playerID : state.players) { auto* player = Game::entityManager->GetEntity(playerID); if (player != nullptr) { - GameMessages::SendPlayNDAudioEmitter(player, player->GetSystemAddress(), spawnSoundGUID); + GameMessages::PlayNDAudioEmitter(player->GetObjectID(), spawnSoundGUID).Send(UNASSIGNED_SYSTEM_ADDRESS); } } } else if (name == NextWaveTickTimer) { diff --git a/dScripts/ChooseYourDestinationNsToNt.cpp b/dScripts/ChooseYourDestinationNsToNt.cpp index b736883c4..47a70578f 100644 --- a/dScripts/ChooseYourDestinationNsToNt.cpp +++ b/dScripts/ChooseYourDestinationNsToNt.cpp @@ -1,6 +1,7 @@ #include "ChooseYourDestinationNsToNt.h" #include "Character.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "eTerminateType.h" bool ChooseYourDestinationNsToNt::CheckChoice(Entity* self, Entity* player) { @@ -56,7 +57,15 @@ void ChooseYourDestinationNsToNt::BaseChoiceBoxRespond(Entity* self, Entity* sen self->SetVar(u"teleportString", strText); self->SetVar(u"transferZoneID", GeneralUtils::to_u16string(newMap.value())); - GameMessages::SendDisplayMessageBox(sender->GetObjectID(), true, self->GetObjectID(), u"TransferBox", 0, strText, u"", sender->GetSystemAddress()); + GameMessages::DisplayMessageBox messageBox; + messageBox.target = sender->GetObjectID(); + messageBox.bShow = true; + messageBox.callbackClient = self->GetObjectID(); + messageBox.identifier = u"TransferBox"; + messageBox.imageID = 0; + messageBox.text = strText; + messageBox.userData = u""; + messageBox.Send(sender->GetSystemAddress()); } else { GameMessages::SendTerminateInteraction(sender->GetObjectID(), eTerminateType::FROM_INTERACTION, self->GetObjectID()); } diff --git a/dScripts/NtFactionSpyServer.cpp b/dScripts/NtFactionSpyServer.cpp index 7414bb344..ab2f85a41 100644 --- a/dScripts/NtFactionSpyServer.cpp +++ b/dScripts/NtFactionSpyServer.cpp @@ -3,6 +3,7 @@ #include "ProximityMonitorComponent.h" #include "InventoryComponent.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "MissionComponent.h" #include "eMissionState.h" #include "eReplicaComponentType.h" @@ -41,8 +42,13 @@ void NtFactionSpyServer::OnProximityUpdate(Entity* self, Entity* entering, std:: self->SetVar(m_CinematicRootVariable, cinematicSplit.at(0)); } - GameMessages::SendPlayCinematic(entering->GetObjectID(), cinematic, entering->GetSystemAddress(), - true, true, true); + GameMessages::PlayCinematic playCinematic; + playCinematic.target = entering->GetObjectID(); + playCinematic.pathName = cinematic; + playCinematic.allowGhostUpdates = true; + playCinematic.bCloseMultiInteract = true; + playCinematic.bSendServerNotify = true; + playCinematic.Send(entering->GetSystemAddress()); } } } diff --git a/dScripts/SpawnPetBaseServer.cpp b/dScripts/SpawnPetBaseServer.cpp index 04a24ae68..345727e43 100644 --- a/dScripts/SpawnPetBaseServer.cpp +++ b/dScripts/SpawnPetBaseServer.cpp @@ -1,5 +1,6 @@ #include "SpawnPetBaseServer.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "EntityManager.h" #include "PetComponent.h" #include "EntityInfo.h" @@ -39,7 +40,10 @@ void SpawnPetBaseServer::OnUse(Entity* self, Entity* user) { auto spawnCinematic = self->GetVar(u"spawnCinematic"); if (!spawnCinematic.empty()) { - GameMessages::SendPlayCinematic(user->GetObjectID(), spawnCinematic, UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::PlayCinematic cinematic; + cinematic.target = user->GetObjectID(); + cinematic.pathName = spawnCinematic; + cinematic.Send(UNASSIGNED_SYSTEM_ADDRESS); } GameMessages::SendTerminateInteraction(user->GetObjectID(), eTerminateType::FROM_INTERACTION, self->GetObjectID()); diff --git a/dScripts/ai/ACT/ActMine.cpp b/dScripts/ai/ACT/ActMine.cpp index 24863e508..18aa4e25e 100644 --- a/dScripts/ai/ACT/ActMine.cpp +++ b/dScripts/ai/ACT/ActMine.cpp @@ -2,6 +2,7 @@ #include "SkillComponent.h" #include "DestroyableComponent.h" #include "QuickBuildComponent.h" +#include "EffectsMessages.h" void ActMine::OnStartup(Entity* self) { self->SetVar(u"QuickBuildComplete", false); @@ -27,7 +28,7 @@ void ActMine::OnProximityUpdate(Entity* self, Entity* entering, std::string name auto* detroyable = self->GetComponent(); if (!detroyable) return; if (status == "ENTER" && self->GetVar(u"QuickBuildComplete") == true && detroyable->IsEnemy(entering)) { - GameMessages::SendPlayFXEffect(self->GetObjectID(), 242, u"orange", "sirenlight_B"); + GameMessages::PlayFXEffect(self->GetObjectID(), 242, u"orange", "sirenlight_B").Send(UNASSIGNED_SYSTEM_ADDRESS); self->AddTimer("Tick", TICK_TIME); } } @@ -40,7 +41,7 @@ void ActMine::OnTimerDone(Entity* self, std::string timerName) { skill->CalculateBehavior(SKILL_ID, BEHAVIOR_ID, LWOOBJID_EMPTY); self->AddTimer("BlowedUp", BLOWED_UP_TIME); } else { - GameMessages::SendPlayFXEffect(self->GetObjectID(), 242, u"orange", "sirenlight_B"); + GameMessages::PlayFXEffect(self->GetObjectID(), 242, u"orange", "sirenlight_B").Send(UNASSIGNED_SYSTEM_ADDRESS); self->AddTimer("Tick", TICK_TIME); self->SetVar(u"NumWarnings", self->GetVar(u"NumWarnings") + 1); } diff --git a/dScripts/ai/AG/AgBusDoor.cpp b/dScripts/ai/AG/AgBusDoor.cpp index a4106aaf5..e74e8af88 100644 --- a/dScripts/ai/AG/AgBusDoor.cpp +++ b/dScripts/ai/AG/AgBusDoor.cpp @@ -1,6 +1,7 @@ #include "AgBusDoor.h" #include "Entity.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "ProximityMonitorComponent.h" void AgBusDoor::OnStartup(Entity* self) { @@ -55,11 +56,11 @@ void AgBusDoor::MoveDoor(Entity* self, bool bOpen) { } //This is currently commented out because it might be the reason that people's audio is cutting out. - GameMessages::SendPlayNDAudioEmitter(self, UNASSIGNED_SYSTEM_ADDRESS, "{9a24f1fa-3177-4745-a2df-fbd996d6e1e3}"); + GameMessages::PlayNDAudioEmitter(self->GetObjectID(), "{9a24f1fa-3177-4745-a2df-fbd996d6e1e3}").Send(UNASSIGNED_SYSTEM_ADDRESS); } void AgBusDoor::OnTimerDone(Entity* self, std::string timerName) { if (timerName == "dustTimer") { - GameMessages::SendPlayFXEffect(self->GetObjectID(), 642, u"create", "busDust", LWOOBJID_EMPTY, 1.0f, 1.0f, true); + GameMessages::PlayFXEffect(self->GetObjectID(), 642, u"create", "busDust").Send(UNASSIGNED_SYSTEM_ADDRESS); } } diff --git a/dScripts/ai/AG/AgJetEffectServer.cpp b/dScripts/ai/AG/AgJetEffectServer.cpp index 69e94c8f8..0344a2f49 100644 --- a/dScripts/ai/AG/AgJetEffectServer.cpp +++ b/dScripts/ai/AG/AgJetEffectServer.cpp @@ -1,5 +1,6 @@ #include "AgJetEffectServer.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "EntityManager.h" #include "SkillComponent.h" #include "eReplicaComponentType.h" @@ -14,7 +15,7 @@ void AgJetEffectServer::OnUse(Entity* self, Entity* user) { auto entities = Game::entityManager->GetEntitiesInGroup("Jet_FX"); if (entities.empty()) return; - GameMessages::SendPlayFXEffect(entities.at(0), 641, u"create", "radarDish", LWOOBJID_EMPTY, 1, 1, true); + GameMessages::PlayFXEffect(entities.at(0)->GetObjectID(), 641, u"create", "radarDish").Send(UNASSIGNED_SYSTEM_ADDRESS); self->AddTimer("radarDish", 2.0f); self->AddTimer("PlayEffect", 2.5f); self->AddTimer("CineDone", 7.5f + 5.0f); // 7.5f is time the cinematic takes to play @@ -38,7 +39,7 @@ void AgJetEffectServer::OnQuickBuildComplete(Entity* self, Entity* target) { void AgJetEffectServer::OnTimerDone(Entity* self, std::string timerName) { if (timerName == "radarDish") { - GameMessages::SendStopFXEffect(self, true, "radarDish"); + GameMessages::StopFXEffect(self->GetObjectID(), true, "radarDish").Send(UNASSIGNED_SYSTEM_ADDRESS); } else if (timerName == "PlayEffect") { auto entities = Game::entityManager->GetEntitiesInGroup("mortarMain"); if (entities.empty()) return; diff --git a/dScripts/ai/AG/AgShipPlayerShockServer.cpp b/dScripts/ai/AG/AgShipPlayerShockServer.cpp index e14d48ae7..c274a535d 100644 --- a/dScripts/ai/AG/AgShipPlayerShockServer.cpp +++ b/dScripts/ai/AG/AgShipPlayerShockServer.cpp @@ -1,5 +1,6 @@ #include "AgShipPlayerShockServer.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "RenderComponent.h" #include "Entity.h" #include "eTerminateType.h" @@ -13,11 +14,11 @@ void AgShipPlayerShockServer::OnUse(Entity* self, Entity* user) { 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); + GameMessages::PlayFXEffect(self->GetObjectID(), 1430, u"create", "console_sparks").Send(UNASSIGNED_SYSTEM_ADDRESS); self->AddTimer("FXTime", fxTime); } void AgShipPlayerShockServer::OnTimerDone(Entity* self, std::string timerName) { - GameMessages::SendStopFXEffect(self, true, "console_sparks"); + GameMessages::StopFXEffect(self->GetObjectID(), true, "console_sparks").Send(UNASSIGNED_SYSTEM_ADDRESS); active = false; } diff --git a/dScripts/ai/AG/AgShipShake.cpp b/dScripts/ai/AG/AgShipShake.cpp index 7dd2323a7..0df1a9f65 100644 --- a/dScripts/ai/AG/AgShipShake.cpp +++ b/dScripts/ai/AG/AgShipShake.cpp @@ -2,6 +2,7 @@ #include "EntityInfo.h" #include "GeneralUtils.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "EntityManager.h" #include "RenderComponent.h" #include "Entity.h" @@ -39,18 +40,24 @@ void AgShipShake::OnTimerDone(Entity* self, std::string timerName) { self->AddTimer("ShipShakeIdle", static_cast(time)); - if (ref) - GameMessages::SendPlayEmbeddedEffectOnAllClientsNearObject(ref, FXName, ref->GetObjectID(), 500.0f); + if (ref) { + GameMessages::PlayEmbeddedEffectOnAllClientsNearObject embeddedEffect; + embeddedEffect.target = ref->GetObjectID(); + embeddedEffect.effectName = FXName; + embeddedEffect.fromObjectID = ref->GetObjectID(); + embeddedEffect.radius = 500.0f; + embeddedEffect.Send(UNASSIGNED_SYSTEM_ADDRESS); + } if (debrisObject) - GameMessages::SendPlayFXEffect(debrisObject, -1, u"DebrisFall", "Debris", LWOOBJID_EMPTY, 1.0f, 1.0f, true); + GameMessages::PlayFXEffect(debrisObject->GetObjectID(), -1, u"DebrisFall", "Debris").Send(UNASSIGNED_SYSTEM_ADDRESS); const auto randomFx = GeneralUtils::GenerateRandomNumber(0, 3); if (shipFxObject) { std::string effectType = "shipboom" + std::to_string(randomFx); - GameMessages::SendPlayFXEffect(shipFxObject, 559, GeneralUtils::ASCIIToUTF16(effectType), "FX", LWOOBJID_EMPTY, 1.0f, 1.0f, true); + GameMessages::PlayFXEffect(shipFxObject->GetObjectID(), 559, GeneralUtils::ASCIIToUTF16(effectType), "FX").Send(UNASSIGNED_SYSTEM_ADDRESS); } self->AddTimer("ShipShakeExplode", 5.0f); diff --git a/dScripts/ai/AG/AgSpiderBossMessage.cpp b/dScripts/ai/AG/AgSpiderBossMessage.cpp index 495225b7f..a9a7ce0c5 100644 --- a/dScripts/ai/AG/AgSpiderBossMessage.cpp +++ b/dScripts/ai/AG/AgSpiderBossMessage.cpp @@ -2,6 +2,7 @@ #include "Entity.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "RenderComponent.h" @@ -38,7 +39,7 @@ void AgSpiderBossMessage::OnCollisionPhantom(Entity* self, Entity* target) { // knockback the target auto forward = QuatUtils::Forward(self->GetRotation()); box.boxTarget = target->GetObjectID(); - GameMessages::SendPlayFXEffect(target->GetObjectID(), 1378, u"create", "pushBack"); + GameMessages::PlayFXEffect(target->GetObjectID(), 1378, u"create", "pushBack").Send(UNASSIGNED_SYSTEM_ADDRESS); RenderComponent::PlayAnimation(target, "knockback-recovery"); forward.y += 15; forward.x *= 100; diff --git a/dScripts/ai/FV/ActNinjaSensei.cpp b/dScripts/ai/FV/ActNinjaSensei.cpp index 6a7dc8938..93c064bd9 100644 --- a/dScripts/ai/FV/ActNinjaSensei.cpp +++ b/dScripts/ai/FV/ActNinjaSensei.cpp @@ -2,6 +2,7 @@ #include "Entity.h" #include "EntityManager.h" #include "GameMessages.h" +#include "EffectsMessages.h" void ActNinjaSensei::OnStartup(Entity* self) { auto students = Game::entityManager->GetEntitiesInGroup(this->m_StudentGroup); @@ -19,54 +20,54 @@ void ActNinjaSensei::OnTimerDone(Entity* self, std::string timerName) { if (timerName == "crane") { for (auto student : students) { - if (student) GameMessages::SendPlayAnimation(student, u"crane"); + if (student) GameMessages::PlayAnimation(student->GetObjectID(), u"crane").Send(UNASSIGNED_SYSTEM_ADDRESS); } - GameMessages::SendPlayAnimation(self, u"crane"); + GameMessages::PlayAnimation(self->GetObjectID(), u"crane").Send(UNASSIGNED_SYSTEM_ADDRESS); self->AddTimer("bow", 15.33); } if (timerName == "bow") { - GameMessages::SendPlayAnimation(self, u"bow"); + GameMessages::PlayAnimation(self->GetObjectID(), u"bow").Send(UNASSIGNED_SYSTEM_ADDRESS); for (auto student : students) { - if (student) GameMessages::SendPlayAnimation(student, u"bow"); + if (student) GameMessages::PlayAnimation(student->GetObjectID(), u"bow").Send(UNASSIGNED_SYSTEM_ADDRESS); } - GameMessages::SendPlayAnimation(self, u"bow"); + GameMessages::PlayAnimation(self->GetObjectID(), u"bow").Send(UNASSIGNED_SYSTEM_ADDRESS); self->AddTimer("tiger", 5); } if (timerName == "tiger") { - GameMessages::SendPlayAnimation(self, u"tiger"); + GameMessages::PlayAnimation(self->GetObjectID(), u"tiger").Send(UNASSIGNED_SYSTEM_ADDRESS); for (auto student : students) { - if (student) GameMessages::SendPlayAnimation(student, u"tiger"); + if (student) GameMessages::PlayAnimation(student->GetObjectID(), u"tiger").Send(UNASSIGNED_SYSTEM_ADDRESS); } - GameMessages::SendPlayAnimation(self, u"tiger"); + GameMessages::PlayAnimation(self->GetObjectID(), u"tiger").Send(UNASSIGNED_SYSTEM_ADDRESS); self->AddTimer("bow2", 15.33); } if (timerName == "bow2") { - GameMessages::SendPlayAnimation(self, u"bow"); + GameMessages::PlayAnimation(self->GetObjectID(), u"bow").Send(UNASSIGNED_SYSTEM_ADDRESS); for (auto student : students) { - if (student) GameMessages::SendPlayAnimation(student, u"bow"); + if (student) GameMessages::PlayAnimation(student->GetObjectID(), u"bow").Send(UNASSIGNED_SYSTEM_ADDRESS); } - GameMessages::SendPlayAnimation(self, u"bow"); + GameMessages::PlayAnimation(self->GetObjectID(), u"bow").Send(UNASSIGNED_SYSTEM_ADDRESS); self->AddTimer("mantis", 5); } if (timerName == "mantis") { - GameMessages::SendPlayAnimation(self, u"mantis"); + GameMessages::PlayAnimation(self->GetObjectID(), u"mantis").Send(UNASSIGNED_SYSTEM_ADDRESS); for (auto student : students) { - if (student) GameMessages::SendPlayAnimation(student, u"mantis"); + if (student) GameMessages::PlayAnimation(student->GetObjectID(), u"mantis").Send(UNASSIGNED_SYSTEM_ADDRESS); } - GameMessages::SendPlayAnimation(self, u"mantis"); + GameMessages::PlayAnimation(self->GetObjectID(), u"mantis").Send(UNASSIGNED_SYSTEM_ADDRESS); self->AddTimer("bow3", 15.3); } if (timerName == "bow3") { - GameMessages::SendPlayAnimation(self, u"bow"); + GameMessages::PlayAnimation(self->GetObjectID(), u"bow").Send(UNASSIGNED_SYSTEM_ADDRESS); for (auto student : students) { - if (student) GameMessages::SendPlayAnimation(student, u"bow"); + if (student) GameMessages::PlayAnimation(student->GetObjectID(), u"bow").Send(UNASSIGNED_SYSTEM_ADDRESS); } - GameMessages::SendPlayAnimation(self, u"bow"); + GameMessages::PlayAnimation(self->GetObjectID(), u"bow").Send(UNASSIGNED_SYSTEM_ADDRESS); self->AddTimer("repeat", 5); } diff --git a/dScripts/ai/FV/ActParadoxPipeFix.cpp b/dScripts/ai/FV/ActParadoxPipeFix.cpp index 7e6451f96..5632454e2 100644 --- a/dScripts/ai/FV/ActParadoxPipeFix.cpp +++ b/dScripts/ai/FV/ActParadoxPipeFix.cpp @@ -2,6 +2,7 @@ #include "EntityManager.h" #include "QuickBuildComponent.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "MissionComponent.h" #include "eEndBehavior.h" @@ -30,7 +31,7 @@ void ActParadoxPipeFix::OnQuickBuildComplete(Entity* self, Entity* target) { const auto refinery = Game::entityManager->GetEntitiesInGroup("Paradox"); if (!refinery.empty()) { - GameMessages::SendPlayFXEffect(refinery[0]->GetObjectID(), 3999, u"create", "pipeFX"); + GameMessages::PlayFXEffect(refinery[0]->GetObjectID(), 3999, u"create", "pipeFX").Send(UNASSIGNED_SYSTEM_ADDRESS); } for (auto* object : groupObjs) { @@ -43,7 +44,17 @@ void ActParadoxPipeFix::OnQuickBuildComplete(Entity* self, Entity* target) { missionComponent->ForceProgressTaskType(769, 1, 1, false); } - GameMessages::SendPlayCinematic(player->GetObjectID(), u"ParadoxPipeFinish", player->GetSystemAddress(), true, true, false, false, eEndBehavior::RETURN, false, 2.0f); + GameMessages::PlayCinematic cinematic; + cinematic.target = player->GetObjectID(); + cinematic.pathName = u"ParadoxPipeFinish"; + cinematic.allowGhostUpdates = true; + cinematic.bCloseMultiInteract = true; + cinematic.bSendServerNotify = false; + cinematic.bUseControlledObjectForAudioListener = false; + cinematic.endBehavior = eEndBehavior::RETURN; + cinematic.hidePlayerDuringCine = false; + cinematic.leadIn = 2.0f; + cinematic.Send(player->GetSystemAddress()); } object->SetVar(u"PlayerID", LWOOBJID_EMPTY); @@ -56,7 +67,7 @@ void ActParadoxPipeFix::OnQuickBuildNotifyState(Entity* self, eQuickBuildState s const auto refinery = Game::entityManager->GetEntitiesInGroup("Paradox"); if (!refinery.empty()) { - GameMessages::SendStopFXEffect(refinery[0], true, "pipeFX"); + GameMessages::StopFXEffect(refinery[0]->GetObjectID(), true, "pipeFX").Send(UNASSIGNED_SYSTEM_ADDRESS); } } } diff --git a/dScripts/ai/FV/FvFacilityBrick.cpp b/dScripts/ai/FV/FvFacilityBrick.cpp index 1402991c4..10815de92 100644 --- a/dScripts/ai/FV/FvFacilityBrick.cpp +++ b/dScripts/ai/FV/FvFacilityBrick.cpp @@ -1,5 +1,6 @@ #include "FvFacilityBrick.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "dZoneManager.h" #include "EntityManager.h" @@ -17,43 +18,43 @@ void FvFacilityBrick::OnNotifyObject(Entity* self, Entity* sender, const std::st auto* const canisterSpawner = canisterObjs.empty() ? nullptr : canisterObjs[0]; if (name == "ConsoleLeftUp") { - GameMessages::SendStopFXEffect(self, true, "LeftPipeOff"); - GameMessages::SendPlayFXEffect(self->GetObjectID(), 2775, u"create", "LeftPipeEnergy"); + GameMessages::StopFXEffect(self->GetObjectID(), true, "LeftPipeOff").Send(UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::PlayFXEffect(self->GetObjectID(), 2775, u"create", "LeftPipeEnergy").Send(UNASSIGNED_SYSTEM_ADDRESS); } else if (name == "ConsoleLeftDown") { self->SetVar(u"ConsoleLEFTActive", false); - GameMessages::SendStopFXEffect(self, true, "LeftPipeEnergy"); - GameMessages::SendStopFXEffect(self, true, "LeftPipeOn"); - GameMessages::SendPlayFXEffect(self->GetObjectID(), 2774, u"create", "LeftPipeOff"); + GameMessages::StopFXEffect(self->GetObjectID(), true, "LeftPipeEnergy").Send(UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::StopFXEffect(self->GetObjectID(), true, "LeftPipeOn").Send(UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::PlayFXEffect(self->GetObjectID(), 2774, u"create", "LeftPipeOff").Send(UNASSIGNED_SYSTEM_ADDRESS); } else if (name == "ConsoleLeftActive") { self->SetVar(u"ConsoleLEFTActive", true); - GameMessages::SendStopFXEffect(self, true, "LeftPipeEnergy"); - GameMessages::SendPlayFXEffect(self->GetObjectID(), 2776, u"create", "LeftPipeOn"); + GameMessages::StopFXEffect(self->GetObjectID(), true, "LeftPipeEnergy").Send(UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::PlayFXEffect(self->GetObjectID(), 2776, u"create", "LeftPipeOn").Send(UNASSIGNED_SYSTEM_ADDRESS); } else if (name == "ConsoleRightUp") { - GameMessages::SendStopFXEffect(self, true, "RightPipeOff"); - GameMessages::SendPlayFXEffect(self->GetObjectID(), 2778, u"create", "RightPipeEnergy"); + GameMessages::StopFXEffect(self->GetObjectID(), true, "RightPipeOff").Send(UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::PlayFXEffect(self->GetObjectID(), 2778, u"create", "RightPipeEnergy").Send(UNASSIGNED_SYSTEM_ADDRESS); } else if (name == "ConsoleRightDown") { self->SetVar(u"ConsoleRIGHTActive", false); - GameMessages::SendStopFXEffect(self, true, "RightPipeEnergy"); - GameMessages::SendStopFXEffect(self, true, "RightPipeOn"); - GameMessages::SendPlayFXEffect(self->GetObjectID(), 2777, u"create", "RightPipeOff"); + GameMessages::StopFXEffect(self->GetObjectID(), true, "RightPipeEnergy").Send(UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::StopFXEffect(self->GetObjectID(), true, "RightPipeOn").Send(UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::PlayFXEffect(self->GetObjectID(), 2777, u"create", "RightPipeOff").Send(UNASSIGNED_SYSTEM_ADDRESS); } else if (name == "ConsoleRightActive") { self->SetVar(u"ConsoleRIGHTActive", true); - GameMessages::SendStopFXEffect(self, true, "RightPipeOff"); - GameMessages::SendPlayFXEffect(self->GetObjectID(), 2779, u"create", "RightPipeEnergy"); + GameMessages::StopFXEffect(self->GetObjectID(), true, "RightPipeOff").Send(UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::PlayFXEffect(self->GetObjectID(), 2779, u"create", "RightPipeEnergy").Send(UNASSIGNED_SYSTEM_ADDRESS); } if (self->GetVar(u"ConsoleLEFTActive") && self->GetVar(u"ConsoleRIGHTActive")) { auto* object = Game::entityManager->GetEntitiesInGroup("Brick")[0]; if (object != nullptr) { - GameMessages::SendPlayFXEffect(object->GetObjectID(), 122, u"create", "bluebrick"); - GameMessages::SendPlayFXEffect(object->GetObjectID(), 1034, u"cast", "imaginationexplosion"); + GameMessages::PlayFXEffect(object->GetObjectID(), 122, u"create", "bluebrick").Send(UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::PlayFXEffect(object->GetObjectID(), 1034, u"cast", "imaginationexplosion").Send(UNASSIGNED_SYSTEM_ADDRESS); } object = Game::entityManager->GetEntitiesInGroup("Canister")[0]; @@ -70,7 +71,7 @@ void FvFacilityBrick::OnNotifyObject(Entity* self, Entity* sender, const std::st auto* object = Game::entityManager->GetEntitiesInGroup("Brick")[0]; if (object != nullptr) { - GameMessages::SendStopFXEffect(object, true, "bluebrick"); + GameMessages::StopFXEffect(object->GetObjectID(), true, "bluebrick").Send(UNASSIGNED_SYSTEM_ADDRESS); } if (bugSpawner) { @@ -101,8 +102,8 @@ void FvFacilityBrick::OnFireEventServerSide(Entity* self, Entity* sender, std::s return; } - GameMessages::SendPlayFXEffect(self->GetObjectID(), 2774, u"create", "LeftPipeOff"); - GameMessages::SendPlayFXEffect(self->GetObjectID(), 2777, u"create", "RightPipeOff"); - GameMessages::SendPlayFXEffect(self->GetObjectID(), 2750, u"create", "imagination_canister"); - GameMessages::SendPlayFXEffect(self->GetObjectID(), 2751, u"create", "canister_light_filler"); + GameMessages::PlayFXEffect(self->GetObjectID(), 2774, u"create", "LeftPipeOff").Send(UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::PlayFXEffect(self->GetObjectID(), 2777, u"create", "RightPipeOff").Send(UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::PlayFXEffect(self->GetObjectID(), 2750, u"create", "imagination_canister").Send(UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::PlayFXEffect(self->GetObjectID(), 2751, u"create", "canister_light_filler").Send(UNASSIGNED_SYSTEM_ADDRESS); } diff --git a/dScripts/ai/FV/FvFacilityPipes.cpp b/dScripts/ai/FV/FvFacilityPipes.cpp index dd35ffe1d..a01c4a8e2 100644 --- a/dScripts/ai/FV/FvFacilityPipes.cpp +++ b/dScripts/ai/FV/FvFacilityPipes.cpp @@ -1,10 +1,11 @@ #include "FvFacilityPipes.h" #include "GameMessages.h" +#include "EffectsMessages.h" void FvFacilityPipes::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2, int32_t param3) { if (args == "startFX") { - GameMessages::SendPlayFXEffect(self->GetObjectID(), m_LeftPipeEffectID, m_EffectType, m_LeftPipeEffectName); - GameMessages::SendPlayFXEffect(self->GetObjectID(), m_RightPipeEffectID, m_EffectType, m_RightPipeEffectName); - GameMessages::SendPlayFXEffect(self->GetObjectID(), m_ImaginationCanisterEffectID, m_EffectType, m_ImaginationCanisterEffectName); + GameMessages::PlayFXEffect(self->GetObjectID(), m_LeftPipeEffectID, m_EffectType, m_LeftPipeEffectName).Send(UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::PlayFXEffect(self->GetObjectID(), m_RightPipeEffectID, m_EffectType, m_RightPipeEffectName).Send(UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::PlayFXEffect(self->GetObjectID(), m_ImaginationCanisterEffectID, m_EffectType, m_ImaginationCanisterEffectName).Send(UNASSIGNED_SYSTEM_ADDRESS); } } diff --git a/dScripts/ai/GENERAL/ForceFieldEffect.cpp b/dScripts/ai/GENERAL/ForceFieldEffect.cpp index 62d0eeb82..71dd4409c 100644 --- a/dScripts/ai/GENERAL/ForceFieldEffect.cpp +++ b/dScripts/ai/GENERAL/ForceFieldEffect.cpp @@ -2,9 +2,10 @@ #include "Entity.h" #include "GameMessages.h" +#include "EffectsMessages.h" void ForceFieldEffect::OnCollisionPhantom(Entity* self, Entity* target) { if (!target) return; - GameMessages::SendPlayFXEffect(target, 3671, u"cast", "", LWOOBJID_EMPTY); + GameMessages::PlayFXEffect(target->GetObjectID(), 3671, u"cast", "").Send(UNASSIGNED_SYSTEM_ADDRESS); } diff --git a/dScripts/ai/GENERAL/InstanceExitTransferPlayerToLastNonInstance.cpp b/dScripts/ai/GENERAL/InstanceExitTransferPlayerToLastNonInstance.cpp index 667f41bd2..00792dcfd 100644 --- a/dScripts/ai/GENERAL/InstanceExitTransferPlayerToLastNonInstance.cpp +++ b/dScripts/ai/GENERAL/InstanceExitTransferPlayerToLastNonInstance.cpp @@ -1,5 +1,6 @@ #include "InstanceExitTransferPlayerToLastNonInstance.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "CharacterComponent.h" #include "Character.h" #include "dServer.h" @@ -10,16 +11,15 @@ void InstanceExitTransferPlayerToLastNonInstance::OnUse(Entity* self, Entity* us if (transferText.empty()) transferText = u"DRAGON_EXIT_QUESTION"; - GameMessages::SendDisplayMessageBox( - user->GetObjectID(), - true, - self->GetObjectID(), - u"Instance_Exit", - 1, - transferText, - u"", - user->GetSystemAddress() - ); + GameMessages::DisplayMessageBox messageBox; + messageBox.target = user->GetObjectID(); + messageBox.bShow = true; + messageBox.callbackClient = self->GetObjectID(); + messageBox.identifier = u"Instance_Exit"; + messageBox.imageID = 1; + messageBox.text = transferText; + messageBox.userData = u""; + messageBox.Send(user->GetSystemAddress()); } void InstanceExitTransferPlayerToLastNonInstance::OnMessageBoxResponse(Entity* self, Entity* sender, int32_t button, const std::u16string& identifier, const std::u16string& userData) { diff --git a/dScripts/ai/GF/GfOrgan.cpp b/dScripts/ai/GF/GfOrgan.cpp index 3184aa829..007e4c365 100644 --- a/dScripts/ai/GF/GfOrgan.cpp +++ b/dScripts/ai/GF/GfOrgan.cpp @@ -1,5 +1,6 @@ #include "GfOrgan.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "Entity.h" #include "RenderComponent.h" @@ -9,7 +10,7 @@ void GfOrgan::OnUse(Entity* self, Entity* user) { return; } - GameMessages::SendPlayNDAudioEmitter(self, UNASSIGNED_SYSTEM_ADDRESS, "{15d5f8bd-139a-4c31-8904-970c480cd70f}"); + GameMessages::PlayNDAudioEmitter(self->GetObjectID(), "{15d5f8bd-139a-4c31-8904-970c480cd70f}").Send(UNASSIGNED_SYSTEM_ADDRESS); self->SetBoolean(u"bIsInUse", true); self->AddTimer("reset", 5.0f); diff --git a/dScripts/ai/MINIGAME/SG_GF/SERVER/SGCannon.cpp b/dScripts/ai/MINIGAME/SG_GF/SERVER/SGCannon.cpp index e33b857a9..93a61eb93 100644 --- a/dScripts/ai/MINIGAME/SG_GF/SERVER/SGCannon.cpp +++ b/dScripts/ai/MINIGAME/SG_GF/SERVER/SGCannon.cpp @@ -1,6 +1,7 @@ #include "SGCannon.h" #include "EntityManager.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "ActivityMessages.h" #include "dZoneManager.h" #include "Character.h" @@ -132,10 +133,15 @@ void SGCannon::OnMessageBoxResponse(Entity* self, Entity* sender, int32_t button if (!player) return; if (identifier == u"Scoreboardinfo") { - GameMessages::SendDisplayMessageBox(player->GetObjectID(), true, - Game::zoneManager->GetZoneControlObject()->GetObjectID(), - u"Shooting_Gallery_Retry", 2, u"Retry?", - u"", player->GetSystemAddress()); + GameMessages::DisplayMessageBox messageBox; + messageBox.target = player->GetObjectID(); + messageBox.bShow = true; + messageBox.callbackClient = Game::zoneManager->GetZoneControlObject()->GetObjectID(); + messageBox.identifier = u"Shooting_Gallery_Retry"; + messageBox.imageID = 2; + messageBox.text = u"Retry?"; + messageBox.userData = u""; + messageBox.Send(player->GetSystemAddress()); } else { if ((button == 1 && (identifier == u"Shooting_Gallery_Retry" || identifier == u"RePlay")) || identifier == u"SG1" || button == 0) { if (IsPlayerInActivity(self, player->GetObjectID())) return; @@ -187,7 +193,7 @@ void SGCannon::SpawnWaveTimerFunc(Entity* self) { const auto* player = Game::entityManager->GetEntity(self->GetVar(PlayerIDVariable)); if (player != nullptr) { - GameMessages::SendPlayFXEffect(player->GetObjectID(), -1, u"SG-start", ""); + GameMessages::PlayFXEffect(player->GetObjectID(), -1, u"SG-start", "").Send(UNASSIGNED_SYSTEM_ADDRESS); GameMessages::StartActivityTime startActivityTime; startActivityTime.target = self->GetObjectID(); @@ -362,7 +368,7 @@ void SGCannon::StartGame(Entity* self) { activityStart.target = self->GetObjectID(); activityStart.Send(player->GetSystemAddress()); - GameMessages::SendPlayFXEffect(self->GetObjectID(), -1, u"start", ""); + GameMessages::PlayFXEffect(self->GetObjectID(), -1, u"start", "").Send(UNASSIGNED_SYSTEM_ADDRESS); self->SetNetworkVar(ClearVariable, true); DoGameStartup(self); diff --git a/dScripts/ai/NP/NpcNpJetpackGuy.cpp b/dScripts/ai/NP/NpcNpJetpackGuy.cpp index 0e772ad1b..582b7c53c 100644 --- a/dScripts/ai/NP/NpcNpJetpackGuy.cpp +++ b/dScripts/ai/NP/NpcNpJetpackGuy.cpp @@ -2,8 +2,9 @@ #include "Entity.h" #include "GameMessages.h" +#include "EffectsMessages.h" void NpcNpJetpackGuy::OnUse(Entity* self, Entity* user) { // No effect ID, the client plays the object's own effect of this type. - GameMessages::SendPlayFXEffect(self, -1, u"launch", "", LWOOBJID_EMPTY); + GameMessages::PlayFXEffect(self->GetObjectID(), -1, u"launch", "").Send(UNASSIGNED_SYSTEM_ADDRESS); } diff --git a/dScripts/ai/NS/NsConcertInstrument.cpp b/dScripts/ai/NS/NsConcertInstrument.cpp index d1b259183..3f910ef37 100644 --- a/dScripts/ai/NS/NsConcertInstrument.cpp +++ b/dScripts/ai/NS/NsConcertInstrument.cpp @@ -1,5 +1,6 @@ #include "NsConcertInstrument.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "Item.h" #include "DestroyableComponent.h" #include "EntityManager.h" @@ -121,7 +122,10 @@ void NsConcertInstrument::StartPlayingInstrument(Entity* self, Entity* player) { EquipInstruments(self, player); GameMessages::SendNotifyClientObject(self->GetObjectID(), u"startPlaying", 0, 0, player->GetObjectID(), "", UNASSIGNED_SYSTEM_ADDRESS); - GameMessages::SendPlayCinematic(player->GetObjectID(), cinematics.at(instrumentLot), UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::PlayCinematic cinematic; + cinematic.target = player->GetObjectID(); + cinematic.pathName = cinematics.at(instrumentLot); + cinematic.Send(UNASSIGNED_SYSTEM_ADDRESS); self->AddCallbackTimer(1.0f, [player, instrumentLot]() { RenderComponent::PlayAnimation(player, animations.at(instrumentLot), 2.0f); }); @@ -153,7 +157,11 @@ void NsConcertInstrument::StopPlayingInstrument(Entity* self, Entity* player) { missions->Progress(eMissionTaskType::SCRIPT, self->GetLOT()); } - GameMessages::SendEndCinematic(player->GetObjectID(), cinematics.at(instrumentLot), UNASSIGNED_SYSTEM_ADDRESS, 1.0f); + GameMessages::EndCinematic endCinematic; + endCinematic.target = player->GetObjectID(); + endCinematic.pathName = cinematics.at(instrumentLot); + endCinematic.leadOut = 1.0f; + endCinematic.Send(UNASSIGNED_SYSTEM_ADDRESS); 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/NsConcertQuickBuild.cpp b/dScripts/ai/NS/NsConcertQuickBuild.cpp index 2278eb5c2..3fb1d539b 100644 --- a/dScripts/ai/NS/NsConcertQuickBuild.cpp +++ b/dScripts/ai/NS/NsConcertQuickBuild.cpp @@ -3,6 +3,7 @@ #include "NsConcertChoiceBuildManager.h" #include "DestroyableComponent.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "MovingPlatformComponent.h" #include "MissionComponent.h" @@ -206,8 +207,7 @@ void NsConcertQuickBuild::UpdateEffects(Entity* self) { for (const auto& effectName : setIterator->second.effects) { const auto effectObjects = Game::entityManager->GetEntitiesInGroup(quickBuildFX.at(effectName)); for (auto* effectObject : effectObjects) { - GameMessages::SendPlayFXEffect(effectObject, 0, GeneralUtils::ASCIIToUTF16(effectName), - effectName + "Effect", LWOOBJID_EMPTY, 1, 1, true); + GameMessages::PlayFXEffect(effectObject->GetObjectID(), 0, GeneralUtils::ASCIIToUTF16(effectName), effectName + "Effect").Send(UNASSIGNED_SYSTEM_ADDRESS); } } } @@ -220,7 +220,7 @@ void NsConcertQuickBuild::CancelEffects(Entity* self) { for (const auto& effectName : setIterator->second.effects) { const auto effectObjects = Game::entityManager->GetEntitiesInGroup(quickBuildFX.at(effectName)); for (auto* effectObject : effectObjects) { - GameMessages::SendStopFXEffect(effectObject, true, effectName + "Effect"); + GameMessages::StopFXEffect(effectObject->GetObjectID(), true, effectName + "Effect").Send(UNASSIGNED_SYSTEM_ADDRESS); } } } diff --git a/dScripts/ai/NS/NsGetFactionMissionServer.cpp b/dScripts/ai/NS/NsGetFactionMissionServer.cpp index d395cfd89..cf8655d31 100644 --- a/dScripts/ai/NS/NsGetFactionMissionServer.cpp +++ b/dScripts/ai/NS/NsGetFactionMissionServer.cpp @@ -1,5 +1,6 @@ #include "NsGetFactionMissionServer.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "MissionComponent.h" #include "Character.h" #include "eReplicaComponentType.h" @@ -38,7 +39,10 @@ void NsGetFactionMissionServer::OnRespondToMission(Entity* self, int missionID, factionMissions.push_back(778); if (celebrationID != -1) { - GameMessages::SendStartCelebrationEffect(player, player->GetSystemAddress(), celebrationID); + GameMessages::StartCelebrationEffect celebration; + celebration.target = player->GetObjectID(); + celebration.celebrationID = celebrationID; + celebration.SendToClient(player->GetSystemAddress()); } if (flagID != -1) { diff --git a/dScripts/ai/NS/WH/RockHydrantBroken.cpp b/dScripts/ai/NS/WH/RockHydrantBroken.cpp index bb4484258..887254219 100644 --- a/dScripts/ai/NS/WH/RockHydrantBroken.cpp +++ b/dScripts/ai/NS/WH/RockHydrantBroken.cpp @@ -2,6 +2,7 @@ #include "PetMessages.h" #include "EntityManager.h" #include "GameMessages.h" +#include "EffectsMessages.h" void RockHydrantBroken::OnStartup(Entity* self) { self->AddTimer("playEffect", 1); @@ -40,6 +41,6 @@ void RockHydrantBroken::OnTimerDone(Entity* self, std::string timerName) { self->Kill(); } else if (timerName == "playEffect") { - GameMessages::SendPlayFXEffect(self->GetObjectID(), 4737, u"water", "water", LWOOBJID_EMPTY, 1, 1, true); + GameMessages::PlayFXEffect(self->GetObjectID(), 4737, u"water", "water").Send(UNASSIGNED_SYSTEM_ADDRESS); } } diff --git a/dScripts/ai/PROPERTY/AG/AgPropGuard.cpp b/dScripts/ai/PROPERTY/AG/AgPropGuard.cpp index 86c2c1599..0542c9492 100644 --- a/dScripts/ai/PROPERTY/AG/AgPropGuard.cpp +++ b/dScripts/ai/PROPERTY/AG/AgPropGuard.cpp @@ -7,6 +7,7 @@ #include "MissionComponent.h" #include "Item.h" #include "eMissionState.h" +#include "EffectsMessages.h" void AgPropGuard::OnMissionDialogueOK(Entity* self, Entity* target, int missionID, eMissionState missionState) { auto* character = target->GetCharacter(); @@ -17,7 +18,10 @@ void AgPropGuard::OnMissionDialogueOK(Entity* self, Entity* target, int missionI if (missionID == 768 && missionState == eMissionState::AVAILABLE) { // Players who have not touched the orb yet get a camera pan showing where it is. if (character && !character->GetPlayerFlag(71)) { - GameMessages::SendPlayCinematic(target->GetObjectID(), u"MissionCam", target->GetSystemAddress()); + GameMessages::PlayCinematic cinematic; + cinematic.target = target->GetObjectID(); + cinematic.pathName = u"MissionCam"; + cinematic.Send(target->GetSystemAddress()); } } else if (missionID == 768 && missionState >= eMissionState::READY_TO_COMPLETE) { //remove the inventory items diff --git a/dScripts/ai/PROPERTY/AgPropguards.cpp b/dScripts/ai/PROPERTY/AgPropguards.cpp index ced7dd688..7d88c3790 100644 --- a/dScripts/ai/PROPERTY/AgPropguards.cpp +++ b/dScripts/ai/PROPERTY/AgPropguards.cpp @@ -1,6 +1,7 @@ #include "AgPropguards.h" #include "Character.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "EntityManager.h" #include "dZoneManager.h" #include "eMissionState.h" @@ -17,7 +18,10 @@ void AgPropguards::OnMissionDialogueOK(Entity* self, Entity* target, int mission if ((missionState == eMissionState::AVAILABLE || missionState == eMissionState::ACTIVE) && !character->GetPlayerFlag(flag)) { // If the player just started the mission, play a cinematic highlighting the target - GameMessages::SendPlayCinematic(target->GetObjectID(), u"MissionCam", target->GetSystemAddress()); + GameMessages::PlayCinematic cinematic; + cinematic.target = target->GetObjectID(); + cinematic.pathName = u"MissionCam"; + cinematic.Send(target->GetSystemAddress()); } else if (missionState == eMissionState::READY_TO_COMPLETE) { // Makes the guard disappear once the mission has been completed const auto zoneControlID = Game::entityManager->GetZoneControlEntity()->GetObjectID(); diff --git a/dScripts/ai/SPEC/SpecialCoinSpawner.cpp b/dScripts/ai/SPEC/SpecialCoinSpawner.cpp index ff494845e..b0e29eb99 100644 --- a/dScripts/ai/SPEC/SpecialCoinSpawner.cpp +++ b/dScripts/ai/SPEC/SpecialCoinSpawner.cpp @@ -1,5 +1,6 @@ #include "SpecialCoinSpawner.h" #include "CharacterComponent.h" +#include "EffectsMessages.h" void SpecialCoinSpawner::OnStartup(Entity* self) { self->SetProximityRadius(1.5f, "powerupEnter"); @@ -10,7 +11,7 @@ void SpecialCoinSpawner::OnProximityUpdate(Entity* self, Entity* entering, const if (!entering->IsPlayer()) return; auto character = entering->GetCharacter(); if (!character) return; - GameMessages::SendPlayFXEffect(self, -1, u"pickup", "", LWOOBJID_EMPTY, 1, 1, true); + GameMessages::PlayFXEffect(self->GetObjectID(), -1, u"pickup", "").Send(UNASSIGNED_SYSTEM_ADDRESS); character->SetCoins(character->GetCoins() + this->m_CurrencyDenomination, eLootSourceType::CURRENCY); self->Smash(entering->GetObjectID(), eKillType::SILENT); } diff --git a/dScripts/ai/SPEC/SpecialPowerupSpawner.cpp b/dScripts/ai/SPEC/SpecialPowerupSpawner.cpp index 72565923b..44e71155b 100644 --- a/dScripts/ai/SPEC/SpecialPowerupSpawner.cpp +++ b/dScripts/ai/SPEC/SpecialPowerupSpawner.cpp @@ -1,6 +1,7 @@ #include "SpecialPowerupSpawner.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "SkillComponent.h" #include "EntityManager.h" #include "eReplicaComponentType.h" @@ -15,7 +16,7 @@ void SpecialPowerupSpawner::OnProximityUpdate(Entity* self, Entity* entering, co if (!entering->IsPlayer()) return; if (self->GetVar(u"bIsDead")) return; - GameMessages::SendPlayFXEffect(self, -1, u"pickup", "", LWOOBJID_EMPTY, 1, 1, true); + GameMessages::PlayFXEffect(self->GetObjectID(), -1, u"pickup", "").Send(UNASSIGNED_SYSTEM_ADDRESS); auto skillComponent = self->GetComponent(); if (!skillComponent) return; diff --git a/dScripts/ai/SPEC/SpecialSpeedBuffSpawner.cpp b/dScripts/ai/SPEC/SpecialSpeedBuffSpawner.cpp index d31098061..6e8045957 100644 --- a/dScripts/ai/SPEC/SpecialSpeedBuffSpawner.cpp +++ b/dScripts/ai/SPEC/SpecialSpeedBuffSpawner.cpp @@ -1,6 +1,7 @@ #include "SpecialSpeedBuffSpawner.h" #include "GameMessages.h" +#include "EffectsMessages.h" #include "SkillComponent.h" #include "EntityManager.h" #include "eReplicaComponentType.h" @@ -15,7 +16,7 @@ void SpecialSpeedBuffSpawner::OnProximityUpdate(Entity* self, Entity* entering, if (!entering->IsPlayer()) return; if (self->GetVar(u"bIsDead")) return; - GameMessages::SendPlayFXEffect(self, -1, u"pickup", "", LWOOBJID_EMPTY, 1, 1, true); + GameMessages::PlayFXEffect(self->GetObjectID(), -1, u"pickup", "").Send(UNASSIGNED_SYSTEM_ADDRESS); auto skillComponent = entering->GetComponent(); if (!skillComponent) return; diff --git a/dScripts/ai/WILD/LupGenericInteract.cpp b/dScripts/ai/WILD/LupGenericInteract.cpp index 95eb7a96f..db824a3eb 100644 --- a/dScripts/ai/WILD/LupGenericInteract.cpp +++ b/dScripts/ai/WILD/LupGenericInteract.cpp @@ -1,6 +1,7 @@ #include "LupGenericInteract.h" #include "GameMessages.h" +#include "EffectsMessages.h" void LupGenericInteract::OnUse(Entity* self, Entity* user) { - GameMessages::SendPlayAnimation(self, u"interact"); + GameMessages::PlayAnimation(self->GetObjectID(), u"interact").Send(UNASSIGNED_SYSTEM_ADDRESS); } diff --git a/dScripts/ai/WILD/WildAmbientCrab.cpp b/dScripts/ai/WILD/WildAmbientCrab.cpp index 7b5b3d45c..78575bc04 100644 --- a/dScripts/ai/WILD/WildAmbientCrab.cpp +++ b/dScripts/ai/WILD/WildAmbientCrab.cpp @@ -1,27 +1,28 @@ #include "WildAmbientCrab.h" #include "GameMessages.h" +#include "EffectsMessages.h" void WildAmbientCrab::OnStartup(Entity* self){ self->SetVar(u"flipped", true); - GameMessages::SendPlayAnimation(self, u"idle"); + GameMessages::PlayAnimation(self->GetObjectID(), u"idle").Send(UNASSIGNED_SYSTEM_ADDRESS); } void WildAmbientCrab::OnUse(Entity* self, Entity* user) { auto flipped = self->GetVar(u"flipped"); if (flipped) { self->AddTimer("Flipping", 0.6f); - GameMessages::SendPlayAnimation(self, u"flip-over"); + GameMessages::PlayAnimation(self->GetObjectID(), u"flip-over").Send(UNASSIGNED_SYSTEM_ADDRESS); self->SetVar(u"flipped", false); } else if (!flipped) { self->AddTimer("Flipback", 0.8f); - GameMessages::SendPlayAnimation(self, u"flip-back"); + GameMessages::PlayAnimation(self->GetObjectID(), u"flip-back").Send(UNASSIGNED_SYSTEM_ADDRESS); self->SetVar(u"flipped", true); } } void WildAmbientCrab::OnTimerDone(Entity* self, std::string timerName) { - if (timerName == "Flipping") GameMessages::SendPlayAnimation(self, u"over-idle"); - else if (timerName == "Flipback") GameMessages::SendPlayAnimation(self, u"idle"); + if (timerName == "Flipping") GameMessages::PlayAnimation(self->GetObjectID(), u"over-idle").Send(UNASSIGNED_SYSTEM_ADDRESS); + else if (timerName == "Flipback") GameMessages::PlayAnimation(self->GetObjectID(), u"idle").Send(UNASSIGNED_SYSTEM_ADDRESS); } diff --git a/dScripts/ai/WILD/WildAndScared.cpp b/dScripts/ai/WILD/WildAndScared.cpp index d2e89c40d..647f2c820 100644 --- a/dScripts/ai/WILD/WildAndScared.cpp +++ b/dScripts/ai/WILD/WildAndScared.cpp @@ -1,6 +1,7 @@ #include "WildAndScared.h" #include "GameMessages.h" +#include "EffectsMessages.h" void WildAndScared::OnUse(Entity* self, Entity* user) { - GameMessages::SendPlayAnimation(self, u"scared"); + GameMessages::PlayAnimation(self->GetObjectID(), u"scared").Send(UNASSIGNED_SYSTEM_ADDRESS); } diff --git a/dScripts/ai/WILD/WildGfGlowbug.cpp b/dScripts/ai/WILD/WildGfGlowbug.cpp index d834f5b5d..f346d00fe 100644 --- a/dScripts/ai/WILD/WildGfGlowbug.cpp +++ b/dScripts/ai/WILD/WildGfGlowbug.cpp @@ -1,5 +1,6 @@ #include "WildGfGlowbug.h" #include "GameMessages.h" +#include "EffectsMessages.h" void WildGfGlowbug::OnStartup(Entity* self){ self->SetVar(u"switch", false); @@ -9,9 +10,9 @@ void WildGfGlowbug::OnFireEventServerSide(Entity* self, Entity* sender, std::str if (args == "physicsReady") { auto switchState = self->GetVar(u"switch"); if (!switchState) { - GameMessages::SendStopFXEffect(self, true, "glowlight"); + GameMessages::StopFXEffect(self->GetObjectID(), true, "glowlight").Send(UNASSIGNED_SYSTEM_ADDRESS); } else if (switchState) { - GameMessages::SendPlayFXEffect(self, -1, u"light", "glowlight", LWOOBJID_EMPTY); + GameMessages::PlayFXEffect(self->GetObjectID(), -1, u"light", "glowlight").Send(UNASSIGNED_SYSTEM_ADDRESS); } } } @@ -19,10 +20,10 @@ void WildGfGlowbug::OnFireEventServerSide(Entity* self, Entity* sender, std::str void WildGfGlowbug::OnUse(Entity* self, Entity* user) { auto switchState = self->GetVar(u"switch"); if (switchState) { - GameMessages::SendStopFXEffect(self, true, "glowlight"); + GameMessages::StopFXEffect(self->GetObjectID(), true, "glowlight").Send(UNASSIGNED_SYSTEM_ADDRESS); self->SetVar(u"switch", false); } else if (!switchState) { - GameMessages::SendPlayFXEffect(self, -1, u"light", "glowlight", LWOOBJID_EMPTY); + GameMessages::PlayFXEffect(self->GetObjectID(), -1, u"light", "glowlight").Send(UNASSIGNED_SYSTEM_ADDRESS); self->SetVar(u"switch", true); } } diff --git a/dScripts/ai/WILD/WildNinjaBricks.cpp b/dScripts/ai/WILD/WildNinjaBricks.cpp index 4fa65b010..d0f10c053 100644 --- a/dScripts/ai/WILD/WildNinjaBricks.cpp +++ b/dScripts/ai/WILD/WildNinjaBricks.cpp @@ -1,13 +1,14 @@ #include "WildNinjaBricks.h" #include "Entity.h" +#include "EffectsMessages.h" void WildNinjaBricks::OnStartup(Entity* self) { self->AddToGroup("Ninjastuff"); } void WildNinjaBricks::OnNotifyObject(Entity* self, Entity* sender, const std::string& name, int32_t param1, int32_t param2) { - if (name == "Crane") GameMessages::SendPlayAnimation(self, u"crane"); - else if (name == "Tiger") GameMessages::SendPlayAnimation(self, u"tiger"); - else if (name == "Mantis") GameMessages::SendPlayAnimation(self, u"mantis"); + if (name == "Crane") GameMessages::PlayAnimation(self->GetObjectID(), u"crane").Send(UNASSIGNED_SYSTEM_ADDRESS); + else if (name == "Tiger") GameMessages::PlayAnimation(self->GetObjectID(), u"tiger").Send(UNASSIGNED_SYSTEM_ADDRESS); + else if (name == "Mantis") GameMessages::PlayAnimation(self->GetObjectID(), u"mantis").Send(UNASSIGNED_SYSTEM_ADDRESS); } diff --git a/dScripts/ai/WILD/WildNinjaSensei.cpp b/dScripts/ai/WILD/WildNinjaSensei.cpp index 0941e41c1..7071cd06c 100644 --- a/dScripts/ai/WILD/WildNinjaSensei.cpp +++ b/dScripts/ai/WILD/WildNinjaSensei.cpp @@ -1,8 +1,9 @@ #include "WildNinjaSensei.h" #include "Entity.h" +#include "EffectsMessages.h" void WildNinjaSensei::OnStartup(Entity* self) { - GameMessages::SendPlayAnimation(self, u"bow"); + GameMessages::PlayAnimation(self->GetObjectID(), u"bow").Send(UNASSIGNED_SYSTEM_ADDRESS); self->AddTimer("CraneStart", 5); } @@ -12,25 +13,25 @@ void WildNinjaSensei::OnTimerDone(Entity* self, std::string timerName) { for (auto ninja : ninjas) ninja->NotifyObject(self, "Crane"); self->AddTimer("Bow", 15.5f); self->AddTimer("TigerStart", 25); - GameMessages::SendPlayAnimation(self, u"crane"); + GameMessages::PlayAnimation(self->GetObjectID(), u"crane").Send(UNASSIGNED_SYSTEM_ADDRESS); } else if (timerName == "TigerStart") { auto ninjas = Game::entityManager->GetEntitiesInGroup("Ninjastuff"); - GameMessages::SendPlayAnimation(self, u"bow"); + GameMessages::PlayAnimation(self->GetObjectID(), u"bow").Send(UNASSIGNED_SYSTEM_ADDRESS); for (auto ninja : ninjas) ninja->NotifyObject(self, "Tiger"); self->AddTimer("Bow", 15.5f); self->AddTimer("MantisStart", 25); - GameMessages::SendPlayAnimation(self, u"tiger"); + GameMessages::PlayAnimation(self->GetObjectID(), u"tiger").Send(UNASSIGNED_SYSTEM_ADDRESS); } else if (timerName == "MantisStart") { auto ninjas = Game::entityManager->GetEntitiesInGroup("Ninjastuff"); - GameMessages::SendPlayAnimation(self, u"tiger"); + GameMessages::PlayAnimation(self->GetObjectID(), u"tiger").Send(UNASSIGNED_SYSTEM_ADDRESS); for (auto ninja : ninjas) ninja->NotifyObject(self, "Mantis"); self->AddTimer("Bow", 15.5f); self->AddTimer("CraneStart", 25); - GameMessages::SendPlayAnimation(self, u"mantis"); + GameMessages::PlayAnimation(self->GetObjectID(), u"mantis").Send(UNASSIGNED_SYSTEM_ADDRESS); } else if (timerName == "Bow") { auto ninjas = Game::entityManager->GetEntitiesInGroup("Ninjastuff"); for (auto ninja : ninjas) ninja->NotifyObject(self, "Bow"); - GameMessages::SendPlayAnimation(self, u"bow"); + GameMessages::PlayAnimation(self->GetObjectID(), u"bow").Send(UNASSIGNED_SYSTEM_ADDRESS); } } diff --git a/dScripts/ai/WILD/WildNinjaStudent.cpp b/dScripts/ai/WILD/WildNinjaStudent.cpp index b7e2f5852..9a8e4d401 100644 --- a/dScripts/ai/WILD/WildNinjaStudent.cpp +++ b/dScripts/ai/WILD/WildNinjaStudent.cpp @@ -1,14 +1,15 @@ #include "WildNinjaStudent.h" #include "GameMessages.h" +#include "EffectsMessages.h" void WildNinjaStudent::OnStartup(Entity* self) { self->AddToGroup("Ninjastuff"); - GameMessages::SendPlayAnimation(self, u"bow"); + GameMessages::PlayAnimation(self->GetObjectID(), u"bow").Send(UNASSIGNED_SYSTEM_ADDRESS); } void WildNinjaStudent::OnNotifyObject(Entity* self, Entity* sender, const std::string& name, int32_t param1, int32_t param2) { - if (name == "Crane") GameMessages::SendPlayAnimation(self, u"crane"); - else if (name == "Tiger") GameMessages::SendPlayAnimation(self, u"tiger"); - else if (name == "Mantis") GameMessages::SendPlayAnimation(self, u"mantis"); - else if (name == "Bow") GameMessages::SendPlayAnimation(self, u"bow"); + if (name == "Crane") GameMessages::PlayAnimation(self->GetObjectID(), u"crane").Send(UNASSIGNED_SYSTEM_ADDRESS); + else if (name == "Tiger") GameMessages::PlayAnimation(self->GetObjectID(), u"tiger").Send(UNASSIGNED_SYSTEM_ADDRESS); + else if (name == "Mantis") GameMessages::PlayAnimation(self->GetObjectID(), u"mantis").Send(UNASSIGNED_SYSTEM_ADDRESS); + else if (name == "Bow") GameMessages::PlayAnimation(self->GetObjectID(), u"bow").Send(UNASSIGNED_SYSTEM_ADDRESS); } diff --git a/dScripts/ai/WILD/WildPants.cpp b/dScripts/ai/WILD/WildPants.cpp index 7c5e1cd24..4f141964f 100644 --- a/dScripts/ai/WILD/WildPants.cpp +++ b/dScripts/ai/WILD/WildPants.cpp @@ -1,10 +1,11 @@ #include "WildPants.h" #include "GameMessages.h" +#include "EffectsMessages.h" void WildPants::OnStartup(Entity* self) { self->SetProximityRadius(5, "scardyPants"); } void WildPants::OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status) { - if (status == "ENTER") GameMessages::SendPlayAnimation(self, u"scared"); + if (status == "ENTER") GameMessages::PlayAnimation(self->GetObjectID(), u"scared").Send(UNASSIGNED_SYSTEM_ADDRESS); } diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index f03e2dec4..27c7f9367 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -99,6 +99,7 @@ #include "Item.h" #include "eFunnessTypes.h" #include "WorldMigration.h" +#include "EffectsMessages.h" namespace Game { Logger* logger = nullptr; @@ -621,7 +622,10 @@ namespace { args.Insert("title", announcement.title); args.Insert("message", announcement.message); - GameMessages::SendUIMessageServerToAllClients("ToggleAnnounce", args); + GameMessages::UIMessageServerToAllClients uiMessage; + uiMessage.strMessageName = "ToggleAnnounce"; + uiMessage.args = std::move(args); + uiMessage.Send(UNASSIGNED_SYSTEM_ADDRESS); }); handlers.On(MessageType::Chat::GM_MUTE, [](const ChatPackets::GMMute& mute, const SystemAddress&) { @@ -1153,7 +1157,10 @@ namespace { args.Insert("title", Game::config->GetValue("cdclient_mismatch_title")); args.Insert("message", Game::config->GetValue("cdclient_mismatch_message")); - GameMessages::SendUIMessageServerToSingleClient("ToggleAnnounce", args, sysAddr); + GameMessages::UIMessageServerToAllClients uiMessage; + uiMessage.strMessageName = "ToggleAnnounce"; + uiMessage.args = std::move(args); + uiMessage.SendToClient(sysAddr); LOG("Account (%s) with GmLevel (%s) does not have a matching FDB, but is a developer and will skip this check." , username.GetAsString().c_str(), StringifiedEnum::ToString(accountInfo->maxGmLevel).data()); } @@ -1555,7 +1562,11 @@ namespace { data.Insert("Description3", Game::config->GetValue("help_3_description")); data.Insert("Description4", Game::config->GetValue("help_4_description")); - GameMessages::SendUIMessageServerToSingleClient(entity, sysAddr, "UIHelpTop5", data); + GameMessages::UIMessageServerToSingleClient uiMessage; + uiMessage.target = entity->GetObjectID(); + uiMessage.strMessageName = "UIHelpTop5"; + uiMessage.args = std::move(data); + uiMessage.SendToClient(sysAddr); } }; diff --git a/tests/dGameTests/dGameMessagesTests/CMakeLists.txt b/tests/dGameTests/dGameMessagesTests/CMakeLists.txt index cf20079c8..a49e21d7a 100644 --- a/tests/dGameTests/dGameMessagesTests/CMakeLists.txt +++ b/tests/dGameTests/dGameMessagesTests/CMakeLists.txt @@ -3,6 +3,7 @@ SET(DGAMEMESSAGES_TESTS "BuildingMessagesTests.cpp" "GameMessageTests.cpp" "GameMsgSplitTests.cpp" + "EffectsMessagesTests.cpp" "MissionMessagesTests.cpp" "PetMessagesTests.cpp" "PropertyMessagesTests.cpp" diff --git a/tests/dGameTests/dGameMessagesTests/EffectsMessagesTests.cpp b/tests/dGameTests/dGameMessagesTests/EffectsMessagesTests.cpp new file mode 100644 index 000000000..6da338f70 --- /dev/null +++ b/tests/dGameTests/dGameMessagesTests/EffectsMessagesTests.cpp @@ -0,0 +1,571 @@ +#include "EffectsMessages.h" +#include "GameDependencies.h" +#include "GameMessageTestUtils.h" +#include "Legacy/EffectsMessagesLegacy.h" + +#include +#include +#include + +#include + +using namespace GameMessageTestUtils; + +namespace { + const std::vector g_Ints = { 0, 1, -1, 1727, std::numeric_limits::max(), std::numeric_limits::min() }; + const std::vector g_Floats = { 0.0f, 1.0f, -1.0f, 0.4f, 0.8f, 3.5f }; + const std::vector g_WStrings = { u"", u"a", u"camshake-bridge", u"été ☃", std::u16string(300, u'x') }; + const std::vector g_Strings = { "", "a", "{9a24f1fa-3177-4745-a2df-fbd996d6e1e3}", std::string(300, 'y') }; + const std::vector g_Ids = { LWOOBJID_EMPTY, 0x1000000000000001LL, -1 }; + + PacketBytes Payload(const GameMessages::NetGameMsg& msg) { + RakNet::BitStream bitStream; + msg.Serialize(bitStream); + return FromBitStream(bitStream); + } + + // Serializes msg, then reads it with the legacy read sequence; both must consume exactly the same bits. + template + Result ReadWithLegacy(const GameMessages::NetGameMsg& msg, const std::function& read) { + RakNet::BitStream wire; + msg.Serialize(wire); + RakNet::BitStream legacyStream(wire.GetData(), wire.GetNumberOfBytesUsed(), false); + auto result = read(legacyStream); + EXPECT_EQ(legacyStream.GetReadOffset(), wire.GetNumberOfBitsUsed()); + return result; + } + + // Round trip for messages carrying AMF arrays: the associative part is an unordered map, so a re-serialized + // copy may list the keys in another order. Checks every bit is consumed and returns the copy. + template + T AmfRoundTrip(const T& msg) { + RakNet::BitStream bitStream; + msg.Serialize(bitStream); + T copy; + EXPECT_TRUE(copy.Deserialize(bitStream)); + EXPECT_EQ(bitStream.GetNumberOfUnreadBits(), 0); + RakNet::BitStream again; + copy.Serialize(again); + EXPECT_EQ(again.GetNumberOfBitsUsed(), bitStream.GetNumberOfBitsUsed()); + return copy; + } + + // A few differently shaped AMF argument arrays (built fresh each time: AMFArrayValue is move only). + AMFArrayValue MakeArgs(const int variant) { + AMFArrayValue args; + if (variant == 1) { + args.Insert("visible", true); + args.Insert("text", "hello"); + } else if (variant == 2) { + args.Insert("state", "Lobby"); + args.Insert("amount", -5); + args.Insert("ratio", 0.25); + auto* nested = args.InsertArray("nested"); + nested->Push("one"); + nested->Push(false); + } + return args; + } +} + +class EffectsMessagesTests : public GameDependenciesTest { +protected: + void SetUp() override { SetUpDependencies(); } + void TearDown() override { TearDownDependencies(); } +}; + +TEST_F(EffectsMessagesTests, PlayAnimationMatchesLegacy) { + for (const auto target : g_Targets) { + Entity entity(target, info); + for (const auto& animation : g_WStrings) { + for (const auto priority : g_Floats) { + for (const auto scale : g_Floats) { + GameMessages::PlayAnimation msg(target, animation); + msg.fPriority = priority; + msg.fScale = scale; + ExpectSameAsLegacy([&](const SystemAddress&) { LegacyGameMessages::SendPlayAnimation(&entity, animation, priority, scale); }, msg, SendMode::Broadcast); + if (animation == GeneralUtils::ASCIIToUTF16(GeneralUtils::UTF16ToWTF8(animation))) { + const auto copy = RoundTrip(msg); + EXPECT_EQ(copy.animationID, animation); + EXPECT_EQ(copy.fPriority, priority); + EXPECT_EQ(copy.fScale, scale); + } + } + } + } + } +} + +TEST_F(EffectsMessagesTests, PlayNDAudioEmitterMatchesLegacy) { + for (const auto target : g_Targets) { + Entity entity(target, info); + for (const auto& guid : g_Strings) { + const GameMessages::PlayNDAudioEmitter msg(target, guid); + // The legacy function always broadcast, whatever address it was given. + ExpectSameAsLegacy([&](const SystemAddress& a) { LegacyGameMessages::SendPlayNDAudioEmitter(&entity, a, guid); }, msg, SendMode::Broadcast); + EXPECT_EQ(RoundTrip(msg).NDAudioEventGUID, guid); + } + } + GameMessages::PlayNDAudioEmitter full; + full.NDAudioCallbackMessageData = 5; + full.NDAudioEmitterID = 7; + full.NDAudioEventGUID = "guid"; + full.NDAudioMetaEventName = "meta"; + full.result = true; + full.targetObjectIDForNDAudioCallbackMessages = 9; + const auto copy = RoundTrip(full); + EXPECT_EQ(copy.NDAudioCallbackMessageData, 5); + EXPECT_EQ(copy.NDAudioEmitterID, 7); + EXPECT_EQ(copy.NDAudioMetaEventName, "meta"); + EXPECT_EQ(copy.targetObjectIDForNDAudioCallbackMessages, 9); + ExpectTruncatedFails(full); +} + +TEST_F(EffectsMessagesTests, PlayEmbeddedEffectMatchesLegacy) { + for (const auto target : g_Targets) { + Entity entity(target, info); + for (const auto& effectName : g_WStrings) { + for (const auto from : g_Ids) { + for (const auto radius : g_Floats) { + GameMessages::PlayEmbeddedEffectOnAllClientsNearObject msg; + msg.target = target; + msg.effectName = effectName; + msg.fromObjectID = from; + msg.radius = radius; + ExpectSameAsLegacy([&](const SystemAddress&) { LegacyGameMessages::SendPlayEmbeddedEffectOnAllClientsNearObject(&entity, effectName, from, radius); }, msg, SendMode::Broadcast); + const auto copy = RoundTrip(msg); + EXPECT_EQ(copy.effectName, effectName); + EXPECT_EQ(copy.fromObjectID, from); + EXPECT_EQ(copy.radius, radius); + } + } + } + } +} + +TEST_F(EffectsMessagesTests, PlayFXEffectMatchesLegacy) { + for (const auto target : g_Targets) { + Entity entity(target, info); + for (const auto effectID : g_Ints) { + for (const auto& effectType : g_WStrings) { + for (const auto& name : g_Strings) { + for (const auto secondary : g_Ids) { + for (const auto priority : { 1.0f, 0.4f, 1.07f }) { + for (const auto scale : { 1.0f, 2.0f }) { + for (const bool serialize : { false, true }) { + GameMessages::PlayFXEffect msg(target, effectID, effectType, name); + msg.secondary = secondary; + msg.priority = priority; + msg.scale = scale; + msg.serialize = serialize; + ExpectSameAsLegacy([&](const SystemAddress&) { LegacyGameMessages::SendPlayFXEffect(target, effectID, effectType, name, secondary, priority, scale, serialize); }, msg, SendMode::Broadcast); + // The Entity* overload wrote the same thing. + ExpectSameAsLegacy([&](const SystemAddress&) { LegacyGameMessages::SendPlayFXEffect(&entity, effectID, effectType, name, secondary, priority, scale, serialize); }, msg, SendMode::Broadcast); + const auto copy = RoundTrip(msg); + EXPECT_EQ(copy.effectID, effectID); + EXPECT_EQ(copy.effectType, effectType); + EXPECT_EQ(copy.name, name); + EXPECT_EQ(copy.secondary, secondary); + EXPECT_EQ(copy.priority, priority); + EXPECT_EQ(copy.scale, scale); + EXPECT_EQ(copy.serialize, serialize); + } + } + } + } + } + } + } + } +} + +TEST_F(EffectsMessagesTests, StopFXEffectMatchesLegacy) { + for (const auto target : g_Targets) { + Entity entity(target, info); + for (const bool killImmediate : { false, true }) { + for (const auto& name : g_Strings) { + const GameMessages::StopFXEffect msg(target, killImmediate, name); + ExpectSameAsLegacy([&](const SystemAddress&) { LegacyGameMessages::SendStopFXEffect(&entity, killImmediate, name); }, msg, SendMode::Broadcast); + const auto copy = RoundTrip(msg); + EXPECT_EQ(copy.killImmediate, killImmediate); + EXPECT_EQ(copy.name, name); + } + } + } +} + +TEST_F(EffectsMessagesTests, BroadcastTextToChatboxMatchesLegacy) { + for (const auto target : g_Targets) { + Entity entity(target, info); + for (const auto& attrs : g_WStrings) { + for (const auto& text : g_WStrings) { + GameMessages::BroadcastTextToChatbox msg; + msg.target = target; + msg.attrs = attrs; + msg.wsText = text; + // The legacy function always broadcast. + ExpectSameAsLegacy([&](const SystemAddress& a) { LegacyGameMessages::SendBroadcastTextToChatbox(&entity, a, attrs, text); }, msg, SendMode::Broadcast); + const auto copy = RoundTrip(msg); + EXPECT_EQ(copy.attrs, attrs); + EXPECT_EQ(copy.wsText, text); + } + } + } +} + +TEST_F(EffectsMessagesTests, AmbientSoundsMatchLegacy) { + for (const auto target : g_Targets) { + Entity entity(target, info); + for (const auto& guid : g_Strings) { + for (const bool result : { false, true }) { + GameMessages::Play2DAmbientSound play; + play.target = target; + play.audioGUID = guid; + play.result = result; + // Sent to the entity's own address (the test entity has none, so both send nothing to a client). + const auto legacyPlay = Capture([&] { LegacyGameMessages::SendPlay2DAmbientSound(&entity, guid, result); }); + const auto ourPlay = Capture([&] { play.SendToClient(entity.GetSystemAddress()); }); + ASSERT_EQ(legacyPlay.size(), 1); + ASSERT_EQ(ourPlay.size(), 1); + EXPECT_PACKET_EQ(FromCapture(legacyPlay[0]), FromCapture(ourPlay[0])); + EXPECT_EQ(legacyPlay[0].sysAddr, ourPlay[0].sysAddr); + EXPECT_EQ(legacyPlay[0].broadcast, ourPlay[0].broadcast); + const auto playCopy = RoundTrip(play); + EXPECT_EQ(playCopy.audioGUID, guid); + EXPECT_EQ(playCopy.result, result); + + for (const bool force : { false, true }) { + GameMessages::Stop2DAmbientSound stop; + stop.target = target; + stop.force = force; + stop.audioGUID = guid; + stop.result = result; + const auto legacyStop = Capture([&] { LegacyGameMessages::SendStop2DAmbientSound(&entity, force, guid, result); }); + const auto ourStop = Capture([&] { stop.SendToClient(entity.GetSystemAddress()); }); + ASSERT_EQ(legacyStop.size(), 1); + ASSERT_EQ(ourStop.size(), 1); + EXPECT_PACKET_EQ(FromCapture(legacyStop[0]), FromCapture(ourStop[0])); + EXPECT_EQ(legacyStop[0].sysAddr, ourStop[0].sysAddr); + const auto stopCopy = RoundTrip(stop); + EXPECT_EQ(stopCopy.force, force); + EXPECT_EQ(stopCopy.audioGUID, guid); + } + } + } + } +} + +TEST_F(EffectsMessagesTests, UIMessagesMatchLegacy) { + for (const auto target : g_Targets) { + Entity entity(target, info); + for (const int variant : { 0, 1, 2 }) { + for (const auto& name : g_Strings) { + GameMessages::UIMessageServerToSingleClient single; + single.target = target; + single.args = MakeArgs(variant); + single.strMessageName = name; + auto legacyArgs = MakeArgs(variant); + ExpectSameAsLegacy([&](const SystemAddress& a) { LegacyGameMessages::SendUIMessageServerToSingleClient(&entity, a, name, legacyArgs); }, single, SendMode::SendToClient); + const auto singleCopy = AmfRoundTrip(single); + EXPECT_EQ(singleCopy.strMessageName, name); + EXPECT_EQ(singleCopy.args.GetAssociative().size(), single.args.GetAssociative().size()); + + // The "single client by address" overload sent UIMessageServerToAllClients with an empty target. + GameMessages::UIMessageServerToAllClients all; + all.args = MakeArgs(variant); + all.strMessageName = name; + ExpectSameAsLegacy([&](const SystemAddress& a) { LegacyGameMessages::SendUIMessageServerToSingleClient(name, legacyArgs, a); }, all, SendMode::SendToClient); + // And the broadcast one. + ExpectSameAsLegacy([&](const SystemAddress&) { LegacyGameMessages::SendUIMessageServerToAllClients(name, legacyArgs); }, all, SendMode::Broadcast); + const auto allCopy = AmfRoundTrip(all); + EXPECT_EQ(allCopy.strMessageName, name); + EXPECT_EQ(allCopy.args.GetAssociative().size(), all.args.GetAssociative().size()); + EXPECT_EQ(allCopy.args.GetDense().size(), all.args.GetDense().size()); + } + } + } +} + +TEST_F(EffectsMessagesTests, StartCelebrationEffectMatchesLegacy) { + for (const auto target : g_Targets) { + Entity entity(target, info); + for (const auto celebrationID : g_Ints) { + GameMessages::StartCelebrationEffect msg; + msg.target = target; + msg.celebrationID = celebrationID; + ExpectSameAsLegacy([&](const SystemAddress& a) { LegacyGameMessages::SendStartCelebrationEffect(&entity, a, celebrationID); }, msg, SendMode::SendToClient); + EXPECT_EQ(RoundTrip(msg).celebrationID, celebrationID); + } + } + GameMessages::StartCelebrationEffect full; + full.animation = u"anim"; + full.backgroundObject = 1; + full.cameraPathLOT = 2; + full.celeLeadIn = 3.0f; + full.celeLeadOut = 4.0f; + full.celebrationID = 22; + full.duration = 5.0f; + full.iconID = 6; + full.mainText = u"main"; + full.mixerProgram = "mixer"; + full.musicCue = "cue"; + full.pathNodeName = "node"; + full.soundGUID = "sound"; + full.subText = u"sub"; + const auto copy = RoundTrip(full); + EXPECT_EQ(copy.backgroundObject, 1); + EXPECT_EQ(copy.cameraPathLOT, 2); + EXPECT_EQ(copy.celeLeadOut, 4.0f); + EXPECT_EQ(copy.subText, u"sub"); + ExpectTruncatedFails(full); +} + +TEST_F(EffectsMessagesTests, MessageBoxAndChatBubbleMatchLegacy) { + for (const auto target : g_Targets) { + for (const bool show : { false, true }) { + for (const auto callback : g_Ids) { + for (const auto& identifier : g_WStrings) { + for (const auto imageID : g_Ints) { + GameMessages::DisplayMessageBox msg; + msg.target = target; + msg.bShow = show; + msg.callbackClient = callback; + msg.identifier = identifier; + msg.imageID = imageID; + msg.text = identifier + u"!"; + msg.userData = u"data"; + ExpectSameAsLegacy([&](const SystemAddress& a) { LegacyGameMessages::SendDisplayMessageBox(target, show, callback, identifier, imageID, identifier + u"!", u"data", a); }, msg); + const auto copy = RoundTrip(msg); + EXPECT_EQ(copy.bShow, show); + EXPECT_EQ(copy.callbackClient, callback); + EXPECT_EQ(copy.identifier, identifier); + EXPECT_EQ(copy.imageID, imageID); + EXPECT_EQ(copy.text, identifier + u"!"); + EXPECT_EQ(copy.userData, u"data"); + } + } + } + } + for (const auto& text : g_WStrings) { + GameMessages::DisplayChatBubble bubble; + bubble.target = target; + bubble.wsText = text; + ExpectSameAsLegacy([&](const SystemAddress& a) { LegacyGameMessages::SendDisplayChatBubble(target, text, a); }, bubble); + EXPECT_EQ(RoundTrip(bubble).wsText, text); + } + } +} + +TEST_F(EffectsMessagesTests, ChangeIdleFlagsMatchesLegacy) { + const auto flags = { eAnimationFlags::IDLE_NONE, eAnimationFlags::IDLE_COMBAT, static_cast(0xFFFFFFFF) }; + for (const auto target : g_Targets) { + for (const auto on : flags) { + for (const auto off : flags) { + GameMessages::ChangeIdleFlags msg; + msg.target = target; + msg.flagsOn = on; + msg.flagsOff = off; + ExpectSameAsLegacy([&](const SystemAddress& a) { LegacyGameMessages::SendChangeIdleFlags(target, on, off, a); }, msg, SendMode::Broadcast); + const auto copy = RoundTrip(msg); + EXPECT_EQ(copy.flagsOn, on); + EXPECT_EQ(copy.flagsOff, off); + } + } + } +} + +TEST_F(EffectsMessagesTests, BillboardsMatchLegacy) { + for (const auto target : g_Targets) { + GameMessages::SetNameBillboardState state; + state.target = target; + ExpectSameAsLegacy([&](const SystemAddress& a) { LegacyGameMessages::SendSetNamebillboardState(a, target); }, state); + GameMessages::ShowBillboardInteractIcon icon; + icon.target = target; + ExpectSameAsLegacy([&](const SystemAddress& a) { LegacyGameMessages::SendShowBillboardInteractIcon(a, target); }, icon); + } +} + +TEST_F(EffectsMessagesTests, CinematicsMatchLegacy) { + const auto endBehaviors = { eEndBehavior::RETURN, eEndBehavior::WAIT }; + for (const auto target : g_Targets) { + for (const auto& path : g_WStrings) { + for (const auto leadIn : { -1.0f, 0.0f, 2.0f }) { + for (const auto endBehavior : endBehaviors) { + for (uint32_t bools = 0; bools < (1u << 10); bools += 37) { + const auto bit = [&](int i) { return ((bools >> i) & 1) != 0; }; + GameMessages::PlayCinematic msg; + msg.target = target; + msg.pathName = path; + msg.allowGhostUpdates = bit(0); + msg.bCloseMultiInteract = bit(1); + msg.bSendServerNotify = bit(2); + msg.bUseControlledObjectForAudioListener = bit(3); + msg.endBehavior = endBehavior; + msg.hidePlayerDuringCine = bit(4); + msg.leadIn = leadIn; + msg.leavePlayerLockedWhenFinished = bit(5); + msg.lockPlayer = bit(6); + msg.result = bit(7); + msg.skipIfSamePath = bit(8); + msg.startTimeAdvance = bit(9) ? 1.5f : 0.0f; + ExpectSameAsLegacy([&](const SystemAddress& a) { + LegacyGameMessages::SendPlayCinematic(target, path, a, bit(0), bit(1), bit(2), bit(3), endBehavior, bit(4), leadIn, bit(5), bit(6), bit(7), bit(8), bit(9) ? 1.5f : 0.0f); + }, msg); + const auto copy = RoundTrip(msg); + EXPECT_EQ(copy.pathName, path); + EXPECT_EQ(copy.endBehavior, endBehavior); + EXPECT_EQ(copy.leadIn, leadIn); + EXPECT_EQ(copy.lockPlayer, bit(6)); + } + } + } + for (const auto leadOut : { -1.0f, 1.0f }) { + for (const bool locked : { false, true }) { + GameMessages::EndCinematic end; + end.target = target; + end.pathName = path; + end.leadOut = leadOut; + end.leavePlayerLocked = locked; + ExpectSameAsLegacy([&](const SystemAddress& a) { LegacyGameMessages::SendEndCinematic(target, path, a, leadOut, locked); }, end); + const auto copy = RoundTrip(end); + EXPECT_EQ(copy.leadOut, leadOut); + EXPECT_EQ(copy.leavePlayerLocked, locked); + EXPECT_EQ(copy.pathName, path); + } + } + } + } +} + +TEST_F(EffectsMessagesTests, SlashCommandTextFeedbackMatchesLegacy) { + for (const auto target : g_Targets) { + Entity entity(target, info); + for (const auto& text : g_WStrings) { + const GameMessages::SlashCommandTextFeedback msg(target, text); + const auto legacy = Capture([&] { LegacyGameMessages::SendSlashCommandFeedbackText(&entity, text); }); + const auto ours = Capture([&] { msg.SendToClient(entity.GetSystemAddress()); }); + ASSERT_EQ(legacy.size(), 1); + ASSERT_EQ(ours.size(), 1); + EXPECT_PACKET_EQ(FromCapture(legacy[0]), FromCapture(ours[0])); + EXPECT_EQ(legacy[0].sysAddr, ours[0].sysAddr); + EXPECT_EQ(RoundTrip(msg).text, text); + } + } +} + +TEST_F(EffectsMessagesTests, EmotesMatchLegacy) { + for (const auto target : g_Targets) { + Entity entity(target, info); + for (const auto emoteID : g_Ints) { + for (const auto emoteTarget : g_Ids) { + GameMessages::PlayEmote msg; + msg.target = target; + msg.emoteID = emoteID; + msg.targetID = emoteTarget; + ExpectSameAsLegacy([&](const SystemAddress& a) { LegacyGameMessages::SendPlayEmote(target, emoteID, emoteTarget, a); }, msg); + const auto legacyRead = ReadWithLegacy(msg, LegacyGameMessages::ReadPlayEmote); + const auto copy = RoundTrip(msg); + EXPECT_EQ(copy.emoteID, legacyRead.emoteID); + EXPECT_EQ(copy.targetID, legacyRead.targetID); + ExpectTruncatedFails(msg); + } + for (const bool lock : { false, true }) { + GameMessages::SetEmoteLockState lockState; + lockState.target = target; + lockState.bLock = lock; + lockState.emoteID = emoteID; + const auto legacy = Capture([&] { LegacyGameMessages::SendSetEmoteLockState(&entity, lock, emoteID); }); + const auto ours = Capture([&] { lockState.SendToClient(entity.GetSystemAddress()); }); + ASSERT_EQ(legacy.size(), 1); + ASSERT_EQ(ours.size(), 1); + EXPECT_PACKET_EQ(FromCapture(legacy[0]), FromCapture(ours[0])); + const auto copy = RoundTrip(lockState); + EXPECT_EQ(copy.bLock, lock); + EXPECT_EQ(copy.emoteID, emoteID); + } + } + } +} + +TEST_F(EffectsMessagesTests, InboundReadsLikeLegacy) { + for (const auto button : g_Ints) { + for (const auto& identifier : g_WStrings) { + GameMessages::MessageBoxRespond box; + box.iButton = button; + box.identifier = identifier; + box.userData = u"user"; + const auto legacyBox = ReadWithLegacy(box, LegacyGameMessages::ReadMessageBoxResponse); + const auto boxCopy = RoundTrip(box); + EXPECT_TRUE(legacyBox.ok); + EXPECT_EQ(boxCopy.iButton, legacyBox.iButton); + EXPECT_EQ(boxCopy.identifier, legacyBox.identifier); + EXPECT_EQ(boxCopy.userData, legacyBox.userData); + ExpectTruncatedFails(box); + + GameMessages::ChoiceBoxRespond choice; + choice.buttonIdentifier = u"btn"; + choice.iButton = button; + choice.identifier = identifier; + const auto legacyChoice = ReadWithLegacy(choice, LegacyGameMessages::ReadChoiceBoxRespond); + const auto choiceCopy = RoundTrip(choice); + EXPECT_TRUE(legacyChoice.ok); + EXPECT_EQ(choiceCopy.buttonIdentifier, legacyChoice.buttonIdentifier); + EXPECT_EQ(choiceCopy.iButton, legacyChoice.iButton); + EXPECT_EQ(choiceCopy.identifier, legacyChoice.identifier); + ExpectTruncatedFails(choice); + } + } + + for (const auto event : { eCinematicEvent::STARTED, eCinematicEvent::WAYPOINT, eCinematicEvent::ENDED }) { + for (const auto time : { -1.0f, 0.0f, 2.5f }) { + for (const auto waypoint : { -1, 0, 3 }) { + for (const auto& path : g_WStrings) { + GameMessages::CinematicUpdate update; + update.event = event; + update.overallTime = time; + update.pathName = path; + update.pathTime = time * 2; + update.waypoint = waypoint; + const auto legacy = ReadWithLegacy(update, LegacyGameMessages::ReadCinematicUpdate); + const auto copy = RoundTrip(update); + EXPECT_EQ(copy.event, legacy.event); + EXPECT_EQ(copy.overallTime, legacy.overallTime); + EXPECT_EQ(copy.pathName, legacy.pathName); + EXPECT_EQ(copy.pathTime, legacy.pathTime); + EXPECT_EQ(copy.waypoint, legacy.waypoint); + ExpectTruncatedFails(update); + } + } + } + } + + // A length above MAX_MESSAGE_LENGTH is rejected, as the old handler did. + RakNet::BitStream tooLong; + tooLong.Write(0); + tooLong.Write(MAX_MESSAGE_LENGTH + 1); + GameMessages::MessageBoxRespond box; + EXPECT_FALSE(box.Deserialize(tooLong)); +} + +// Independent of the legacy code: hand computed payloads (RakNet writes MSB first). +TEST_F(EffectsMessagesTests, GoldenBytes) { + // effectID 7 (flag 1), "a" (u32 1, 0x61 0x00), scale default (0), "b" (u32 1, 0x62), priority default (0), + // secondary default (0), serialize true (1). + GameMessages::PlayFXEffect fx(0, 7, u"a", "b"); + EXPECT_PACKET_EQ(FromHex("83 80 00 00 00 80 00 00 30 80 00 40 00 00 18 88", 125), Payload(fx)); + + GameMessages::StopFXEffect stop(0, true, "ab"); + EXPECT_PACKET_EQ(FromHex("81 00 00 00 30 b1 00", 49), Payload(stop)); + + GameMessages::PlayAnimation animation(0, u"ab"); + // u32 2, "a\0b\0", then expect(1) immediate(0) complete(0) priority(0) scale(0) + EXPECT_PACKET_EQ(FromHex("02 00 00 00 61 00 62 00 80", 69), Payload(animation)); + + GameMessages::ChangeIdleFlags idle; + idle.flagsOn = static_cast(1); + // off default (0), on flag (1) then 01 00 00 00 + EXPECT_PACKET_EQ(FromHex("40 40 00 00 00", 34), Payload(idle)); + + GameMessages::EndCinematic end; + EXPECT_PACKET_EQ(FromHex("00 00 00 00 00", 34), Payload(end)); +} diff --git a/tests/dGameTests/dGameMessagesTests/GameMessageTestUtils.h b/tests/dGameTests/dGameMessagesTests/GameMessageTestUtils.h index 9cfccfb57..4a230f532 100644 --- a/tests/dGameTests/dGameMessagesTests/GameMessageTestUtils.h +++ b/tests/dGameTests/dGameMessagesTests/GameMessageTestUtils.h @@ -33,8 +33,10 @@ namespace GameMessageTestUtils { } // How the struct is sent in a comparison: Send (UNASSIGNED broadcasts; legacy functions that did - // "if (UNASSIGNED) SEND_PACKET_BROADCAST; SEND_PACKET;") or SendToClient (legacy functions with only SEND_PACKET). - enum class SendMode { Send, SendToClient }; + // "if (UNASSIGNED) SEND_PACKET_BROADCAST; SEND_PACKET;"), SendToClient (legacy functions with only SEND_PACKET) + // or Broadcast (legacy functions with only SEND_PACKET_BROADCAST, whatever address they were given: the struct is + // sent with Send(UNASSIGNED_SYSTEM_ADDRESS)). + enum class SendMode { Send, SendToClient, Broadcast }; // Sends the same message through the frozen legacy function and through the struct, to one client and to // UNASSIGNED_SYSTEM_ADDRESS, and requires identical bytes and the same effective destination. @@ -43,7 +45,11 @@ namespace GameMessageTestUtils { for (const auto& address : g_Addresses) { SCOPED_TRACE(address == UNASSIGNED_SYSTEM_ADDRESS ? "unassigned address" : "single client"); const auto legacyPackets = Capture([&] { legacySend(address); }); - const auto newPackets = Capture([&] { mode == SendMode::Send ? msg.Send(address) : msg.SendToClient(address); }); + const auto newPackets = Capture([&] { + if (mode == SendMode::Send) msg.Send(address); + else if (mode == SendMode::SendToClient) msg.SendToClient(address); + else msg.Send(UNASSIGNED_SYSTEM_ADDRESS); + }); ASSERT_FALSE(legacyPackets.empty()); ASSERT_EQ(newPackets.size(), 1); diff --git a/tests/dGameTests/dGameMessagesTests/Legacy/EffectsMessagesLegacy.h b/tests/dGameTests/dGameMessagesTests/Legacy/EffectsMessagesLegacy.h new file mode 100644 index 000000000..873c58c28 --- /dev/null +++ b/tests/dGameTests/dGameMessagesTests/Legacy/EffectsMessagesLegacy.h @@ -0,0 +1,607 @@ +#ifndef EFFECTSMESSAGESLEGACY_H +#define EFFECTSMESSAGESLEGACY_H + +// FROZEN ORACLE - DO NOT EDIT. +// Verbatim copies of the hand written GameMessages functions that EffectsMessages.h replaced +// (dGame/dGameMessages/GameMessages.cpp, branched from origin/main 129199e4). Only the namespace changed. +// The Read* functions are the read sequences of the replaced GameMessages::Handle* functions. + +#include "Amf3.h" +#include "AmfSerialize.h" +#include "BitStreamUtils.h" +#include "dCommonVars.h" +#include "dServer.h" +#include "eAnimationFlags.h" +#include "eCinematicEvent.h" +#include "eEndBehavior.h" +#include "Entity.h" +#include "Game.h" +#include "GeneralUtils.h" +#include "Logger.h" +#include "MessageType/Client.h" +#include "MessageType/Game.h" +#include "ServiceType.h" + +#include +#include + +namespace LegacyGameMessages { + // Declared in GameMessages.h in the original; the Entity* overload forwards to it. + inline void SendPlayFXEffect(const LWOOBJID& entity, int32_t effectID, const std::u16string& effectType, const std::string& name, LWOOBJID secondary, float priority, float scale, bool serialize); + + inline void SendPlayAnimation(Entity* entity, const std::u16string& animationName, float fPriority, float fScale) { + if (!entity) { + LOG("Trying to play animation, but entity var is nullptr!"); + return; + } + + //Stolen from the old DLU codebase as the new one's autogenerated code doesn't work properly for animationIDs longer than 6 characters. + CBITSTREAM; + CMSGHEADER; + std::string sAnimationID = GeneralUtils::UTF16ToWTF8(animationName); + + uint32_t animationIDLength = sAnimationID.size(); + bool bExpectAnimToExist = true; + bool bPlayImmediate = false; + bool bTriggerOnCompleteMsg = false; + + bitStream.Write(entity->GetObjectID()); + bitStream.Write(MessageType::Game::PLAY_ANIMATION); + + bitStream.Write(animationIDLength); + bitStream.Write(LUWString(animationName, animationIDLength)); + + bitStream.Write(bExpectAnimToExist); + + bitStream.Write(bPlayImmediate); + + bitStream.Write(bTriggerOnCompleteMsg); + + bitStream.Write(fPriority != 0.0f); + if (fPriority != 0.0f) bitStream.Write(fPriority); + + bitStream.Write(fScale != 1.0f); + if (fScale != 1.0f) bitStream.Write(fScale); + + SEND_PACKET_BROADCAST; + } + + inline void SendPlayNDAudioEmitter(Entity* entity, const SystemAddress& sysAddr, std::string audioGUID) { + CBITSTREAM; + CMSGHEADER; + + bitStream.Write(entity->GetObjectID()); + bitStream.Write(MessageType::Game::PLAY_ND_AUDIO_EMITTER); + bitStream.Write0(); // callback message data {lwoobjid} + bitStream.Write0(); // audio emitterid {uint32_t} + + uint32_t length = audioGUID.size(); + bitStream.Write(length); + for (uint32_t k = 0; k < length; k++) { + bitStream.Write(audioGUID[k]); + } + + bitStream.Write(0); // size of NDAudioMetaEventName (then print the string like the guid) + bitStream.Write0(); // result {bool} + bitStream.Write0(); // m_TargetObjectIDForNDAudioCallbackMessages {lwoobjid} + + SEND_PACKET_BROADCAST; + } + + inline void SendPlayEmbeddedEffectOnAllClientsNearObject(Entity* entity, std::u16string effectName, const LWOOBJID& fromObjectID, float radius) { + CBITSTREAM; + CMSGHEADER; + + bitStream.Write(entity->GetObjectID()); + bitStream.Write(MessageType::Game::PLAY_EMBEDDED_EFFECT_ON_ALL_CLIENTS_NEAR_OBJECT); + + bitStream.Write(effectName.length()); + for (uint32_t k = 0; k < effectName.length(); k++) { + bitStream.Write(effectName[k]); + } + bitStream.Write(fromObjectID); + bitStream.Write(radius); + + SEND_PACKET_BROADCAST; + } + + inline void SendPlayFXEffect(Entity* entity, int32_t effectID, const std::u16string& effectType, const std::string& name, LWOOBJID secondary, float priority, float scale, bool serialize) { + SendPlayFXEffect(entity->GetObjectID(), effectID, effectType, name, secondary, priority, scale, serialize); + } + + inline void SendPlayFXEffect(const LWOOBJID& entity, int32_t effectID, const std::u16string& effectType, const std::string& name, LWOOBJID secondary, float priority, float scale, bool serialize) { + CBITSTREAM; + CMSGHEADER; + + bitStream.Write(entity); + bitStream.Write(MessageType::Game::PLAY_FX_EFFECT); + + bitStream.Write(effectID != -1); + if (effectID != -1) bitStream.Write(effectID); + + bitStream.Write(effectType.size()); + for (const auto& k : effectType) { + bitStream.Write(k); + } + + bitStream.Write(scale != 1.0f); + if (scale != 1.0f) bitStream.Write(scale); + + bitStream.Write(name.size()); + for (const auto& k : name) { + bitStream.Write(k); + } + + bitStream.Write(priority != 1.0); + if (priority != 1.0) bitStream.Write(priority); + + bitStream.Write(secondary != LWOOBJID_EMPTY); + if (secondary != LWOOBJID_EMPTY) bitStream.Write(secondary); + + bitStream.Write(serialize); + + SEND_PACKET_BROADCAST; + } + + inline void SendStopFXEffect(Entity* entity, bool killImmediate, std::string name) { + CBITSTREAM; + CMSGHEADER; + + bitStream.Write(entity->GetObjectID()); + bitStream.Write(MessageType::Game::STOP_FX_EFFECT); + + bitStream.Write(killImmediate); + bitStream.Write(name.size()); + bitStream.Write(name.c_str(), name.size()); + + SEND_PACKET_BROADCAST; + } + + inline void SendBroadcastTextToChatbox(Entity* entity, const SystemAddress& sysAddr, const std::u16string& attrs, const std::u16string& wsText) { + CBITSTREAM; + CMSGHEADER; + + bitStream.Write(entity->GetObjectID()); + bitStream.Write(MessageType::Game::BROADCAST_TEXT_TO_CHATBOX); + + bitStream.Write(attrs.size()); + for (uint32_t i = 0; i < attrs.size(); ++i) { + bitStream.Write(attrs[i]); + } + bitStream.Write(0x00); // Null Terminator + + uint32_t wsTextLength = wsText.size(); + bitStream.Write(wsTextLength); + for (uint32_t k = 0; k < wsTextLength; k++) { + bitStream.Write(wsText[k]); + } + + SEND_PACKET_BROADCAST; + } + + inline void SendPlay2DAmbientSound(Entity* entity, std::string audioGUID, bool result) { + CBITSTREAM; + CMSGHEADER; + + bitStream.Write(entity->GetObjectID()); + bitStream.Write(MessageType::Game::PLAY2_D_AMBIENT_SOUND); + uint32_t audioGUIDSize = audioGUID.size(); + + bitStream.Write(audioGUIDSize); + for (uint32_t k = 0; k < audioGUIDSize; k++) { + bitStream.Write(audioGUID[k]); + } + bitStream.Write(result); + + SystemAddress sysAddr = entity->GetSystemAddress(); + SEND_PACKET; + } + + inline void SendStop2DAmbientSound(Entity* entity, bool force, std::string audioGUID, bool result) { + CBITSTREAM; + CMSGHEADER; + + bitStream.Write(entity->GetObjectID()); + bitStream.Write(MessageType::Game::STOP2_D_AMBIENT_SOUND); + + uint32_t audioGUIDSize = audioGUID.size(); + + bitStream.Write(force); + bitStream.Write(audioGUIDSize); + + for (uint32_t k = 0; k < audioGUIDSize; k++) { + bitStream.Write(audioGUID[k]); + } + + bitStream.Write(result); + + SystemAddress sysAddr = entity->GetSystemAddress(); + + SEND_PACKET; + } + + inline void SendUIMessageServerToSingleClient(Entity* entity, const SystemAddress& sysAddr, const std::string& message, AMFBaseValue& args) { + CBITSTREAM; + CMSGHEADER; + + bitStream.Write(entity->GetObjectID()); + bitStream.Write(MessageType::Game::UI_MESSAGE_SERVER_TO_SINGLE_CLIENT); + + bitStream.Write(args); + uint32_t strMessageNameLength = message.size(); + bitStream.Write(strMessageNameLength); + + for (uint32_t k = 0; k < strMessageNameLength; k++) { + bitStream.Write(message[k]); + } + + SEND_PACKET; + } + + inline void SendUIMessageServerToSingleClient(const std::string& message, AMFBaseValue& args, const SystemAddress& sysAddr) { + CBITSTREAM; + CMSGHEADER; + + LWOOBJID empty = 0; + bitStream.Write(empty); + bitStream.Write(MessageType::Game::UI_MESSAGE_SERVER_TO_ALL_CLIENTS); // This is intentional to allow the server to send a ui message to a client via their system address. + + bitStream.Write(args); + uint32_t strMessageNameLength = message.size(); + bitStream.Write(strMessageNameLength); + + for (uint32_t k = 0; k < strMessageNameLength; k++) { + bitStream.Write(message[k]); + } + + SEND_PACKET; + } + + inline void SendUIMessageServerToAllClients(const std::string& message, AMFBaseValue& args) { + CBITSTREAM; + CMSGHEADER; + + LWOOBJID empty = 0; + bitStream.Write(empty); + bitStream.Write(MessageType::Game::UI_MESSAGE_SERVER_TO_ALL_CLIENTS); + + bitStream.Write(args); + uint32_t strMessageNameLength = message.size(); + bitStream.Write(strMessageNameLength); + + for (uint32_t k = 0; k < strMessageNameLength; k++) { + bitStream.Write(message[k]); + } + + SEND_PACKET_BROADCAST; + } + + inline void SendStartCelebrationEffect(Entity* entity, const SystemAddress& sysAddr, int celebrationID) { + CBITSTREAM; + CMSGHEADER; + + bitStream.Write(entity->GetObjectID()); + bitStream.Write(MessageType::Game::START_CELEBRATION_EFFECT); + + bitStream.Write(0); //animation + bitStream.Write0(); //No custom bg obj + bitStream.Write0(); //custom path + bitStream.Write0(); //leadin + bitStream.Write0(); //leadout + bitStream.Write1(); + bitStream.Write(celebrationID); + bitStream.Write(0.0f); //duration + bitStream.Write(0); //icon + bitStream.Write(0); //text + bitStream.Write(0); //mixer + bitStream.Write(0); //cue + bitStream.Write(0); //pathnodename + bitStream.Write(0); //soundguid + bitStream.Write(0); //subtext + + SEND_PACKET; + } + + inline void SendDisplayMessageBox(LWOOBJID objectId, bool bShow, LWOOBJID callbackClient, const std::u16string& identifier, int32_t imageID, const std::u16string& text, const std::u16string& userData, const SystemAddress& sysAddr) { + CBITSTREAM; + CMSGHEADER; + + bitStream.Write(objectId); + bitStream.Write(MessageType::Game::DISPLAY_MESSAGE_BOX); + + bitStream.Write(bShow); + bitStream.Write(callbackClient); + + bitStream.Write(identifier.size()); + for (const auto character : identifier) { + bitStream.Write(character); + } + + bitStream.Write(imageID); + + bitStream.Write(text.size()); + for (const auto character : text) { + bitStream.Write(character); + } + + bitStream.Write(userData.size()); + for (const auto character : userData) { + bitStream.Write(character); + } + + if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST; + SEND_PACKET; + } + + inline void SendDisplayChatBubble(LWOOBJID objectId, const std::u16string& text, const SystemAddress& sysAddr) { + // MessageType::Game::DISPLAY_CHAT_BUBBLE + CBITSTREAM; + CMSGHEADER; + + bitStream.Write(objectId); + bitStream.Write(MessageType::Game::DISPLAY_CHAT_BUBBLE); + + bitStream.Write(text.size()); + for (const auto character : text) { + bitStream.Write(character); + } + + if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST; + SEND_PACKET; + } + + inline void SendChangeIdleFlags(LWOOBJID objectId, eAnimationFlags flagsOn, eAnimationFlags flagsOff, const SystemAddress& sysAddr) { + CBITSTREAM; + CMSGHEADER; + + bitStream.Write(objectId); + bitStream.Write(MessageType::Game::CHANGE_IDLE_FLAGS); + bitStream.Write(flagsOff != eAnimationFlags::IDLE_NONE); + if (flagsOff != eAnimationFlags::IDLE_NONE) bitStream.Write(flagsOff); + bitStream.Write(flagsOn != eAnimationFlags::IDLE_NONE); + if (flagsOn != eAnimationFlags::IDLE_NONE) bitStream.Write(flagsOn); + + SEND_PACKET_BROADCAST; + } + + inline void SendSetNamebillboardState(const SystemAddress& sysAddr, LWOOBJID objectId) { + CBITSTREAM; + CMSGHEADER; + + bitStream.Write(objectId); + bitStream.Write(MessageType::Game::SET_NAME_BILLBOARD_STATE); + + // Technically these bits would be written, however the client does not + // contain a deserialize method to actually deserialize, so we are leaving it out. + // As such this GM only turns the billboard off. + + // bitStream.Write(overrideDefault); + // bitStream.Write(state); + + if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST + else SEND_PACKET + } + + inline void SendShowBillboardInteractIcon(const SystemAddress& sysAddr, LWOOBJID objectId) { + CBITSTREAM; + CMSGHEADER; + + bitStream.Write(objectId); + bitStream.Write(MessageType::Game::SHOW_BILLBOARD_INTERACT_ICON); + + if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST + else SEND_PACKET + } + + inline void SendPlayCinematic(LWOOBJID objectId, std::u16string pathName, const SystemAddress& sysAddr, + bool allowGhostUpdates, bool bCloseMultiInteract, bool bSendServerNotify, bool bUseControlledObjectForAudioListener, + eEndBehavior endBehavior, bool hidePlayerDuringCine, float leadIn, bool leavePlayerLockedWhenFinished, + bool lockPlayer, bool result, bool skipIfSamePath, float startTimeAdvance) { + CBITSTREAM; + CMSGHEADER; + + bitStream.Write(objectId); + bitStream.Write(MessageType::Game::PLAY_CINEMATIC); + + bitStream.Write(allowGhostUpdates); + bitStream.Write(bCloseMultiInteract); + bitStream.Write(bSendServerNotify); + bitStream.Write(bUseControlledObjectForAudioListener); + + bitStream.Write(endBehavior != eEndBehavior::RETURN); + if (endBehavior != eEndBehavior::RETURN) bitStream.Write(endBehavior); + + bitStream.Write(hidePlayerDuringCine); + + bitStream.Write(leadIn != -1); + if (leadIn != -1) bitStream.Write(leadIn); + + bitStream.Write(leavePlayerLockedWhenFinished); + bitStream.Write(lockPlayer); + + bitStream.Write(pathName.size()); + for (char16_t c : pathName) { + bitStream.Write(c); + } + + bitStream.Write(result); + + bitStream.Write(skipIfSamePath); + + bitStream.Write(startTimeAdvance); + + if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST; + SEND_PACKET; + } + + inline void SendEndCinematic(LWOOBJID objectId, std::u16string pathName, const SystemAddress& sysAddr, + float leadOut, bool leavePlayerLocked) { + CBITSTREAM; + CMSGHEADER; + + bitStream.Write(objectId); + bitStream.Write(MessageType::Game::END_CINEMATIC); + + bitStream.Write(leadOut != -1); + if (leadOut != -1) bitStream.Write(leadOut); + + bitStream.Write(leavePlayerLocked); + + bitStream.Write(pathName.size()); + for (uint32_t i = 0; i < pathName.size(); i++) { + bitStream.Write(pathName[i]); + } + + if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST; + SEND_PACKET; + } + + inline void SendSlashCommandFeedbackText(Entity* entity, std::u16string text) { + CBITSTREAM; + CMSGHEADER; + + bitStream.Write(entity->GetObjectID()); + bitStream.Write(MessageType::Game::SLASH_COMMAND_TEXT_FEEDBACK); + bitStream.Write(text.size()); + bitStream.Write(text); + auto sysAddr = entity->GetSystemAddress(); + SEND_PACKET; + } + + inline void SendPlayEmote(LWOOBJID objectId, int32_t emoteID, LWOOBJID target, const SystemAddress& sysAddr) { + CBITSTREAM; + CMSGHEADER; + + bitStream.Write(objectId); + bitStream.Write(MessageType::Game::PLAY_EMOTE); + + bitStream.Write(emoteID); + bitStream.Write(target); + + if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST; + SEND_PACKET; + } + + inline void SendSetEmoteLockState(Entity* entity, bool bLock, int emoteID) { + CBITSTREAM; + CMSGHEADER; + + bitStream.Write(entity->GetObjectID()); + bitStream.Write(MessageType::Game::SET_EMOTE_LOCK_STATE); + bitStream.Write(bLock); + bitStream.Write(emoteID); + + SystemAddress sysAddr = entity->GetSystemAddress(); + SEND_PACKET; + } + + struct LegacyMessageBoxResponse { bool ok{}; int32_t iButton{}; std::u16string identifier; std::u16string userData; }; + inline LegacyMessageBoxResponse ReadMessageBoxResponse(RakNet::BitStream& inStream) { + int32_t iButton; + uint32_t identifierLength; + std::u16string identifier; + uint32_t userDataLength; + std::u16string userData; + + inStream.Read(iButton); + + inStream.Read(identifierLength); + if (identifierLength > MAX_MESSAGE_LENGTH) return {}; + for (size_t i = 0; i < identifierLength; i++) { + char16_t character; + inStream.Read(character); + identifier.push_back(character); + } + + inStream.Read(userDataLength); + if (userDataLength > MAX_MESSAGE_LENGTH) return {}; + for (size_t i = 0; i < userDataLength; i++) { + char16_t character; + inStream.Read(character); + userData.push_back(character); + } + return { true, iButton, identifier, userData }; + } + + struct LegacyChoiceBoxRespond { bool ok{}; int32_t iButton{}; std::u16string buttonIdentifier; std::u16string identifier; }; + inline LegacyChoiceBoxRespond ReadChoiceBoxRespond(RakNet::BitStream& inStream) { + int32_t iButton; + uint32_t buttonIdentifierLength; + std::u16string buttonIdentifier; + uint32_t identifierLength; + std::u16string identifier; + + inStream.Read(buttonIdentifierLength); + if (buttonIdentifierLength > MAX_MESSAGE_LENGTH) return {}; + for (size_t i = 0; i < buttonIdentifierLength; i++) { + char16_t character; + inStream.Read(character); + buttonIdentifier.push_back(character); + } + + inStream.Read(iButton); + + inStream.Read(identifierLength); + if (identifierLength > MAX_MESSAGE_LENGTH) return {}; + for (size_t i = 0; i < identifierLength; i++) { + char16_t character; + inStream.Read(character); + identifier.push_back(character); + } + return { true, iButton, buttonIdentifier, identifier }; + } + + struct LegacyCinematicUpdate { eCinematicEvent event; float_t overallTime; std::u16string pathName; float_t pathTime; int32_t waypoint; }; + inline LegacyCinematicUpdate ReadCinematicUpdate(RakNet::BitStream& inStream) { + eCinematicEvent event; + if (!inStream.ReadBit()) { + event = eCinematicEvent::STARTED; + } else { + inStream.Read(event); + } + + float_t overallTime; + if (!inStream.ReadBit()) { + overallTime = -1.0f; + } else { + inStream.Read(overallTime); + } + + uint32_t pathNameLength; + inStream.Read(pathNameLength); + + std::u16string pathName; + for (size_t i = 0; i < pathNameLength; i++) { + char16_t character; + inStream.Read(character); + pathName.push_back(character); + } + + float_t pathTime; + if (!inStream.ReadBit()) { + pathTime = -1.0f; + } else { + inStream.Read(pathTime); + } + + int32_t waypoint; + if (!inStream.ReadBit()) { + waypoint = -1; + } else { + inStream.Read(waypoint); + } + return { event, overallTime, pathName, pathTime, waypoint }; + } + + struct LegacyPlayEmote { int32_t emoteID; LWOOBJID targetID; }; + inline LegacyPlayEmote ReadPlayEmote(RakNet::BitStream& inStream) { + int32_t emoteID; + LWOOBJID targetID; + + inStream.Read(emoteID); + inStream.Read(targetID); + return { emoteID, targetID }; + } +} + +#endif // EFFECTSMESSAGESLEGACY_H