From b1b233f97ad47df0a583653568b89c777006973d Mon Sep 17 00:00:00 2001 From: Robbe Bryssinck Date: Tue, 24 May 2022 19:30:31 +0200 Subject: [PATCH] fix: invisibility --- Code/client/Games/Skyrim/Actor.h | 4 +-- .../Skyrim/Effects/InvisibilityEffect.cpp | 32 +++++++++++++++++++ .../Games/Skyrim/Effects/InvisibilityEffect.h | 7 ++++ .../client/Games/Skyrim/Magic/MagicTarget.cpp | 13 +++++--- Code/client/Games/Skyrim/Magic/MagicTarget.h | 2 ++ .../Services/Debug/Views/FormDebugView.cpp | 13 +++++--- 6 files changed, 59 insertions(+), 12 deletions(-) create mode 100644 Code/client/Games/Skyrim/Effects/InvisibilityEffect.cpp create mode 100644 Code/client/Games/Skyrim/Effects/InvisibilityEffect.h diff --git a/Code/client/Games/Skyrim/Actor.h b/Code/client/Games/Skyrim/Actor.h index d360c1ca9..54d871b8e 100644 --- a/Code/client/Games/Skyrim/Actor.h +++ b/Code/client/Games/Skyrim/Actor.h @@ -70,7 +70,7 @@ struct Actor : TESObjectREFR virtual void sub_C0(); virtual void sub_C1(); virtual void sub_C2(); - virtual void sub_C3(); + virtual void SetRefraction(bool aEnable, float aRefraction); virtual void sub_C4(); virtual void sub_C5(); virtual void sub_C6(); @@ -99,7 +99,7 @@ struct Actor : TESObjectREFR virtual void sub_DD(); virtual void sub_DE(); virtual void PutCreatedPackage(struct TESPackage*, bool = false, bool = true, bool = true); // 14069BBF0 - virtual void sub_E0(); + virtual void UpdateAlpha(); virtual void sub_E1(); virtual void sub_E2(); virtual void sub_E3(); diff --git a/Code/client/Games/Skyrim/Effects/InvisibilityEffect.cpp b/Code/client/Games/Skyrim/Effects/InvisibilityEffect.cpp new file mode 100644 index 000000000..701217732 --- /dev/null +++ b/Code/client/Games/Skyrim/Effects/InvisibilityEffect.cpp @@ -0,0 +1,32 @@ +#include "InvisibilityEffect.h" + +#include +#include + +TP_THIS_FUNCTION(TFinish, void, InvisibilityEffect); +static TFinish* RealFinish = nullptr; + +// This needs to be done because the actor value does not update in time +void TP_MAKE_THISCALL(HookFinish, InvisibilityEffect) +{ + if (apThis && apThis->pTarget) + { + if (Actor* pActor = apThis->pTarget->GetTargetAsActor()) + { + if (pActor->GetExtension()->IsRemote()) + pActor->SetActorValue(ActorValueInfo::kInvisibility, 0.f); + } + } + + ThisCall(RealFinish, apThis); +} + +static TiltedPhoques::Initializer s_invisibilityEffectsHooks([]() +{ + POINTER_SKYRIMSE(TFinish, s_finish, 34370); + + RealFinish = s_finish.Get(); + + TP_HOOK(&RealFinish, HookFinish); +}); + diff --git a/Code/client/Games/Skyrim/Effects/InvisibilityEffect.h b/Code/client/Games/Skyrim/Effects/InvisibilityEffect.h new file mode 100644 index 000000000..a0c08c248 --- /dev/null +++ b/Code/client/Games/Skyrim/Effects/InvisibilityEffect.h @@ -0,0 +1,7 @@ +#pragma once + +#include "ValueModifierEffect.h" + +struct InvisibilityEffect : ValueModifierEffect +{ +}; diff --git a/Code/client/Games/Skyrim/Magic/MagicTarget.cpp b/Code/client/Games/Skyrim/Magic/MagicTarget.cpp index 9e7c7178f..b1be27b59 100644 --- a/Code/client/Games/Skyrim/Magic/MagicTarget.cpp +++ b/Code/client/Games/Skyrim/Magic/MagicTarget.cpp @@ -38,13 +38,17 @@ bool MagicTarget::AddTargetData::ShouldSync() !pSpell->IsWardSpell(); } +Actor* MagicTarget::GetTargetAsActor() +{ + TP_THIS_FUNCTION(TGetTargetAsActor, Actor*, MagicTarget); + POINTER_SKYRIMSE(TGetTargetAsActor, getTargetAsActor, 34529); + return ThisCall(getTargetAsActor, this); +} + // If you want a detailed flowchart of what's happening here, ask cosi bool TP_MAKE_THISCALL(HookAddTarget, MagicTarget, MagicTarget::AddTargetData& arData) { - spdlog::info("HookAddTarget"); - - // TODO: this can be fixed by properly implementing multiple inheritance - Actor* pTargetActor = (Actor*)((uint8_t*)apThis - 0x98); + Actor* pTargetActor = apThis->GetTargetAsActor(); ActorExtension* pTargetActorEx = pTargetActor->GetExtension(); if (!pTargetActorEx) @@ -56,7 +60,6 @@ bool TP_MAKE_THISCALL(HookAddTarget, MagicTarget, MagicTarget::AddTargetData& ar if (arData.pEffectItem->IsVampireLordEffect()) pTargetActorEx->GraphDescriptorHash = AnimationGraphDescriptor_VampireLordBehavior::m_key; - // TODO(cosideci): maybe call MagicTarget::AddTarget()? if (ScopedSpellCastOverride::IsOverriden()) return ThisCall(RealAddTarget, apThis, arData); diff --git a/Code/client/Games/Skyrim/Magic/MagicTarget.h b/Code/client/Games/Skyrim/Magic/MagicTarget.h index df95e0efa..38e90aebf 100644 --- a/Code/client/Games/Skyrim/Magic/MagicTarget.h +++ b/Code/client/Games/Skyrim/Magic/MagicTarget.h @@ -62,6 +62,8 @@ struct MagicTarget virtual ~MagicTarget(); + Actor* GetTargetAsActor(); + bool AddTarget(AddTargetData& arData) noexcept; // this function actually adds the effect bool CheckAddEffect(AddTargetData& arData) noexcept; diff --git a/Code/client/Services/Debug/Views/FormDebugView.cpp b/Code/client/Services/Debug/Views/FormDebugView.cpp index d67d18985..5f86b045a 100644 --- a/Code/client/Services/Debug/Views/FormDebugView.cpp +++ b/Code/client/Services/Debug/Views/FormDebugView.cpp @@ -13,7 +13,7 @@ void DebugService::DrawFormDebugView() { - static TESObjectREFR* pRefr = nullptr; + static Actor* pRefr = nullptr; static TESForm* pFetchForm = nullptr; ImGui::Begin("Form"); @@ -27,7 +27,7 @@ void DebugService::DrawFormDebugView() { pFetchForm = TESForm::GetById(m_formId); if (pFetchForm) - pRefr = Cast(pFetchForm); + pRefr = Cast(pFetchForm); } } @@ -39,12 +39,13 @@ void DebugService::DrawFormDebugView() if (pRefr) { + /* char name[256]; sprintf_s(name, std::size(name), "%s (%x)", pRefr->baseForm->GetName(), pRefr->formID); ImGui::InputText("Name", name, std::size(name), ImGuiInputTextFlags_ReadOnly); + */ - /* - for (ActiveEffect* pEffect : *pActor->currentProcess->middleProcess->ActiveEffects) + for (ActiveEffect* pEffect : *pRefr->currentProcess->middleProcess->ActiveEffects) { if (!pEffect) continue; @@ -56,8 +57,10 @@ void DebugService::DrawFormDebugView() ImGui::InputFloat("Duration", &pEffect->fDuration, 0, 0, "%.1f", ImGuiInputTextFlags_ReadOnly); ImGui::InputFloat("Magnitude", &pEffect->fMagnitude, 0, 0, "%.1f", ImGuiInputTextFlags_ReadOnly); ImGui::InputInt("Flags", (int*)&pEffect->uiFlags, 0, 0, ImGuiInputTextFlags_ReadOnly); + + if (ImGui::Button("Elapse time")) + m_world.GetRunner().Queue([pEffect]() { pEffect->fElapsedSeconds = pEffect->fDuration - 3.f; }); } - */ } ImGui::End();