Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…olution into stability
  • Loading branch information
Yamashi committed May 6, 2022
2 parents a73dcaf + 2907b92 commit ab1c98f
Show file tree
Hide file tree
Showing 33 changed files with 393 additions and 91 deletions.
15 changes: 15 additions & 0 deletions Code/client/Events/DialogueEvent.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#pragma once

/**
* @brief Dispatched whenever an actor talks
*/
struct DialogueEvent
{
DialogueEvent(uint32_t aActorID, String aVoiceFile)
: ActorID(aActorID), VoiceFile(aVoiceFile)
{}

uint32_t ActorID;
String VoiceFile;
};

30 changes: 29 additions & 1 deletion Code/client/Games/References.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

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

#include <TiltedCore/Serialization.hpp>

Expand Down Expand Up @@ -63,7 +64,7 @@ float CalculateRealDamage(Actor* apHittee, float aDamage) noexcept

float realDamage = aDamage;

if (fabs(aDamage) <= 0.000099999997 || DifficultyMultiplier < 1.0)
if (fabs(aDamage) <= 0.000099999997 || multiplier < 1.0)
realDamage = aDamage * multiplier;

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

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, 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)
{
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(const char* pFile)
{
uint32_t handle[3]{};
handle[0] = -1;
ThisCall(RealSpeakSoundFunction, this, pFile, handle, 0, 0x32, 0, 0, 0, 0, 0, 0, 0, 1, 1);
}

TiltedPhoques::Initializer s_referencesHooks([]()
{
POINTER_SKYRIMSE(TSetPosition, s_setPosition, 19790);
Expand All @@ -731,6 +755,8 @@ TiltedPhoques::Initializer s_referencesHooks([]()
POINTER_SKYRIMSE(TInitFromPackage, s_initFromPackage, 38959);
POINTER_FALLOUT4(TInitFromPackage, s_initFromPackage, 0x140E219A0 - 0x140000000);

POINTER_SKYRIMSE(TSpeakSoundFunction, s_speakSoundFunction, 37542);

RealSetPosition = s_setPosition.Get();
RealRotateX = s_rotateX.Get();
RealRotateY = s_rotateY.Get();
Expand All @@ -739,6 +765,7 @@ TiltedPhoques::Initializer s_referencesHooks([]()
RealLockChange = s_lockChange.Get();
RealCheckForNewPackage = s_checkForNewPackage.Get();
RealInitFromPackage = s_initFromPackage.Get();
RealSpeakSoundFunction = s_speakSoundFunction.Get();

TP_HOOK(&RealSetPosition, HookSetPosition);
TP_HOOK(&RealRotateX, HookRotateX);
Expand All @@ -748,5 +775,6 @@ TiltedPhoques::Initializer s_referencesHooks([]()
TP_HOOK(&RealLockChange, HookLockChange);
TP_HOOK(&RealCheckForNewPackage, HookCheckForNewPackage);
TP_HOOK(&RealInitFromPackage, HookInitFromPackage);
TP_HOOK(&RealSpeakSoundFunction, HookSpeakSoundFunction);
});

1 change: 1 addition & 0 deletions Code/client/Games/Skyrim/Actor.h
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +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(const char* pFile);

enum ActorFlags
{
Expand Down
10 changes: 8 additions & 2 deletions Code/client/Games/Skyrim/Forms/TESQuest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,19 @@ bool TESQuest::SetStage(uint16_t newStage)
return SetStage(this, newStage);
}

void TESQuest::ScriptSetStage(uint16_t stage)
void TESQuest::ScriptSetStage(uint16_t stageIndex)
{
ScopedQuestOverride _;

for (Stage* stage : stages)
{
if (stage->stageIndex == stageIndex && stage->IsDone())
return;
}

using Quest = TESQuest;
PAPYRUS_FUNCTION(void, Quest, SetCurrentStageID, int);
s_pSetCurrentStageID(this, stage);
s_pSetCurrentStageID(this, stageIndex);
}

void TESQuest::SetStopped()
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;
};
13 changes: 13 additions & 0 deletions Code/client/Services/Debug/DebugService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <Services/QuestService.h>

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

#include <Games/References.h>

Expand Down Expand Up @@ -86,6 +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<DialogueEvent>().connect<&DebugService::OnActorSpokeEvent>(this);
}

void DebugService::OnUpdate(const UpdateEvent& acUpdateEvent) noexcept
Expand Down Expand Up @@ -136,12 +138,23 @@ void DebugService::OnUpdate(const UpdateEvent& acUpdateEvent) noexcept
if (!s_f8Pressed)
{
s_f8Pressed = true;

Actor* pActor = Cast<Actor>(TESForm::GetById(m_spokenActorId));
pActor->SpeakSound(m_voiceFileName.data());
}
}
else
s_f8Pressed = false;
}

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

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

