Skip to content

Commit

Permalink
Version 2.2.5
Browse files Browse the repository at this point in the history
  • Loading branch information
ersh1 committed Oct 27, 2023
1 parent 99f92e5 commit 626c826
Show file tree
Hide file tree
Showing 11 changed files with 170 additions and 36 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.22)

project(
TrueDirectionalMovement
VERSION 2.2.4
VERSION 2.2.5
LANGUAGES CXX
)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
Expand Down
7 changes: 7 additions & 0 deletions scripts/source/TrueDirectionalMovement.psc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
ScriptName TrueDirectionalMovement Hidden

bool Function GetDirectionalMovementState() global native
bool Function GetTargetLockState() global native
Actor Function GetCurrentTarget() global native
Function ToggleDisableDirectionalMovement(String asModName, bool abDisable) global native
Function ToggleDisableHeadtracking(String asModName, bool abDisable) global native
96 changes: 67 additions & 29 deletions src/DirectionalMovementHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -246,9 +246,10 @@ void DirectionalMovementHandler::Update()
float desiredRotationX = NormalRelativeAngle(_desiredCameraAngleX - cameraTarget->data.angle.z);
float desiredRotationY = Settings::bResetCameraPitch ? 0.f : thirdPersonState->freeRotation.y;
float desiredTargetPitch = Settings::bResetCameraPitch ? 0.f : cameraTarget->data.angle.x;
thirdPersonState->freeRotation.x = InterpAngleTo(thirdPersonState->freeRotation.x, desiredRotationX, *g_deltaTimeRealTime, 10.f);
thirdPersonState->freeRotation.y = InterpAngleTo(thirdPersonState->freeRotation.y, desiredRotationY, *g_deltaTimeRealTime, 10.f);
cameraTarget->data.angle.x = InterpAngleTo(cameraTarget->data.angle.x, desiredTargetPitch, *g_deltaTimeRealTime, 10.f);
const float realTimeDeltaTime = GetRealTimeDeltaTime();
thirdPersonState->freeRotation.x = InterpAngleTo(thirdPersonState->freeRotation.x, desiredRotationX, realTimeDeltaTime, 10.f);
thirdPersonState->freeRotation.y = InterpAngleTo(thirdPersonState->freeRotation.y, desiredRotationY, realTimeDeltaTime, 10.f);
cameraTarget->data.angle.x = InterpAngleTo(cameraTarget->data.angle.x, desiredTargetPitch, realTimeDeltaTime, 10.f);
if (GetAngleDiff(thirdPersonState->freeRotation.x, desiredRotationX) < 0.05f &&
GetAngleDiff(thirdPersonState->freeRotation.y, desiredRotationY) < 0.05f &&
GetAngleDiff(cameraTarget->data.angle.x, desiredTargetPitch) < 0.05f) {
Expand Down Expand Up @@ -309,7 +310,7 @@ void DirectionalMovementHandler::UpdateDirectionalMovement()
bool bFreeCamera = GetFreeCameraEnabled();

RE::TESCameraState* currentCameraState = RE::PlayerCamera::GetSingleton()->currentState.get();
if (bFreeCamera && !_bForceDisableDirectionalMovement && currentCameraState && !bIsAIDriven &&
if (bFreeCamera && !GetForceDisableDirectionalMovement() && currentCameraState && !bIsAIDriven &&
(!_bShouldFaceCrosshair || _bCurrentlyTurningToCrosshair) &&
((currentCameraState->id == RE::CameraStates::kThirdPerson && !IFPV_IsFirstPerson() && !ImprovedCamera_IsFirstPerson()) ||
(currentCameraState->id == RE::CameraStates::kTween && _cameraStateBeforeTween != RE::CameraStates::kFirstPerson) ||
Expand Down Expand Up @@ -577,7 +578,7 @@ void DirectionalMovementHandler::UpdateSwimmingPitchOffset()
{
auto playerCharacter = RE::PlayerCharacter::GetSingleton();
if (playerCharacter && playerCharacter->AsActorState()->IsSwimming()) {
_currentSwimmingPitchOffset = InterpTo(_currentSwimmingPitchOffset, _desiredSwimmingPitchOffset, *g_deltaTime, Settings::fSwimmingPitchSpeed);
_currentSwimmingPitchOffset = InterpTo(_currentSwimmingPitchOffset, _desiredSwimmingPitchOffset, GetPlayerDeltaTime(), Settings::fSwimmingPitchSpeed);
}
}

Expand Down Expand Up @@ -612,29 +613,31 @@ void DirectionalMovementHandler::UpdateMountedArchery()

void DirectionalMovementHandler::ProgressTimers()
{
const float playerDeltaTime = GetPlayerDeltaTime();
const float realTimeDeltaTime = GetRealTimeDeltaTime();
if (_dialogueHeadtrackTimer > 0.f) {
_dialogueHeadtrackTimer -= *g_deltaTime;
_dialogueHeadtrackTimer -= playerDeltaTime;
}
if (_lastTargetSwitchTimer > 0.f) {
_lastTargetSwitchTimer -= *g_deltaTimeRealTime;
_lastTargetSwitchTimer -= realTimeDeltaTime;
}
if (_lastLOSTimer > 0.f) {
_lastLOSTimer -= *g_deltaTime;
_lastLOSTimer -= playerDeltaTime;
}
if (_faceCrosshairTimer > 0.f) {
_faceCrosshairTimer -= *g_deltaTime;
_faceCrosshairTimer -= playerDeltaTime;
}
if (_aimingTimer > 0.f) {
_aimingTimer -= *g_deltaTime;
_aimingTimer -= playerDeltaTime;
}
if (_cameraHeadtrackTimer > 0.f) {
_cameraHeadtrackTimer -= *g_deltaTime;
_cameraHeadtrackTimer -= playerDeltaTime;
}
if (_cameraRotationDelayTimer > 0.f) {
_cameraRotationDelayTimer -= *g_deltaTimeRealTime;
_cameraRotationDelayTimer -= realTimeDeltaTime;
}
if (_tutorialHintTimer > 0.f) {
_tutorialHintTimer -= *g_deltaTimeRealTime;
_tutorialHintTimer -= realTimeDeltaTime;
}
}

Expand Down Expand Up @@ -685,6 +688,8 @@ void DirectionalMovementHandler::UpdateLeaning(RE::Actor* a_actor, [[maybe_unuse
float desiredPitch = 0.f;
float desiredRoll = 0.f;

const float playerDeltaTime = GetPlayerDeltaTime();

if (a_actor->AsActorState()->actorState1.meleeAttackState == RE::ATTACK_STATE_ENUM::kNone) {
float quad[4];
_mm_store_ps(quad, characterController->forwardVec.quad);
Expand All @@ -697,7 +702,11 @@ void DirectionalMovementHandler::UpdateLeaning(RE::Actor* a_actor, [[maybe_unuse
a_actor->SetGraphVariableFloat("TDM_VelocityY", worldVelocity.y);

// calculate acceleration
RE::NiPoint3 worldAcceleration = (worldVelocity - previousVelocity) / *g_deltaTime;
RE::NiPoint3 worldAcceleration = RE::NiPoint3::Zero();

if (playerDeltaTime > 0.f) {
worldAcceleration = (worldVelocity - previousVelocity) / playerDeltaTime;
}

worldAcceleration *= worldAcceleration.Dot(worldVelocity) > 0 ? 1.f : 0.5f;
worldAcceleration = ClampSizeMax(worldAcceleration, Settings::fMaxLeaningStrength); // clamp to sane values
Expand All @@ -722,8 +731,8 @@ void DirectionalMovementHandler::UpdateLeaning(RE::Actor* a_actor, [[maybe_unuse
a_actor->GetGraphVariableFloat("TDM_Roll", roll);

// interpolate
roll = InterpTo(roll, desiredRoll, *g_deltaTime, Settings::fLeaningSpeed);
pitch = InterpTo(pitch, desiredPitch, *g_deltaTime, Settings::fLeaningSpeed);
roll = InterpTo(roll, desiredRoll, playerDeltaTime, Settings::fLeaningSpeed);
pitch = InterpTo(pitch, desiredPitch, playerDeltaTime, Settings::fLeaningSpeed);

// update angles
a_actor->SetGraphVariableFloat("TDM_Pitch", pitch);
Expand Down Expand Up @@ -767,8 +776,9 @@ void DirectionalMovementHandler::UpdateCameraAutoRotation()
}
}

_currentAutoCameraRotationSpeed = InterpTo(_currentAutoCameraRotationSpeed, desiredSpeed, *g_deltaTimeRealTime, 5.f);
thirdPersonState->freeRotation.x += _currentAutoCameraRotationSpeed * *g_deltaTimeRealTime;
const float realTimeDeltaTime = GetRealTimeDeltaTime();
_currentAutoCameraRotationSpeed = InterpTo(_currentAutoCameraRotationSpeed, desiredSpeed, realTimeDeltaTime, 5.f);
thirdPersonState->freeRotation.x += _currentAutoCameraRotationSpeed * realTimeDeltaTime;
}
}

Expand Down Expand Up @@ -1059,6 +1069,8 @@ void DirectionalMovementHandler::UpdateRotation(bool bForceInstant /*= false */)

bool bInstantRotation = bForceInstant || (_bShouldFaceCrosshair && Settings::bFaceCrosshairInstantly) || (_bShouldFaceCrosshair && !_bCurrentlyTurningToCrosshair) || (_bJustDodged && !playerCharacter->IsAnimationDriven()) || (_bYawControlledByPlugin && _controlledYawRotationSpeedMultiplier <= 0.f);

const float playerDeltaTime = GetPlayerDeltaTime();

if (!bInstantRotation) {
if (IsPlayerAnimationDriven() || _bIsDodging || IsTDMRotationLocked()) {
ResetDesiredAngle();
Expand Down Expand Up @@ -1151,15 +1163,15 @@ void DirectionalMovementHandler::UpdateRotation(bool bForceInstant /*= false */)
rotationSpeedMult /= gtm;
}

float maxAngleDelta = rotationSpeedMult * *g_deltaTime;
float maxAngleDelta = rotationSpeedMult * playerDeltaTime;
if (bRelativeSpeed) {
maxAngleDelta *= (1.f + abs(angleDelta));
}

angleDelta = ClipAngle(angleDelta, -maxAngleDelta, maxAngleDelta);
}

float aiProcessRotationSpeed = angleDelta * (1 / *g_deltaTime);
float aiProcessRotationSpeed = angleDelta * (1 / playerDeltaTime);
SetDesiredAIProcessRotationSpeed(aiProcessRotationSpeed);

playerCharacter->SetRotationZ(playerCharacter->data.angle.z + angleDelta);
Expand Down Expand Up @@ -1216,15 +1228,16 @@ void DirectionalMovementHandler::UpdateRotationLockedCam()
float angleDelta = GetAngle(currentPlayerDirection, playerDirectionToTargetXY);
angleDelta = NormalRelativeAngle(angleDelta);

float desiredCharacterYaw = currentCharacterYaw + angleDelta;
const float realTimeDeltaTime = GetRealTimeDeltaTime();

playerCharacter->SetRotationZ(InterpAngleTo(currentCharacterYaw, desiredCharacterYaw, *g_deltaTimeRealTime, Settings::fTargetLockYawAdjustSpeed));
float desiredCharacterYaw = currentCharacterYaw + angleDelta;
playerCharacter->SetRotationZ(InterpAngleTo(currentCharacterYaw, desiredCharacterYaw, realTimeDeltaTime, Settings::fTargetLockYawAdjustSpeed));

// pitch
RE::NiPoint3 playerAngle = ToOrientationRotation(playerDirectionToTarget);
float desiredPlayerPitch = -playerAngle.x;

playerCharacter->SetRotationX(InterpAngleTo(currentCharacterPitch, desiredPlayerPitch, *g_deltaTimeRealTime, Settings::fTargetLockPitchAdjustSpeed));
playerCharacter->SetRotationX(InterpAngleTo(currentCharacterPitch, desiredPlayerPitch, realTimeDeltaTime, Settings::fTargetLockPitchAdjustSpeed));
}

void DirectionalMovementHandler::UpdateTweeningState()
Expand Down Expand Up @@ -1636,7 +1649,7 @@ bool DirectionalMovementHandler::IsActorValidTarget(RE::ActorPtr a_actor, bool a
return true;
}

RE::ActorHandle DirectionalMovementHandler::FindTarget(TargetLockSelectionMode a_mode)
RE::ActorHandle DirectionalMovementHandler::FindTarget(TargetLockSelectionMode a_mode, bool a_bSkipCurrent /*= true*/)
{
if (auto crosshairRef = Events::CrosshairRefManager::GetSingleton()->GetCachedRef()) {
if (auto crosshairRefPtr = crosshairRef.get()) {
Expand Down Expand Up @@ -1684,6 +1697,9 @@ RE::ActorHandle DirectionalMovementHandler::FindTarget(TargetLockSelectionMode a

for (auto& actorHandle : actorHandles) {
auto actor = actorHandle.get();
if (a_bSkipCurrent && actorHandle == _target) {
continue;
}
if (IsActorValidTarget(actor)) {
float targetLockMaxDistance = Settings::fTargetLockDistance * GetTargetLockDistanceRaceSizeMultiplier(actor->GetRace());

Expand Down Expand Up @@ -2529,8 +2545,10 @@ void DirectionalMovementHandler::LookAtTarget(RE::ActorHandle a_target)
float angleDelta = bIsBehind ? GetAngle(reversedCameraDirection, projectedDirectionToTargetXY) : GetAngle(currentCameraDirection, projectedDirectionToTargetXY);
angleDelta = NormalRelativeAngle(angleDelta);

const float realTimeDeltaTime = GetRealTimeDeltaTime();

float desiredFreeCameraRotation = currentCameraYawOffset + angleDelta;
thirdPersonState->freeRotation.x = InterpAngleTo(currentCameraYawOffset, desiredFreeCameraRotation, *g_deltaTimeRealTime, Settings::fTargetLockYawAdjustSpeed);
thirdPersonState->freeRotation.x = InterpAngleTo(currentCameraYawOffset, desiredFreeCameraRotation, realTimeDeltaTime, Settings::fTargetLockYawAdjustSpeed);

if (bIsBehind)
{
Expand Down Expand Up @@ -2560,9 +2578,9 @@ void DirectionalMovementHandler::LookAtTarget(RE::ActorHandle a_target)

if (!bIsHorseCamera) {
thirdPersonState->freeRotation.y += cameraPitchOffset;
thirdPersonState->freeRotation.y = InterpAngleTo(thirdPersonState->freeRotation.y, desiredCameraAngle, *g_deltaTimeRealTime, Settings::fTargetLockPitchAdjustSpeed);
thirdPersonState->freeRotation.y = InterpAngleTo(thirdPersonState->freeRotation.y, desiredCameraAngle, realTimeDeltaTime, Settings::fTargetLockPitchAdjustSpeed);
} else {
thirdPersonState->freeRotation.y = InterpAngleTo(thirdPersonState->freeRotation.y, -desiredCameraAngle, *g_deltaTimeRealTime, Settings::fTargetLockPitchAdjustSpeed);
thirdPersonState->freeRotation.y = InterpAngleTo(thirdPersonState->freeRotation.y, -desiredCameraAngle, realTimeDeltaTime, Settings::fTargetLockPitchAdjustSpeed);
}
}

Expand Down Expand Up @@ -2662,6 +2680,8 @@ void DirectionalMovementHandler::OnPreLoadGame()
_softTarget = RE::ActorHandle();
_dialogueSpeaker = RE::ObjectRefHandle();
_playerIsNPC = false;
_papyrusDisableDirectionalMovement.clear();
_papyrusDisableHeadtracking.clear();
}

void DirectionalMovementHandler::OnSettingsUpdated()
Expand Down Expand Up @@ -2850,12 +2870,12 @@ void DirectionalMovementHandler::RequestAPIs()

bool DirectionalMovementHandler::GetForceDisableDirectionalMovement() const
{
return _bForceDisableDirectionalMovement;
return _bForceDisableDirectionalMovement || !_papyrusDisableDirectionalMovement.empty();
}

bool DirectionalMovementHandler::GetForceDisableHeadtracking() const
{
return _bForceDisableHeadtracking;
return _bForceDisableHeadtracking || !_papyrusDisableHeadtracking.empty();
}

bool DirectionalMovementHandler::GetYawControl() const
Expand Down Expand Up @@ -2887,6 +2907,24 @@ void DirectionalMovementHandler::SetPlayerYaw(float a_yaw)
_desiredAngle = NormalAbsoluteAngle(a_yaw);
}

void DirectionalMovementHandler::PapyrusDisableDirectionalMovement(std::string_view a_modName, bool a_bDisable)
{
if (a_bDisable) {
_papyrusDisableDirectionalMovement.emplace(a_modName.data());
} else {
_papyrusDisableDirectionalMovement.erase(a_modName.data());
}
}

void DirectionalMovementHandler::PapyrusDisableHeadtracking(std::string_view a_modName, bool a_bDisable)
{
if (a_bDisable) {
_papyrusDisableHeadtracking.emplace(a_modName.data());
} else {
_papyrusDisableHeadtracking.erase(a_modName.data());
}
}

DirectionalMovementHandler::DirectionalMovementHandler() :
_lock()
{}
10 changes: 8 additions & 2 deletions src/DirectionalMovementHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "SmoothCamAPI.h"
#include "TrueHUDAPI.h"
#include "Widgets/TargetLockReticle.h"
#include <unordered_set>

namespace std
{
Expand Down Expand Up @@ -142,7 +143,7 @@ class DirectionalMovementHandler :

bool IsActorValidTarget(RE::ActorPtr a_actor, bool a_bCheckDistance = false) const;

RE::ActorHandle FindTarget(TargetLockSelectionMode a_mode);
RE::ActorHandle FindTarget(TargetLockSelectionMode a_mode, bool a_bSkipCurrent = true);
void SwitchTarget(Direction a_direction);
bool SwitchTargetPoint(Direction a_direction);
RE::ActorHandle SwitchScreenTarget(Direction a_direction);
Expand Down Expand Up @@ -229,6 +230,9 @@ class DirectionalMovementHandler :
void SetYawControl(bool a_enable, float a_yawRotationSpeedMultiplier = 0);
void SetPlayerYaw(float a_yaw);

void PapyrusDisableDirectionalMovement(std::string_view a_modName, bool a_bDisable);
void PapyrusDisableHeadtracking(std::string_view a_modName, bool a_bDisable);

bool IsACCInstalled() const { return _bACCInstalled; }
bool IsICInstalled() const { return _bICInstalled; }

Expand Down Expand Up @@ -317,7 +321,9 @@ class DirectionalMovementHandler :
AttackState _attackState;

bool _bForceDisableDirectionalMovement = false;
bool _bForceDisableHeadtracking = false;
std::unordered_set<std::string> _papyrusDisableDirectionalMovement{};
bool _bForceDisableHeadtracking = false;
std::unordered_set<std::string> _papyrusDisableHeadtracking{};
bool _bYawControlledByPlugin = false;
float _controlledYawRotationSpeedMultiplier = 0;

Expand Down
2 changes: 1 addition & 1 deletion src/Hooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1329,7 +1329,7 @@ namespace Hooks
bool bUnk2 = Actor_IsSyncSprintState(a_this) || (actorState->GetAttackState() == RE::ATTACK_STATE_ENUM::kNone);
bool bIsPreviousMoveInputForward = ((bShouldFaceCrosshair && !bAutoMove) ? normalizedInputDirection.y : playerControls->data.prevMoveVec.y) > 0.f;
bool bIsNotStrafing = bShouldFaceCrosshair ? 0.75f > fabs(normalizedInputDirection.x) : *g_fSprintStopThreshold > fabs(playerControls->data.prevMoveVec.x);
bool bIsStaminaNotZero = a_this->AsActorValueOwner()->GetActorValue(RE::ActorValue::kStamina) > 0.f;
bool bIsStaminaNotZero = actor->AsActorValueOwner()->GetActorValue(RE::ActorValue::kStamina) > 0.f;
bool bIsSprinting = a_this->GetPlayerRuntimeData().playerFlags.isSprinting;

// added
Expand Down
4 changes: 4 additions & 0 deletions src/Offsets.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ static float* g_worldScaleInverse = (float*)RELOCATION_ID(230692, 187407).addres
static float* g_fFreeRotationSpeed = (float*)RELOCATION_ID(509884, 382636).address(); // 1DF3820, 1E87BC8
static float* g_fVanityModeMinDist = (float*)RELOCATION_ID(509874, 382621).address(); // 1DF37A8, 1E87B50
static float* g_fVanityModeMaxDist = (float*)RELOCATION_ID(509878, 382627).address(); // 1DF37D8, 1E87B80
static void** g_142EC5C60 = (void**)RELOCATION_ID(514725, 400883).address(); // 2EC5C60, 2F603B0

// functions
typedef RE::BGSMovementType*(__fastcall* tGetMovementTypeFromString)(const char** a1);
Expand Down Expand Up @@ -65,3 +66,6 @@ static REL::Relocation<tPlayerCamera_SetCameraState> PlayerCamera_SetCameraState

typedef void(tAIProcess_ClearHeadTrackTarget)(RE::AIProcess* a_this);
static REL::Relocation<tAIProcess_ClearHeadTrackTarget> AIProcess_ClearHeadTrackTarget{ RELOCATION_ID(38852, 39889) }; // 67D190, 6A4900

typedef float (*tGetPlayerTimeMult)(void* a1);
static REL::Relocation<tGetPlayerTimeMult> GetPlayerTimeMult{ RELOCATION_ID(43104, 44301) }; // 759420, 7873C0
Loading

0 comments on commit 626c826

Please sign in to comment.