mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-19 11:12:49 +00:00
refactor: effects, audio, animation and UI text game messages as structs
Converts PlayAnimation, PlayNDAudioEmitter, PlayEmbeddedEffectOnAllClientsNearObject,
PlayFXEffect, StopFXEffect, BroadcastTextToChatbox, Play2DAmbientSound,
Stop2DAmbientSound, UIMessageServerToSingleClient, UIMessageServerToAllClients,
StartCelebrationEffect, DisplayMessageBox, DisplayChatBubble, ChangeIdleFlags,
SetNameBillboardState, ShowBillboardInteractIcon, PlayCinematic, EndCinematic,
SlashCommandTextFeedback, PlayEmote and SetEmoteLockState (21 old Send
functions, 23 with overloads) and the received MessageBoxRespond,
ChoiceBoxRespond, CinematicUpdate and PlayEmote to NetGameMsgs in
EffectsMessages.{h,cpp}. The high traffic messages get a constructor for their
required fields. UI messages own their AMF arguments. Every caller is switched,
the received messages are registered in GameMessageHandler's map, and the old
functions and switch cases are deleted. Handlers are copied verbatim.
No wire change and no change in recipients: functions that always broadcast
whatever address they were given are sent with Send(UNASSIGNED_SYSTEM_ADDRESS),
functions that only did SEND_PACKET use SendToClient. Quirks are kept and
documented on the structs (PlayAnimation's UTF-8 sized name, the always written
null terminator in BroadcastTextToChatbox, StartCelebrationEffect always
writing celebrationID, SetNameBillboardState having no payload).
Verified byte for byte against a frozen verbatim copy of the old functions over
an input grid, to one client and broadcast; received messages compared with the
old handlers' read sequences and every truncated payload rejected; hand
computed golden bytes; round trips; a deliberate width mutation made the tests
fail. The byte-equality helper gains a Broadcast mode for functions that
ignored their address.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,7 @@ set(DGAME_DGAMEMESSAGES_SOURCES
|
||||
"BuildingMessages.cpp"
|
||||
"GameMessageDecoder.cpp"
|
||||
"GameMessageHandler.cpp"
|
||||
"EffectsMessages.cpp"
|
||||
"GameMessages.cpp"
|
||||
"MissionMessages.cpp"
|
||||
"PetMessages.cpp"
|
||||
|
||||
489
dGame/dGameMessages/EffectsMessages.cpp
Normal file
489
dGame/dGameMessages/EffectsMessages.cpp
Normal file
@@ -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 <stdexcept>
|
||||
|
||||
namespace {
|
||||
// Reads an AMF3 array written with Write<AMFBaseValue&>. 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<AMFArrayValue*>(value.get()));
|
||||
return true;
|
||||
} catch (const std::exception&) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace GameMessages {
|
||||
void PlayAnimation::Serialize(RakNet::BitStream& bitStream) const {
|
||||
const auto animationIDLength = static_cast<uint32_t>(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<uint32_t>(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<LWOOBJID>(bitStream, NDAudioCallbackMessageData, 0);
|
||||
BitStreamUtils::WriteOptional<uint32_t>(bitStream, NDAudioEmitterID, 0);
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, NDAudioEventGUID);
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, NDAudioMetaEventName);
|
||||
bitStream.Write(result);
|
||||
BitStreamUtils::WriteOptional(bitStream, targetObjectIDForNDAudioCallbackMessages, LWOOBJID_EMPTY);
|
||||
}
|
||||
|
||||
bool PlayNDAudioEmitter::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(BitStreamUtils::ReadOptional<LWOOBJID>(bitStream, NDAudioCallbackMessageData, 0));
|
||||
VALIDATE_READ(BitStreamUtils::ReadOptional<uint32_t>(bitStream, NDAudioEmitterID, 0));
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, NDAudioEventGUID));
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(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<uint32_t>(bitStream, effectName);
|
||||
bitStream.Write(fromObjectID);
|
||||
bitStream.Write(radius);
|
||||
}
|
||||
|
||||
bool PlayEmbeddedEffectOnAllClientsNearObject::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(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<uint32_t>(bitStream, effectType);
|
||||
BitStreamUtils::WriteOptional(bitStream, scale, 1.0f);
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(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<uint32_t>(bitStream, effectType));
|
||||
VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, scale, 1.0f));
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(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<uint32_t>(bitStream, name);
|
||||
}
|
||||
|
||||
bool StopFXEffect::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(bitStream.Read(killImmediate));
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, name));
|
||||
return true;
|
||||
}
|
||||
|
||||
void BroadcastTextToChatbox::Serialize(RakNet::BitStream& bitStream) const {
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, attrs);
|
||||
bitStream.Write<uint16_t>(0x00); // null terminator, always written
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, wsText);
|
||||
}
|
||||
|
||||
bool BroadcastTextToChatbox::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, attrs));
|
||||
uint16_t nullTerminator{};
|
||||
VALIDATE_READ(bitStream.Read(nullTerminator));
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, wsText));
|
||||
return true;
|
||||
}
|
||||
|
||||
void Play2DAmbientSound::Serialize(RakNet::BitStream& bitStream) const {
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, audioGUID);
|
||||
bitStream.Write(result);
|
||||
}
|
||||
|
||||
bool Play2DAmbientSound::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, audioGUID));
|
||||
VALIDATE_READ(bitStream.Read(result));
|
||||
return true;
|
||||
}
|
||||
|
||||
void Stop2DAmbientSound::Serialize(RakNet::BitStream& bitStream) const {
|
||||
bitStream.Write(force);
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, audioGUID);
|
||||
bitStream.Write(result);
|
||||
}
|
||||
|
||||
bool Stop2DAmbientSound::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(bitStream.Read(force));
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, audioGUID));
|
||||
VALIDATE_READ(bitStream.Read(result));
|
||||
return true;
|
||||
}
|
||||
|
||||
void UIMessageServerToSingleClient::Serialize(RakNet::BitStream& bitStream) const {
|
||||
bitStream.Write<AMFBaseValue&>(const_cast<AMFArrayValue&>(args));
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, strMessageName);
|
||||
}
|
||||
|
||||
bool UIMessageServerToSingleClient::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(ReadAmfArray(bitStream, args));
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, strMessageName));
|
||||
return true;
|
||||
}
|
||||
|
||||
void UIMessageServerToAllClients::Serialize(RakNet::BitStream& bitStream) const {
|
||||
bitStream.Write<AMFBaseValue&>(const_cast<AMFArrayValue&>(args));
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, strMessageName);
|
||||
}
|
||||
|
||||
bool UIMessageServerToAllClients::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(ReadAmfArray(bitStream, args));
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, strMessageName));
|
||||
return true;
|
||||
}
|
||||
|
||||
void StartCelebrationEffect::Serialize(RakNet::BitStream& bitStream) const {
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, animation);
|
||||
BitStreamUtils::WriteOptional<LOT>(bitStream, backgroundObject, 11164);
|
||||
BitStreamUtils::WriteOptional<LOT>(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<uint32_t>(bitStream, mainText);
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, mixerProgram);
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, musicCue);
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, pathNodeName);
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, soundGUID);
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, subText);
|
||||
}
|
||||
|
||||
bool StartCelebrationEffect::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, animation));
|
||||
VALIDATE_READ(BitStreamUtils::ReadOptional<LOT>(bitStream, backgroundObject, 11164));
|
||||
VALIDATE_READ(BitStreamUtils::ReadOptional<LOT>(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<uint32_t>(bitStream, mainText));
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, mixerProgram));
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, musicCue));
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, pathNodeName));
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, soundGUID));
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, subText));
|
||||
return true;
|
||||
}
|
||||
|
||||
void DisplayMessageBox::Serialize(RakNet::BitStream& bitStream) const {
|
||||
bitStream.Write(bShow);
|
||||
bitStream.Write(callbackClient);
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, identifier);
|
||||
bitStream.Write(imageID);
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, text);
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, userData);
|
||||
}
|
||||
|
||||
bool DisplayMessageBox::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(bitStream.Read(bShow));
|
||||
VALIDATE_READ(bitStream.Read(callbackClient));
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, identifier));
|
||||
VALIDATE_READ(bitStream.Read(imageID));
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, text));
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, userData));
|
||||
return true;
|
||||
}
|
||||
|
||||
void MessageBoxRespond::Serialize(RakNet::BitStream& bitStream) const {
|
||||
bitStream.Write(iButton);
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, identifier);
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, userData);
|
||||
}
|
||||
|
||||
bool MessageBoxRespond::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(bitStream.Read(iButton));
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, identifier));
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(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<ScriptedActivityComponent>();
|
||||
|
||||
if (scriptedActivityComponent != nullptr) {
|
||||
scriptedActivityComponent->HandleMessageBoxResponse(userEntity, GeneralUtils::UTF16ToWTF8(identifier));
|
||||
}
|
||||
|
||||
auto* racingControlComponent = entity->GetComponent<RacingControlComponent>();
|
||||
|
||||
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<uint32_t>(bitStream, buttonIdentifier);
|
||||
bitStream.Write(iButton);
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, identifier);
|
||||
}
|
||||
|
||||
bool ChoiceBoxRespond::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, buttonIdentifier));
|
||||
VALIDATE_READ(bitStream.Read(iButton));
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(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<uint32_t>(bitStream, wsText);
|
||||
}
|
||||
|
||||
bool DisplayChatBubble::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(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<uint32_t>(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<uint32_t>(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<uint32_t>(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<uint32_t>(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<uint32_t>(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<uint32_t>(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<Entity*> 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<uint32_t>(bitStream, text);
|
||||
}
|
||||
|
||||
bool SlashCommandTextFeedback::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(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<CDEmoteTableTable>();
|
||||
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<MissionComponent>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
327
dGame/dGameMessages/EffectsMessages.h
Normal file
327
dGame/dGameMessages/EffectsMessages.h
Normal file
@@ -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 <string>
|
||||
|
||||
// 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
|
||||
@@ -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<SetFlag>(); } },
|
||||
{ HAS_BEEN_COLLECTED, []() { return std::make_unique<HasBeenCollected>(); } },
|
||||
|
||||
// Effects, emotes, cinematics, UI
|
||||
{ PLAY_EMOTE, []() { return std::make_unique<PlayEmote>(); } },
|
||||
{ MESSAGE_BOX_RESPOND, []() { return std::make_unique<MessageBoxRespond>(); } },
|
||||
{ CHOICE_BOX_RESPOND, []() { return std::make_unique<ChoiceBoxRespond>(); } },
|
||||
{ CINEMATIC_UPDATE, []() { return std::make_unique<CinematicUpdate>(); } },
|
||||
|
||||
// Pets
|
||||
{ PET_TAMING_TRY_BUILD, []() { return std::make_unique<PetTamingTryBuild>(); } },
|
||||
{ NOTIFY_TAMING_BUILD_SUCCESS, []() { return std::make_unique<NotifyTamingBuildSuccess>(); } },
|
||||
@@ -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;
|
||||
|
||||
@@ -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<char>(audioGUID[k]);
|
||||
}
|
||||
|
||||
bitStream.Write<uint32_t>(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<AMFBaseValue&>(args);
|
||||
uint32_t strMessageNameLength = message.size();
|
||||
bitStream.Write(strMessageNameLength);
|
||||
|
||||
for (uint32_t k = 0; k < strMessageNameLength; k++) {
|
||||
bitStream.Write<char>(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<AMFBaseValue&>(args);
|
||||
uint32_t strMessageNameLength = message.size();
|
||||
bitStream.Write(strMessageNameLength);
|
||||
|
||||
for (uint32_t k = 0; k < strMessageNameLength; k++) {
|
||||
bitStream.Write<char>(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<AMFBaseValue&>(args);
|
||||
uint32_t strMessageNameLength = message.size();
|
||||
bitStream.Write(strMessageNameLength);
|
||||
|
||||
for (uint32_t k = 0; k < strMessageNameLength; k++) {
|
||||
bitStream.Write<char>(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<uint32_t>(effectName.length());
|
||||
for (uint32_t k = 0; k < effectName.length(); k++) {
|
||||
bitStream.Write<uint16_t>(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<uint32_t>(effectType.size());
|
||||
for (const auto& k : effectType) {
|
||||
bitStream.Write<uint16_t>(k);
|
||||
}
|
||||
|
||||
bitStream.Write(scale != 1.0f);
|
||||
if (scale != 1.0f) bitStream.Write(scale);
|
||||
|
||||
bitStream.Write<uint32_t>(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<uint32_t>(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<uint32_t>(attrs.size());
|
||||
for (uint32_t i = 0; i < attrs.size(); ++i) {
|
||||
bitStream.Write<uint16_t>(attrs[i]);
|
||||
}
|
||||
bitStream.Write<uint16_t>(0x00); // Null Terminator
|
||||
|
||||
uint32_t wsTextLength = wsText.size();
|
||||
bitStream.Write(wsTextLength);
|
||||
for (uint32_t k = 0; k < wsTextLength; k++) {
|
||||
bitStream.Write<uint16_t>(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<char>(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<char>(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<uint32_t>(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<float>(0.0f); //duration
|
||||
bitStream.Write<uint32_t>(0); //icon
|
||||
bitStream.Write<uint32_t>(0); //text
|
||||
bitStream.Write<uint32_t>(0); //mixer
|
||||
bitStream.Write<uint32_t>(0); //cue
|
||||
bitStream.Write<uint32_t>(0); //pathnodename
|
||||
bitStream.Write<uint32_t>(0); //soundguid
|
||||
bitStream.Write<uint32_t>(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<uint32_t>(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<uint32_t>(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<eCinematicEvent>(event);
|
||||
}
|
||||
|
||||
float_t overallTime;
|
||||
if (!inStream.ReadBit()) {
|
||||
overallTime = -1.0f;
|
||||
} else {
|
||||
inStream.Read<float_t>(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<float_t>(pathTime);
|
||||
}
|
||||
|
||||
int32_t waypoint;
|
||||
if (!inStream.ReadBit()) {
|
||||
waypoint = -1;
|
||||
} else {
|
||||
inStream.Read<int32_t>(waypoint);
|
||||
}
|
||||
|
||||
std::vector<Entity*> 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<ScriptedActivityComponent>();
|
||||
|
||||
if (scriptedActivityComponent != nullptr) {
|
||||
scriptedActivityComponent->HandleMessageBoxResponse(userEntity, GeneralUtils::UTF16ToWTF8(identifier));
|
||||
}
|
||||
|
||||
auto* racingControlComponent = entity->GetComponent<RacingControlComponent>();
|
||||
|
||||
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<uint32_t>(identifier.size());
|
||||
for (const auto character : identifier) {
|
||||
bitStream.Write(character);
|
||||
}
|
||||
|
||||
bitStream.Write(imageID);
|
||||
|
||||
bitStream.Write<uint32_t>(text.size());
|
||||
for (const auto character : text) {
|
||||
bitStream.Write(character);
|
||||
}
|
||||
|
||||
bitStream.Write<uint32_t>(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<uint32_t>(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<bool>(flagsOff != eAnimationFlags::IDLE_NONE);
|
||||
if (flagsOff != eAnimationFlags::IDLE_NONE) bitStream.Write(flagsOff);
|
||||
bitStream.Write<bool>(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<CDEmoteTableTable>();
|
||||
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<MissionComponent>();
|
||||
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<LevelProgressionComponent>();
|
||||
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<uint32_t>(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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user