From 489a1f83b31eb2117f240482c69363b5925d1eb6 Mon Sep 17 00:00:00 2001 From: Robbe Bryssinck Date: Wed, 4 May 2022 23:15:05 +0200 Subject: [PATCH] fix: actor not dying after kill move --- Code/client/Games/References.cpp | 21 +++++++++++++++++ Code/client/Games/References.h | 7 ++++++ Code/client/Games/Skyrim/Actor.cpp | 36 +++++++++++++----------------- 3 files changed, 43 insertions(+), 21 deletions(-) diff --git a/Code/client/Games/References.cpp b/Code/client/Games/References.cpp index 1081622a6..70167cf7c 100644 --- a/Code/client/Games/References.cpp +++ b/Code/client/Games/References.cpp @@ -50,6 +50,27 @@ static TRotate* RealRotateZ = nullptr; static TActorProcess* RealActorProcess = nullptr; static TLockChange* RealLockChange = nullptr; +namespace GameplayFormulas +{ + +float CalculateRealDamage(Actor* apHittee, float aDamage) noexcept +{ + using TGetDifficultyMultiplier = float(int32_t, int32_t, bool); + POINTER_SKYRIMSE(TGetDifficultyMultiplier, s_getDifficultyMultiplier, 26503); + + bool isPlayer = apHittee == PlayerCharacter::Get(); + float multiplier = s_getDifficultyMultiplier(PlayerCharacter::Get()->difficulty, ActorValueInfo::kHealth, isPlayer); + + float realDamage = aDamage; + + if (fabs(aDamage) <= 0.000099999997 || DifficultyMultiplier < 1.0) + realDamage = aDamage * multiplier; + + return realDamage; +} + +} + TESObjectREFR* TESObjectREFR::GetByHandle(uint32_t aHandle) noexcept { TESObjectREFR* pResult = nullptr; diff --git a/Code/client/Games/References.h b/Code/client/Games/References.h index f6e3f8595..65f2cc470 100644 --- a/Code/client/Games/References.h +++ b/Code/client/Games/References.h @@ -3,6 +3,13 @@ #include #include +namespace GameplayFormulas +{ + +float CalculateRealDamage(Actor* apHittee, float aDamage) noexcept; + +} + struct ExActor : Actor, ActorExtension { }; diff --git a/Code/client/Games/Skyrim/Actor.cpp b/Code/client/Games/Skyrim/Actor.cpp index 455b1da0b..3ba1d4c66 100644 --- a/Code/client/Games/Skyrim/Actor.cpp +++ b/Code/client/Games/Skyrim/Actor.cpp @@ -571,50 +571,44 @@ static TDamageActor* RealDamageActor = nullptr; bool TP_MAKE_THISCALL(HookDamageActor, Actor, float aDamage, Actor* apHitter) { - float oldHealth = apThis->GetActorValue(ActorValueInfo::kHealth); + float realDamage = GameplayFormulas::CalculateRealDamage(apThis, aDamage); - const auto pExHittee = apThis->GetExtension(); + float currentHealth = apThis->GetActorValue(ActorValueInfo::kHealth); + bool wouldKill = (currentHealth - realDamage) <= 0.f; + + const auto* pExHittee = apThis->GetExtension(); if (pExHittee->IsLocalPlayer()) { - bool result = ThisCall(RealDamageActor, apThis, aDamage, apHitter); - float newHealth = apThis->GetActorValue(ActorValueInfo::kHealth); - float damage = oldHealth - newHealth; - World::Get().GetRunner().Trigger(HealthChangeEvent(apThis->formID, -damage)); - return result; + World::Get().GetRunner().Trigger(HealthChangeEvent(apThis->formID, -realDamage)); + return ThisCall(RealDamageActor, apThis, aDamage, apHitter); } else if (pExHittee->IsRemotePlayer()) { - return false; + return wouldKill; } if (apHitter) { - const auto pExHitter = apHitter->GetExtension(); + const auto* pExHitter = apHitter->GetExtension(); if (pExHitter->IsLocalPlayer()) { - bool result = ThisCall(RealDamageActor, apThis, aDamage, apHitter); - float newHealth = apThis->GetActorValue(ActorValueInfo::kHealth); - float damage = oldHealth - newHealth; - World::Get().GetRunner().Trigger(HealthChangeEvent(apThis->formID, -damage)); - return result; + World::Get().GetRunner().Trigger(HealthChangeEvent(apThis->formID, -realDamage)); + return ThisCall(RealDamageActor, apThis, aDamage, apHitter); } if (pExHitter->IsRemotePlayer()) { - return false; + return wouldKill; } } if (pExHittee->IsLocal()) { - bool result = ThisCall(RealDamageActor, apThis, aDamage, apHitter); - float newHealth = apThis->GetActorValue(ActorValueInfo::kHealth); - float damage = oldHealth - newHealth; - World::Get().GetRunner().Trigger(HealthChangeEvent(apThis->formID, -damage)); - return result; + World::Get().GetRunner().Trigger(HealthChangeEvent(apThis->formID, -realDamage)); + return ThisCall(RealDamageActor, apThis, aDamage, apHitter); } else { - return false; + return wouldKill; } }