Skip to content

Commit

Permalink
tweak: sync dialogue
Browse files Browse the repository at this point in the history
  • Loading branch information
RobbeBryssinck committed May 5, 2022
1 parent 671cf08 commit 7dc48a1
Show file tree
Hide file tree
Showing 16 changed files with 190 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
/**
* @brief Dispatched whenever an actor talks
*/
struct ActorSpokeEvent
struct DialogueEvent
{
ActorSpokeEvent(uint32_t aActorID, String aVoiceFile)
DialogueEvent(uint32_t aActorID, String aVoiceFile)
: ActorID(aActorID), VoiceFile(aVoiceFile)
{}

Expand Down
15 changes: 10 additions & 5 deletions Code/client/Games/References.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@

#include <Events/LockChangeEvent.h>
#include <Events/InitPackageEvent.h>
#include <Events/ActorSpokeEvent.h>
#include <Events/DialogueEvent.h>

#include <TiltedCore/Serialization.hpp>

Expand Down Expand Up @@ -706,16 +706,21 @@ void TP_MAKE_THISCALL(HookInitFromPackage, void, TESPackage* apPackage, TESObjec
return ThisCall(RealInitFromPackage, apThis, apPackage, apTarget, arActor);
}

TP_THIS_FUNCTION(TSpeakSoundFunction, bool, Actor, char* apName, uint32_t* a3, uint32_t a4, uint32_t a5, uint32_t a6, uint64_t a7, uint64_t a8, uint64_t a9, bool a10, uint64_t a11, bool a12, bool a13, bool a14);
TP_THIS_FUNCTION(TSpeakSoundFunction, bool, Actor, const char* apName, uint32_t* a3, uint32_t a4, uint32_t a5, uint32_t a6, uint64_t a7, uint64_t a8, uint64_t a9, bool a10, uint64_t a11, bool a12, bool a13, bool a14);
static TSpeakSoundFunction* RealSpeakSoundFunction = nullptr;

bool TP_MAKE_THISCALL(HookSpeakSoundFunction, Actor, char* apName, uint32_t* a3, uint32_t a4, uint32_t a5, uint32_t a6, uint64_t a7, uint64_t a8, uint64_t a9, bool a10, uint64_t a11, bool a12, bool a13, bool a14)
bool TP_MAKE_THISCALL(HookSpeakSoundFunction, Actor, const char* apName, uint32_t* a3, uint32_t a4, uint32_t a5, uint32_t a6, uint64_t a7, uint64_t a8, uint64_t a9, bool a10, uint64_t a11, bool a12, bool a13, bool a14)
{
World::Get().GetRunner().Trigger(ActorSpokeEvent(apThis->formID, apName));
spdlog::debug("a3: {:X}, a4: {}, a5: {}, a6: {}, a7: {}, a8: {:X}, a9: {:X}, a10: {}, a11: {:X}, a12: {}, a13: {}, a14: {}",
(uint64_t)a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14);

if (apThis->GetExtension()->IsLocal())
World::Get().GetRunner().Trigger(DialogueEvent(apThis->formID, apName));

return ThisCall(RealSpeakSoundFunction, apThis, apName, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14);
}

void Actor::SpeakSound(char* pFile)
void Actor::SpeakSound(const char* pFile)
{
uint32_t handle[3]{};
handle[0] = -1;
Expand Down
2 changes: 1 addition & 1 deletion Code/client/Games/Skyrim/Actor.h
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ struct Actor : TESObjectREFR
void Respawn() noexcept;
void PickUpObject(TESObjectREFR* apObject, int32_t aCount, bool aUnk1, float aUnk2) noexcept;
void DropObject(TESBoundObject* apObject, ExtraDataList* apExtraData, int32_t aCount, NiPoint3* apLocation, NiPoint3* apRotation) noexcept;
void SpeakSound(char* pFile);
void SpeakSound(const char* pFile);

enum ActorFlags
{
Expand Down
6 changes: 6 additions & 0 deletions Code/client/Services/CharacterService.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ struct NotifyRespawn;
struct LeaveBeastFormEvent;
struct AddExperienceEvent;
struct NotifySyncExperience;
struct DialogueEvent;
struct NotifyDialogue;

struct Actor;
struct World;
Expand Down Expand Up @@ -71,6 +73,8 @@ struct CharacterService
void OnLeaveBeastForm(const LeaveBeastFormEvent& acEvent) const noexcept;
void OnAddExperienceEvent(const AddExperienceEvent& acEvent) noexcept;
void OnNotifySyncExperience(const NotifySyncExperience& acMessage) noexcept;
void OnDialogueEvent(const DialogueEvent& acEvent) noexcept;
void OnNotifyDialogue(const NotifyDialogue& acMessage) noexcept;

private:

Expand Down Expand Up @@ -118,4 +122,6 @@ struct CharacterService
entt::scoped_connection m_leaveBeastFormConnection;
entt::scoped_connection m_addExperienceEventConnection;
entt::scoped_connection m_syncExperienceConnection;
entt::scoped_connection m_dialogueEventConnection;
entt::scoped_connection m_dialogueSyncConnection;
};
8 changes: 4 additions & 4 deletions Code/client/Services/Debug/DebugService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#include <Services/QuestService.h>

#include <Events/UpdateEvent.h>
#include <Events/ActorSpokeEvent.h>
#include <Events/DialogueEvent.h>

#include <Games/References.h>

Expand Down Expand Up @@ -87,7 +87,7 @@ DebugService::DebugService(entt::dispatcher& aDispatcher, World& aWorld, Transpo
{
m_updateConnection = m_dispatcher.sink<UpdateEvent>().connect<&DebugService::OnUpdate>(this);
m_drawImGuiConnection = aImguiService.OnDraw.connect<&DebugService::OnDraw>(this);
m_actorSpokeConnection = m_dispatcher.sink<ActorSpokeEvent>().connect<&DebugService::OnActorSpokeEvent>(this);
m_actorSpokeConnection = m_dispatcher.sink<DialogueEvent>().connect<&DebugService::OnActorSpokeEvent>(this);
}

void DebugService::OnUpdate(const UpdateEvent& acUpdateEvent) noexcept
Expand Down Expand Up @@ -147,12 +147,12 @@ void DebugService::OnUpdate(const UpdateEvent& acUpdateEvent) noexcept
s_f8Pressed = false;
}

void DebugService::OnActorSpokeEvent(const ActorSpokeEvent& acEvent) noexcept
void DebugService::OnActorSpokeEvent(const DialogueEvent& acEvent) noexcept
{
m_spokenActorId = acEvent.ActorID;
m_voiceFileName = acEvent.VoiceFile;

spdlog::warn("Actor spoke, id: {:X}, file: {}", acEvent.ActorID, acEvent.VoiceFile.c_str());
spdlog::debug("Actor spoke, id: {:X}, file: {}", acEvent.ActorID, acEvent.VoiceFile.c_str());
}

uint64_t DebugService::DisplayGraphDescriptorKey(BSAnimationGraphManager* pManager) noexcept
Expand Down
4 changes: 2 additions & 2 deletions Code/client/Services/DebugService.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ struct World;
struct ImguiService;

struct UpdateEvent;
struct ActorSpokeEvent;
struct DialogueEvent;

struct TransportService;
struct BSAnimationGraphManager;
Expand All @@ -22,7 +22,7 @@ struct DebugService
TP_NOCOPYMOVE(DebugService);

void OnUpdate(const UpdateEvent&) noexcept;
void OnActorSpokeEvent(const ActorSpokeEvent&) noexcept;
void OnActorSpokeEvent(const DialogueEvent&) noexcept;

protected:

Expand Down
58 changes: 58 additions & 0 deletions Code/client/Services/Generic/CharacterService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <Events/InitPackageEvent.h>
#include <Events/LeaveBeastFormEvent.h>
#include <Events/AddExperienceEvent.h>
#include <Events/DialogueEvent.h>

#include <Structs/ActionEvent.h>
#include <Messages/CancelAssignmentRequest.h>
Expand All @@ -57,6 +58,8 @@
#include <Messages/NotifyRespawn.h>
#include <Messages/SyncExperienceRequest.h>
#include <Messages/NotifySyncExperience.h>
#include <Messages/DialogueRequest.h>
#include <Messages/NotifyDialogue.h>

#include <World.h>
#include <Games/TES.h>
Expand Down Expand Up @@ -101,6 +104,9 @@ CharacterService::CharacterService(World& aWorld, entt::dispatcher& aDispatcher,

m_addExperienceEventConnection = m_dispatcher.sink<AddExperienceEvent>().connect<&CharacterService::OnAddExperienceEvent>(this);
m_syncExperienceConnection = m_dispatcher.sink<NotifySyncExperience>().connect<&CharacterService::OnNotifySyncExperience>(this);

m_dialogueEventConnection = m_dispatcher.sink<DialogueEvent>().connect<&CharacterService::OnDialogueEvent>(this);
m_dialogueSyncConnection = m_dispatcher.sink<NotifyDialogue>().connect<&CharacterService::OnNotifyDialogue>(this);
}

void CharacterService::OnActorAdded(const ActorAddedEvent& acEvent) noexcept
Expand Down Expand Up @@ -984,6 +990,58 @@ void CharacterService::OnNotifySyncExperience(const NotifySyncExperience& acMess
pPlayer->AddSkillExperience(pPlayerEx->LastUsedCombatSkill, acMessage.Experience);
}

void CharacterService::OnDialogueEvent(const DialogueEvent& acEvent) noexcept
{
if (!m_transport.IsConnected())
return;

auto view = m_world.view<FormIdComponent>(entt::exclude<ObjectComponent>);
auto entityIt = std::find_if(view.begin(), view.end(), [view, formId = acEvent.ActorID](auto entity) {
return view.get<FormIdComponent>(entity).Id == formId;
});

if (entityIt == view.end())
return;

auto serverIdRes = Utils::GetServerId(*entityIt);
if (!serverIdRes)
{
spdlog::error("{}: server id not found for form id {:X}", __FUNCTION__, acEvent.ActorID);
return;
}

DialogueRequest request{};
request.ServerId = serverIdRes.value();
request.SoundFilename = acEvent.VoiceFile;

m_transport.Send(request);
}

void CharacterService::OnNotifyDialogue(const NotifyDialogue& acMessage) noexcept
{
auto remoteView = m_world.view<RemoteComponent, FormIdComponent>();
const auto remoteIt = std::find_if(std::begin(remoteView), std::end(remoteView), [remoteView, Id = acMessage.ServerId](auto entity)
{
return remoteView.get<RemoteComponent>(entity).Id == Id;
});

if (remoteIt == std::end(remoteView))
{
spdlog::warn("Actor for dialogue with remote id {:X} not found.", acMessage.ServerId);
return;
}

auto formIdComponent = remoteView.get<FormIdComponent>(*remoteIt);
const TESForm* pForm = TESForm::GetById(formIdComponent.Id);
Actor* pActor = Cast<Actor>(pForm);

if (!pActor)
return;

// TODO(cosideci): pActor->StopCurrentDialogue() or something
pActor->SpeakSound(acMessage.SoundFilename.c_str());
}

void CharacterService::ProcessNewEntity(entt::entity aEntity) const noexcept
{
if (!m_transport.IsOnline())
Expand Down
3 changes: 2 additions & 1 deletion Code/encoding/Messages/ClientMessageFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include <Messages/SendChatMessageRequest.h>
#include <Messages/TeleportCommandRequest.h>
#include <Messages/PlayerRespawnRequest.h>
#include <Messages/DialogueRequest.h>

using TiltedPhoques::UniquePtr;

Expand All @@ -65,7 +66,7 @@ struct ClientMessageFactory
RequestOwnershipClaim, RequestObjectInventoryChanges, SpellCastRequest, ProjectileLaunchRequest, InterruptCastRequest,
AddTargetRequest, ScriptAnimationRequest, DrawWeaponRequest, MountRequest, NewPackageRequest,
RequestRespawn, SyncExperienceRequest, RequestEquipmentChanges, SendChatMessageRequest,
TeleportCommandRequest, PlayerRespawnRequest>;
TeleportCommandRequest, PlayerRespawnRequest, DialogueRequest>;

return s_visitor(std::forward<T>(func));
}
Expand Down
15 changes: 15 additions & 0 deletions Code/encoding/Messages/DialogueRequest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include <Messages/DialogueRequest.h>

void DialogueRequest::SerializeRaw(TiltedPhoques::Buffer::Writer& aWriter) const noexcept
{
Serialization::WriteVarInt(aWriter, ServerId);
Serialization::WriteString(aWriter, SoundFilename);

This comment has been minimized.

Copy link
@maximegmd

maximegmd May 5, 2022

Member

Would be a good place to use string cache

}

void DialogueRequest::DeserializeRaw(TiltedPhoques::Buffer::Reader& aReader) noexcept
{
ClientMessage::DeserializeRaw(aReader);

ServerId = Serialization::ReadVarInt(aReader) & 0xFFFFFFFF;
SoundFilename = Serialization::ReadString(aReader);
}
28 changes: 28 additions & 0 deletions Code/encoding/Messages/DialogueRequest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#pragma once

#include "Message.h"

using TiltedPhoques::String;

struct DialogueRequest final : ClientMessage
{
static constexpr ClientOpcode Opcode = kDialogueRequest;

DialogueRequest() : ClientMessage(Opcode)
{
}

void SerializeRaw(TiltedPhoques::Buffer::Writer& aWriter) const noexcept override;
void DeserializeRaw(TiltedPhoques::Buffer::Reader& aReader) noexcept override;

bool operator==(const DialogueRequest& acRhs) const noexcept
{
return GetOpcode() == acRhs.GetOpcode() &&
ServerId == acRhs.ServerId &&
SoundFilename == acRhs.SoundFilename;
}

uint32_t ServerId{};
TiltedPhoques::String SoundFilename{};
};

15 changes: 15 additions & 0 deletions Code/encoding/Messages/NotifyDialogue.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include <Messages/NotifyDialogue.h>

void NotifyDialogue::SerializeRaw(TiltedPhoques::Buffer::Writer& aWriter) const noexcept
{
Serialization::WriteVarInt(aWriter, ServerId);
Serialization::WriteString(aWriter, SoundFilename);
}

void NotifyDialogue::DeserializeRaw(TiltedPhoques::Buffer::Reader& aReader) noexcept
{
ServerMessage::DeserializeRaw(aReader);

ServerId = Serialization::ReadVarInt(aReader) & 0xFFFFFFFF;
SoundFilename = Serialization::ReadString(aReader);
}
25 changes: 25 additions & 0 deletions Code/encoding/Messages/NotifyDialogue.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

#include "Message.h"

struct NotifyDialogue final : ServerMessage
{
static constexpr ServerOpcode Opcode = kNotifyDialogue;

NotifyDialogue() : ServerMessage(Opcode)
{
}

void SerializeRaw(TiltedPhoques::Buffer::Writer& aWriter) const noexcept override;
void DeserializeRaw(TiltedPhoques::Buffer::Reader& aReader) noexcept override;

bool operator==(const NotifyDialogue& achRhs) const noexcept
{
return GetOpcode() == achRhs.GetOpcode() &&
ServerId == achRhs.ServerId &&
SoundFilename == achRhs.SoundFilename;
}

uint32_t ServerId{};
TiltedPhoques::String SoundFilename{};
};
3 changes: 2 additions & 1 deletion Code/encoding/Messages/ServerMessageFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include <Messages/TeleportCommandResponse.h>
#include <Messages/StringCacheUpdate.h>
#include <Messages/NotifyPlayerRespawn.h>
#include <Messages/NotifyDialogue.h>

using TiltedPhoques::UniquePtr;

Expand All @@ -62,7 +63,7 @@ struct ServerMessageFactory
NotifyObjectInventoryChanges, NotifySpellCast, NotifyProjectileLaunch, NotifyInterruptCast,
NotifyAddTarget, NotifyScriptAnimation, NotifyDrawWeapon, NotifyMount, NotifyNewPackage,
NotifyRespawn, NotifySyncExperience, NotifyEquipmentChanges, NotifyChatMessageBroadcast,
TeleportCommandResponse, NotifyPlayerRespawn>;
TeleportCommandResponse, NotifyPlayerRespawn, NotifyDialogue>;

return s_visitor(std::forward<T>(func));
}
Expand Down
2 changes: 2 additions & 0 deletions Code/encoding/Opcodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ enum ClientOpcode : unsigned char
kSendChatMessageRequest,
kTeleportCommandRequest,
kPlayerRespawnRequest,
kDialogueRequest,
kClientOpcodeMax
};