uint64_t DebugService::DisplayGraphDescriptorKey(BSAnimationGraphManager* pManager) noexcept
{
auto hash = pManager->GetDescriptorKey();
Expand Down
9 changes: 8 additions & 1 deletion Code/client/Services/Debug/Views/QuestDebugView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,22 @@ void DebugService::DrawQuestDebugView()

ImGui::Begin("Quest log");

Set<uint32_t> foundQuests{};

for (auto &objective : pPlayer->objectives)
{
auto* pQuest = objective.instance->quest;
TESQuest* pQuest = objective.instance->quest;
if (!pQuest)
continue;

if (QuestService::IsNonSyncableQuest(pQuest))
continue;

if (foundQuests.contains(pQuest->formID))
continue;

foundQuests.insert(pQuest->formID);

if (pQuest->IsActive())
{
ImGui::TextColored({255.f, 0.f, 255.f, 255.f}, "%s|%x|%s", pQuest->idName.AsAscii(),
Expand Down
8 changes: 8 additions & 0 deletions Code/client/Services/DebugService.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

struct World;
struct ImguiService;

struct UpdateEvent;
struct DialogueEvent;

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

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

protected:

Expand Down Expand Up @@ -57,8 +60,13 @@ struct DebugService

uint32_t m_formId = 0;

uint32_t m_spokenActorId = 0;
String m_voiceFileName = "";

entt::scoped_connection m_updateConnection;
entt::scoped_connection m_drawImGuiConnection;
entt::scoped_connection m_actorSpokeConnection;

bool m_showDebugStuff = false;
bool m_showBuildTag = true;
bool m_toggleComponentWindow = false;
Expand Down
60 changes: 59 additions & 1 deletion 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 Expand Up @@ -1133,7 +1191,7 @@ void CharacterService::RequestServerAssignment(const entt::entity aEntity) const
message.IsDead = pActor->IsDead();
message.IsWeaponDrawn = pActor->actorState.IsWeaponFullyDrawn();

if (isTemporary && !isNpcTemporary)
if (isTemporary /* && !isNpcTemporary */)
{
if (!m_world.GetModSystem().GetServerModId(pNpc->formID, message.FormId))
{
Expand Down
4 changes: 3 additions & 1 deletion Code/client/Services/Generic/MagicService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,6 @@ void MagicService::OnNotifySpellCast(const NotifySpellCast& acMessage) const noe
pDesiredTargetForm = TESForm::GetById(formIdComponent.Id);
}
}

}

TESObjectREFR* pDesiredTarget = Cast<TESObjectREFR>(pDesiredTargetForm);
Expand Down Expand Up @@ -244,6 +243,9 @@ void MagicService::OnInterruptCastEvent(const InterruptCastEvent& acEvent) const

InterruptCastRequest request;
request.CasterId = localComponent.Id;

spdlog::debug("Sending out interrupt cast");

m_transport.Send(request);
#endif
}
Expand Down
6 changes: 4 additions & 2 deletions Code/client/Services/Generic/QuestService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ void QuestService::OnConnected(const ConnectedEvent&) noexcept

BSTEventResult QuestService::OnEvent(const TESQuestStartStopEvent* apEvent, const EventDispatcher<TESQuestStartStopEvent>*)
{
if (ScopedQuestOverride::IsOverriden())
if (ScopedQuestOverride::IsOverriden()
|| !m_world.Get().GetPartyService().IsLeader())
return BSTEventResult::kOk;

spdlog::info("Quest start/stop event: {:X}", apEvent->formId);
Expand Down Expand Up @@ -94,7 +95,8 @@ BSTEventResult QuestService::OnEvent(const TESQuestStartStopEvent* apEvent, cons

BSTEventResult QuestService::OnEvent(const TESQuestStageEvent* apEvent, const EventDispatcher<TESQuestStageEvent>*)
{
if (ScopedQuestOverride::IsOverriden())
if (ScopedQuestOverride::IsOverriden()
|| !m_world.Get().GetPartyService().IsLeader())
return BSTEventResult::kOk;

spdlog::info("Quest stage event: {:X}, stage: {}", apEvent->formId, apEvent->stageId);
Expand Down
Loading

0 comments on commit ab1c98f

Please sign in to comment.