231 lines
6.1 KiB
C++
231 lines
6.1 KiB
C++
// Fill out your copyright notice in the Description page of Project Settings.
|
|
|
|
|
|
#include "ShooterAnimInstance.h"
|
|
|
|
#include "ShooterCharacter.h"
|
|
#include "GameFramework/CharacterMovementComponent.h"
|
|
#include "Kismet/KismetMathLibrary.h"
|
|
#include "Weapon.h"
|
|
#include "WeaponType.h"
|
|
|
|
UShooterAnimInstance::UShooterAnimInstance() :
|
|
Speed(0.f),
|
|
bIsInAir(false),
|
|
bIsAccelerating(false),
|
|
MovementOffsetYaw(0.f),
|
|
LastMovementOffsetYaw(0.f),
|
|
bAiming(false),
|
|
TIPCharacterYaw(0.f),
|
|
TIPCharacterYawLastFrame(0.f),
|
|
RootYawOffset(0.f),
|
|
RotationCurve(0.f),
|
|
RotationCurveLastFrame(0.f),
|
|
Pitch(0.f),
|
|
bReloading(false),
|
|
OffsetState(EOffsetState::EOS_Hip),
|
|
CharacterRotation(FRotator(0)),
|
|
CharacterRotationLastFrame(FRotator(0)),
|
|
YawDelta(0.f),
|
|
RecoilWeight(1.f),
|
|
bTurningInPlace(false),
|
|
EquippedWeaponType(EWeaponType::EWT_MAX),
|
|
bShouldUseFABRIK(false)
|
|
{
|
|
}
|
|
|
|
void UShooterAnimInstance::UpdateAnimationProperties(float DeltaTime)
|
|
{
|
|
if (!ShooterCharacter)
|
|
ShooterCharacter = Cast<AShooterCharacter>(TryGetPawnOwner());
|
|
|
|
if (!ShooterCharacter) return;
|
|
|
|
|
|
// Get the lateral speed of the character from velocity
|
|
FVector Velocity{ ShooterCharacter->GetVelocity() };
|
|
Velocity.Z = 0;
|
|
Speed = Velocity.Size();
|
|
|
|
// Is the character in the air
|
|
bIsInAir = ShooterCharacter->GetCharacterMovement()->IsFalling();
|
|
|
|
// Is the character accelerating
|
|
bIsAccelerating = ShooterCharacter->GetCharacterMovement()->GetCurrentAcceleration().Size() > 0;
|
|
|
|
FRotator AimRotation = ShooterCharacter->GetBaseAimRotation();
|
|
FRotator MovementRotation = UKismetMathLibrary::MakeRotFromX(ShooterCharacter->GetVelocity());
|
|
|
|
MovementOffsetYaw = UKismetMathLibrary::NormalizedDeltaRotator(MovementRotation, AimRotation).Yaw;
|
|
|
|
// if (GEngine)
|
|
// {
|
|
// GEngine->AddOnScreenDebugMessage(0, -1, FColor::Red, FString::Printf(TEXT("MovementYaw: %f"), MovementYaw));
|
|
// GEngine->AddOnScreenDebugMessage(1, -1, FColor::Red, FString::Printf(TEXT("MovementInputYaw: %f"), MovementInputRotation.Yaw));
|
|
// GEngine->AddOnScreenDebugMessage(2, -1, FColor::Yellow, FString::Printf(TEXT("AimYaw: %f"), AimRotation.Yaw));
|
|
// GEngine->AddOnScreenDebugMessage(3, -1, FColor::Cyan, FString::Printf(TEXT("MovementOffsetYaw: %f"), MovementOffsetYaw));
|
|
// GEngine->AddOnScreenDebugMessage(4, -1, FColor::Cyan, FString::Printf(TEXT("HipRotationOffsetYaw: %f"), HipRotationOffsetYaw));
|
|
// }
|
|
|
|
if (ShooterCharacter->GetVelocity().Size() > 0)
|
|
{
|
|
LastMovementOffsetYaw = MovementOffsetYaw;
|
|
}
|
|
|
|
bAiming = ShooterCharacter->GetAiming();
|
|
bReloading = ShooterCharacter->GetCombatState() == ECombatState::ECS_Reloading;
|
|
bCrouching = ShooterCharacter->IsCrouching();
|
|
bEquipping = ShooterCharacter->GetCombatState() == ECombatState::ECS_Equipping;
|
|
bShouldUseFABRIK = ShooterCharacter->GetCombatState() == ECombatState::ECS_Unoccupied
|
|
|| ShooterCharacter->GetCombatState() == ECombatState::ECS_FireTimerInProgress;
|
|
|
|
if (bReloading)
|
|
{
|
|
OffsetState = EOffsetState::EOS_Reloading;
|
|
}
|
|
else if (bIsInAir)
|
|
{
|
|
OffsetState = EOffsetState::EOS_InAir;
|
|
}
|
|
else if (bAiming)
|
|
{
|
|
OffsetState = EOffsetState::EOS_Aiming;
|
|
}
|
|
else
|
|
{
|
|
OffsetState = EOffsetState::EOS_Hip;
|
|
}
|
|
|
|
// Check if ShooterCharacter has a valid EquippedWeapon
|
|
if (ShooterCharacter->GetEquippedWeapon())
|
|
{
|
|
EquippedWeaponType = ShooterCharacter->GetEquippedWeapon()->GetWeaponType();
|
|
}
|
|
|
|
TurnInPlace();
|
|
Lean(DeltaTime);
|
|
}
|
|
|
|
void UShooterAnimInstance::NativeInitializeAnimation()
|
|
{
|
|
Super::NativeInitializeAnimation();
|
|
|
|
ShooterCharacter = Cast<AShooterCharacter>(TryGetPawnOwner());
|
|
|
|
if (!ShooterCharacter) return;
|
|
|
|
TIPCharacterYaw = ShooterCharacter->GetActorRotation().Yaw;
|
|
TIPCharacterYawLastFrame = TIPCharacterYaw;
|
|
}
|
|
|
|
void UShooterAnimInstance::TurnInPlace()
|
|
{
|
|
if (!ShooterCharacter) return;
|
|
|
|
Pitch = ShooterCharacter->GetBaseAimRotation().Pitch;
|
|
|
|
if (Speed > 0 || bIsInAir)
|
|
{
|
|
// Don't want to turn in place; Character is moving
|
|
RootYawOffset = 0.f;
|
|
TIPCharacterYaw = ShooterCharacter->GetActorRotation().Yaw;
|
|
TIPCharacterYawLastFrame = TIPCharacterYaw;
|
|
RotationCurve = 0.f;
|
|
RotationCurveLastFrame = 0.f;
|
|
}
|
|
else
|
|
{
|
|
TIPCharacterYawLastFrame = TIPCharacterYaw;
|
|
TIPCharacterYaw = ShooterCharacter->GetActorRotation().Yaw;
|
|
const float TIPYawDelta { TIPCharacterYaw - TIPCharacterYawLastFrame };
|
|
|
|
// Root Yaw Offset, updated and clamped to [-180, 180]
|
|
RootYawOffset = UKismetMathLibrary::NormalizeAxis(RootYawOffset - TIPYawDelta);
|
|
|
|
// 1.0 if turning, 0.0 if not
|
|
const float Turning { GetCurveValue(TEXT("Turning")) };
|
|
if (Turning)
|
|
{
|
|
bTurningInPlace = true;
|
|
RotationCurveLastFrame = RotationCurve;
|
|
RotationCurve = GetCurveValue(TEXT("Rotation"));
|
|
const float DeltaRotation { RotationCurve = RotationCurveLastFrame };
|
|
|
|
// If RootYawOffset > 0, -> Turning Left, If RootYawOffset < 0, -> Turning Right
|
|
RootYawOffset > 0 ? RootYawOffset -= DeltaRotation : RootYawOffset += DeltaRotation;
|
|
|
|
const float ABSRootYawOffset { FMath::Abs(RootYawOffset) };
|
|
if (ABSRootYawOffset)
|
|
{
|
|
const float YawExcess { ABSRootYawOffset - 90.f };
|
|
RootYawOffset > 0 ? RootYawOffset -= YawExcess : RootYawOffset += YawExcess;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bTurningInPlace = false;
|
|
}
|
|
}
|
|
|
|
// Set the recoil weight
|
|
if (bTurningInPlace)
|
|
{
|
|
if (bReloading || bEquipping)
|
|
{
|
|
RecoilWeight = 1.f;
|
|
}
|
|
else
|
|
{
|
|
RecoilWeight = 0.f;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (bCrouching)
|
|
{
|
|
if (bReloading || bEquipping)
|
|
{
|
|
RecoilWeight = 1.f;
|
|
}
|
|
else
|
|
{
|
|
RecoilWeight = 0.1f;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (bAiming || bReloading || bEquipping)
|
|
{
|
|
RecoilWeight = 1.f;
|
|
}
|
|
else
|
|
{
|
|
RecoilWeight = 0.5f;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void UShooterAnimInstance::Lean(float DeltaTime)
|
|
{
|
|
if (!ShooterCharacter) return;
|
|
|
|
CharacterRotationLastFrame = CharacterRotation;
|
|
CharacterRotation = ShooterCharacter->GetActorRotation();
|
|
|
|
const FRotator Delta { UKismetMathLibrary::NormalizedDeltaRotator(CharacterRotation, CharacterRotationLastFrame) };
|
|
const double Target { Delta.Yaw / DeltaTime };
|
|
const double Interp { FMath::FInterpTo(YawDelta, Target, DeltaTime, 6.f) };
|
|
YawDelta = FMath::Clamp(Interp, -90.f, 90.f);
|
|
|
|
// if (GEngine)
|
|
// {
|
|
// GEngine->AddOnScreenDebugMessage(
|
|
// 3,
|
|
// -1,
|
|
// FColor::Cyan,
|
|
// FString::Printf(TEXT("YawDelta: %f"), YawDelta)
|
|
// );
|
|
// }
|
|
}
|