Expand Down Expand Up @@ -87,5 +88,6 @@ enum ServerOpcode : unsigned char
kTeleportCommandResponse,
kStringCacheUpdate,
kNotifyPlayerRespawn,
kNotifyDialogue,
kServerOpcodeMax
};
15 changes: 15 additions & 0 deletions Code/server/Services/CharacterService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
#include <Messages/NotifyRespawn.h>
#include <Messages/SyncExperienceRequest.h>
#include <Messages/NotifySyncExperience.h>
#include <Messages/DialogueRequest.h>
#include <Messages/NotifyDialogue.h>

CharacterService::CharacterService(World& aWorld, entt::dispatcher& aDispatcher) noexcept
: m_world(aWorld)
Expand All @@ -56,6 +58,7 @@ CharacterService::CharacterService(World& aWorld, entt::dispatcher& aDispatcher)
, m_newPackageConnection(aDispatcher.sink<PacketEvent<NewPackageRequest>>().connect<&CharacterService::OnNewPackageRequest>(this))
, m_requestRespawnConnection(aDispatcher.sink<PacketEvent<RequestRespawn>>().connect<&CharacterService::OnRequestRespawn>(this))
, m_syncExperienceConnection(aDispatcher.sink<PacketEvent<SyncExperienceRequest>>().connect<&CharacterService::OnSyncExperienceRequest>(this))
, m_dialogueConnection(aDispatcher.sink<PacketEvent<DialogueRequest>>().connect<&CharacterService::OnDialogueRequest>(this))
{
}

Expand Down Expand Up @@ -549,6 +552,18 @@ void CharacterService::OnSyncExperienceRequest(const PacketEvent<SyncExperienceR
GameServer::Get()->SendToParty(notify, partyComponent, acMessage.GetSender());
}

void CharacterService::OnDialogueRequest(const PacketEvent<DialogueRequest>& acMessage) const noexcept
{
auto& message = acMessage.Packet;

NotifyDialogue notify{};
notify.ServerId = message.ServerId;
notify.SoundFilename = message.SoundFilename;

const entt::entity cEntity = static_cast<entt::entity>(message.ServerId);
GameServer::Get()->SendToPlayersInRange(notify, cEntity, acMessage.pPlayer);
}

void CharacterService::CreateCharacter(const PacketEvent<AssignCharacterRequest>& acMessage) const noexcept
{
auto& message = acMessage.Packet;
Expand Down
Loading

0 comments on commit 7dc48a1

Please sign in to comment.