text: // Project:         Advanced Locomotion System V4 on C++
  // Copyright:       Copyright (C) 2020 Doğa Can Yanıkoğlu
  // License:         MIT License (http://www.opensource.org/licenses/mit-license.php)
  // Source Code:     https://github.com/dyanikoglu/ALSV4_CPP
  // Original Author: Doğa Can Yanıkoğlu
  // Contributors:    Haziq Fadhil
  
  
  #pragma once
  
  #include "CoreMinimal.h"
  #include "Components/TimelineComponent.h"
  #include "Library/ALSCharacterEnumLibrary.h"
  #include "Library/ALSCharacterStructLibrary.h"
  #include "Engine/DataTable.h"
  #include "GameFramework/Character.h"
  #include "Kismet/KismetSystemLibrary.h"
  
  #include "ALSBaseCharacter.generated.h"
  
  class UTimelineComponent;
  class UAnimInstance;
  class UAnimMontage;
  class UALSCharacterAnimInstance;
  enum class EVisibilityBasedAnimTickOption : uint8;
  
  /*
   * Base character class
   */
  UCLASS(BlueprintType)
  class ALSV4_CPP_API AALSBaseCharacter : public ACharacter
  {
  	GENERATED_BODY()
  
  public:
  	AALSBaseCharacter(const FObjectInitializer& ObjectInitializer);
  
  	UFUNCTION(BlueprintCallable, Category= "Movement")
  	FORCEINLINE class UALSCharacterMovementComponent* GetMyMovementComponent() const { return MyCharacterMovementComponent; }
  
  	virtual void Tick(float DeltaTime) override;
  
  	virtual void BeginPlay() override;
  
  	virtual void PreInitializeComponents() override;
  
  	virtual void Restart() override;
  
  	virtual void SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) override;
  
  	virtual void PostInitializeComponents() override;
  
  	void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
  
  	/** Ragdoll System */
  
  	/** Implement on BP to get required get up animation according to character's state */
  	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, Category = "ALS|Ragdoll System")
  	UAnimMontage* GetGetUpAnimation(bool bRagdollFaceUpState);
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Ragdoll System")
  	virtual void RagdollStart();
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Ragdoll System")
  	virtual void RagdollEnd();
  
  	UFUNCTION(BlueprintCallable, Server, Unreliable, Category = "ALS|Ragdoll System")
  	void Server_SetMeshLocationDuringRagdoll(FVector MeshLocation);
  
  	/** Character States */
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Character States")
  	void SetMovementState(EALSMovementState NewState);
  
  	UFUNCTION(BlueprintGetter, Category = "ALS|Character States")
  	EALSMovementState GetMovementState() const { return MovementState; }
  
  	UFUNCTION(BlueprintGetter, Category = "ALS|Character States")
  	EALSMovementState GetPrevMovementState() const { return PrevMovementState; }
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Character States")
  	void SetMovementAction(EALSMovementAction NewAction);
  
  	UFUNCTION(BlueprintGetter, Category = "ALS|Character States")
  	EALSMovementAction GetMovementAction() const { return MovementAction; }
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Character States")
  	void SetStance(EALSStance NewStance);
  
  	UFUNCTION(BlueprintGetter, Category = "ALS|Character States")
  	EALSStance GetStance() const { return Stance; }
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Character States")
  	void SetGait(EALSGait NewGait);
  
  	UFUNCTION(BlueprintGetter, Category = "ALS|Character States")
  	EALSGait GetGait() const { return Gait; }
  
  	UFUNCTION(BlueprintGetter, Category = "ALS|CharacterStates")
  	EALSGait GetDesiredGait() const { return DesiredGait; }
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Character States")
  	void SetRotationMode(EALSRotationMode NewRotationMode);
  
  	UFUNCTION(BlueprintCallable, Server, Reliable, Category = "ALS|Character States")
  	void Server_SetRotationMode(EALSRotationMode NewRotationMode);
  
  	UFUNCTION(BlueprintGetter, Category = "ALS|Character States")
  	EALSRotationMode GetRotationMode() const { return RotationMode; }
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Character States")
  	void SetViewMode(EALSViewMode NewViewMode);
  
  	UFUNCTION(BlueprintCallable, Server, Reliable, Category = "ALS|Character States")
  	void Server_SetViewMode(EALSViewMode NewViewMode);
  
  	UFUNCTION(BlueprintGetter, Category = "ALS|Character States")
  	EALSViewMode GetViewMode() const { return ViewMode; }
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Character States")
  	void SetOverlayState(EALSOverlayState NewState);
  
  	UFUNCTION(BlueprintCallable, Server, Reliable, Category = "ALS|Character States")
  	void Server_SetOverlayState(EALSOverlayState NewState);
  
  	UFUNCTION(BlueprintGetter, Category = "ALS|Character States")
  	EALSOverlayState GetOverlayState() const { return OverlayState; }
  
  	UFUNCTION(BlueprintGetter, Category = "ALS|Character States")
  	EALSOverlayState SwitchRight() const { return OverlayState; }
  
  	/** Landed, Jumped, Rolling, Mantling and Ragdoll*/
  	/** On Landed*/
  	UFUNCTION(BlueprintCallable, Category = "ALS|Character States")
  	void EventOnLanded();
  
  	UFUNCTION(BlueprintCallable, NetMulticast, Reliable, Category = "ALS|Character States")
  	void Multicast_OnLanded();
  
  	/** On Jumped*/
  	UFUNCTION(BlueprintCallable, Category = "ALS|Character States")
  	void EventOnJumped();
  
  	UFUNCTION(BlueprintCallable, NetMulticast, Reliable, Category = "ALS|Character States")
  	void Multicast_OnJumped();
  
  	/** Rolling Montage Play Replication*/
  	UFUNCTION(BlueprintCallable, Server, Reliable, Category = "ALS|Character States")
  	void Server_PlayMontage(UAnimMontage* montage, float track);
  
  	UFUNCTION(BlueprintCallable, NetMulticast, Reliable, Category = "ALS|Character States")
  	void Multicast_PlayMontage(UAnimMontage* montage, float track);
  
  	/** Mantling*/
  	UFUNCTION(BlueprintCallable, Server, Reliable, Category = "ALS|Character States")
  	void Server_MantleStart(float MantleHeight, const FALSComponentAndTransform& MantleLedgeWS, EALSMantleType MantleType);
  
  	UFUNCTION(BlueprintCallable, NetMulticast, Reliable, Category = "ALS|Character States")
  	void Multicast_MantleStart(float MantleHeight, const FALSComponentAndTransform& MantleLedgeWS, EALSMantleType MantleType);
  
  	/** Ragdolling*/
  	UFUNCTION(BlueprintCallable, Category = "ALS|Character States")
  	void ReplicatedRagdollStart();
  
  	UFUNCTION(BlueprintCallable, Server, Reliable, Category = "ALS|Character States")
  	void Server_RagdollStart();
  
  	UFUNCTION(BlueprintCallable, NetMulticast, Reliable, Category = "ALS|Character States")
  	void Multicast_RagdollStart();
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Character States")
  	void ReplicatedRagdollEnd();
  
  	UFUNCTION(BlueprintCallable, Server, Reliable, Category = "ALS|Character States")
  	void Server_RagdollEnd(FVector CharacterLocation);
  
  	UFUNCTION(BlueprintCallable, NetMulticast, Reliable, Category = "ALS|Character States")
  	void Multicast_RagdollEnd(FVector CharacterLocation);
  
  	/** Input */
  
  	UFUNCTION(BlueprintGetter, Category = "ALS|Input")
  	EALSStance GetDesiredStance() const { return DesiredStance; }
  
  	UFUNCTION(BlueprintSetter, Category = "ALS|Input")
  	void SetDesiredStance(EALSStance NewStance);
  
  	UFUNCTION(BlueprintCallable, Server, Reliable, Category = "ALS|Input")
  	void Server_SetDesiredStance(EALSStance NewStance);
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Character States")
  	void SetDesiredGait(EALSGait NewGait);
  
  	UFUNCTION(BlueprintCallable, Server, Reliable, Category = "ALS|Character States")
  	void Server_SetDesiredGait(EALSGait NewGait);
  
  	UFUNCTION(BlueprintGetter, Category = "ALS|Input")
  	EALSRotationMode GetDesiredRotationMode() const { return DesiredRotationMode; }
  
  	UFUNCTION(BlueprintSetter, Category = "ALS|Input")
  	void SetDesiredRotationMode(EALSRotationMode NewRotMode);
  
  	UFUNCTION(BlueprintCallable, Server, Reliable, Category = "ALS|Character States")
  	void Server_SetDesiredRotationMode(EALSRotationMode NewRotMode);
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Input")
  	FVector GetPlayerMovementInput() const;
  
  	/** Rotation System */
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Rotation System")
  	void SetActorLocationAndTargetRotation(FVector NewLocation, FRotator NewRotation);
  
  	/** Mantle System */
  
  	/** Implement on BP to get correct mantle parameter set according to character state */
  	UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, Category = "ALS|Mantle System")
  	FALSMantleAsset GetMantleAsset(EALSMantleType MantleType);
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Mantle System")
  	virtual bool MantleCheckGrounded();
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Mantle System")
  	virtual bool MantleCheckFalling();
  
  	/** Movement System */
  
  	UFUNCTION(BlueprintGetter, Category = "ALS|Movement System")
  	bool HasMovementInput() const { return bHasMovementInput; }
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Movement System")
  	void SetHasMovementInput(bool bNewHasMovementInput);
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Movement System")
  	FALSMovementSettings GetTargetMovementSettings() const;
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Movement System")
  	EALSGait GetAllowedGait() const;
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Movement States")
  	EALSGait GetActualGait(EALSGait AllowedGait) const;
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Movement System")
  	bool CanSprint() const;
  
  	/** BP implementable function that called when Breakfall starts */
  	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "ALS|Movement System")
  	void OnBreakfall();
  	virtual void OnBreakfall_Implementation();
  
  	/** BP implementable function that called when A Montage starts, e.g. during rolling */
  	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "ALS|Movement System")
  	void Replicated_PlayMontage(UAnimMontage* montage, float track);
  	virtual void Replicated_PlayMontage_Implementation(UAnimMontage* montage, float track);
  
  	/** Implement on BP to get required roll animation according to character's state */
  	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, Category = "ALS|Movement System")
  	UAnimMontage* GetRollAnimation();
  
  	/** Utility */
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Utility")
  	float GetAnimCurveValue(FName CurveName) const;
  
  	/** Implement on BP to draw debug spheres */
  	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, Category = "ALS|Debug")
  	void DrawDebugSpheres();
  
  	/** Camera System */
  
  	UFUNCTION(BlueprintGetter, Category = "ALS|Camera System")
  	bool IsRightShoulder() const { return bRightShoulder; }
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Camera System")
  	void SetRightShoulder(bool bNewRightShoulder) { bRightShoulder = bNewRightShoulder; }
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Camera System")
  	virtual ECollisionChannel GetThirdPersonTraceParams(FVector& TraceOrigin, float& TraceRadius);
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Camera System")
  	virtual FTransform GetThirdPersonPivotTarget();
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Camera System")
  	virtual FVector GetFirstPersonCameraTarget();
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Camera System")
  	void GetCameraParameters(float& TPFOVOut, float& FPFOVOut, bool& bRightShoulderOut) const;
  
  	/** Essential Information Getters/Setters */
  
  	UFUNCTION(BlueprintGetter, Category = "ALS|Essential Information")
  	FVector GetAcceleration() const { return Acceleration; }
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Essential Information")
  	void SetAcceleration(const FVector& NewAcceleration);
  
  	UFUNCTION(BlueprintGetter, Category = "ALS|Essential Information")
  	bool IsMoving() const { return bIsMoving; }
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Essential Information")
  	void SetIsMoving(bool bNewIsMoving);
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Essential Information")
  	FVector GetMovementInput() const;
  
  	UFUNCTION(BlueprintGetter, Category = "ALS|Essential Information")
  	float GetMovementInputAmount() const { return MovementInputAmount; }
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Essential Information")
  	void SetMovementInputAmount(float NewMovementInputAmount);
  
  	UFUNCTION(BlueprintGetter, Category = "ALS|Essential Information")
  	float GetSpeed() const { return Speed; }
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Essential Information")
  	void SetSpeed(float NewSpeed);
  
  	UFUNCTION(BlueprintCallable)
  	FRotator GetAimingRotation() const { return AimingRotation; }
  
  	UFUNCTION(BlueprintGetter, Category = "ALS|Essential Information")
  	float GetAimYawRate() const { return AimYawRate; }
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Essential Information")
  	void SetAimYawRate(float NewAimYawRate);
  
  	UFUNCTION(BlueprintCallable, Category = "ALS|Essential Information")
  	void GetControlForwardRightVector(FVector& Forward, FVector& Right) const;
  
  protected:
  	/** Ragdoll System */
  
  	void RagdollUpdate(float DeltaTime);
  
  	void SetActorLocationDuringRagdoll(float DeltaTime);
  
  	/** State Changes */
  
  	virtual void OnMovementModeChanged(EMovementMode PrevMovementMode, uint8 PreviousCustomMode = 0) override;
  
  	virtual void OnMovementStateChanged(EALSMovementState PreviousState);
  
  	virtual void OnMovementActionChanged(EALSMovementAction PreviousAction);
  
  	virtual void OnStanceChanged(EALSStance PreviousStance);
  
  	virtual void OnRotationModeChanged(EALSRotationMode PreviousRotationMode);
  
  	virtual void OnGaitChanged(EALSGait PreviousGait);
  
  	virtual void OnViewModeChanged(EALSViewMode PreviousViewMode);
  
  	virtual void OnOverlayStateChanged(EALSOverlayState PreviousState);
  
  	void OnStartCrouch(float HalfHeightAdjust, float ScaledHalfHeightAdjust) override;
  
  	void OnEndCrouch(float HalfHeightAdjust, float ScaledHalfHeightAdjust) override;
  
  	void OnJumped_Implementation() override;
  
  	void Landed(const FHitResult& Hit) override;
  
  	void OnLandFrictionReset();
  
  	void SetEssentialValues(float DeltaTime);
  
  	void UpdateCharacterMovement();
  
  	void UpdateDynamicMovementSettingsNetworked(EALSGait AllowedGait);
  
  	void UpdateDynamicMovementSettingsStandalone(EALSGait AllowedGait);
  
  	void UpdateGroundedRotation(float DeltaTime);
  
  	void UpdateInAirRotation(float DeltaTime);
  
  	/** Mantle System */
  
  	virtual void MantleStart(float MantleHeight, const FALSComponentAndTransform& MantleLedgeWS, EALSMantleType MantleType);
  
  	virtual bool MantleCheck(const FALSMantleTraceSettings& TraceSettings,
  	                         EDrawDebugTrace::Type DebugType = EDrawDebugTrace::Type::ForOneFrame);
  
  	UFUNCTION()
  	virtual void MantleUpdate(float BlendIn);
  
  	UFUNCTION()
  	virtual void MantleEnd();
  
  	/** Utils */
  
  	float GetMappedSpeed() const;
  
  	void SmoothCharacterRotation(FRotator Target, float TargetInterpSpeed, float ActorInterpSpeed, float DeltaTime);
  
  	float CalculateGroundedRotationRate() const;
  
  	void LimitRotation(float AimYawMin, float AimYawMax, float InterpSpeed, float DeltaTime);
  
  	void SetMovementModel();
  
  	/** Input */
  
  	void PlayerForwardMovementInput(float Value);
  
  	void PlayerRightMovementInput(float Value);
  
  	void PlayerCameraUpInput(float Value);
  
  	void PlayerCameraRightInput(float Value);
  
  	void JumpPressedAction();
  
  	void JumpReleasedAction();
  
  	void SprintPressedAction();
  
  	void SprintReleasedAction();
  
  	void AimPressedAction();
  
  	void AimReleasedAction();
  
  	void CameraPressedAction();
  
  	void CameraReleasedAction();
  
  	void OnSwitchCameraMode();
  
  	void StancePressedAction();
  
  	void WalkPressedAction();
  
  	void RagdollPressedAction();
  
  	void VelocityDirectionPressedAction();
  
  	void LookingDirectionPressedAction();
  
  	/** Replication */
  	UFUNCTION()
  	void OnRep_RotationMode(EALSRotationMode PrevRotMode);
  
  	UFUNCTION()
  	void OnRep_ViewMode(EALSViewMode PrevViewMode);
  
  	UFUNCTION()
  	void OnRep_OverlayState(EALSOverlayState PrevOverlayState);
  
  protected:
  	/* Custom movement component*/
  	UALSCharacterMovementComponent* MyCharacterMovementComponent;
  
  	/** Input */
  
  	UPROPERTY(EditAnywhere, Replicated, BlueprintReadWrite, Category = "ALS|Input")
  	EALSRotationMode DesiredRotationMode = EALSRotationMode::LookingDirection;
  
  	UPROPERTY(EditAnywhere, Replicated, BlueprintReadWrite, Category = "ALS|Input")
  	EALSGait DesiredGait = EALSGait::Running;
  
  	UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category = "ALS|Input")
  	EALSStance DesiredStance = EALSStance::Standing;
  
  	UPROPERTY(EditDefaultsOnly, Category = "ALS|Input", BlueprintReadOnly)
  	float LookUpDownRate = 1.25f;
  
  	UPROPERTY(EditDefaultsOnly, Category = "ALS|Input", BlueprintReadOnly)
  	float LookLeftRightRate = 1.25f;
  
  	UPROPERTY(EditDefaultsOnly, Category = "ALS|Input", BlueprintReadOnly)
  	float RollDoubleTapTimeout = 0.3f;
  
  	UPROPERTY(EditDefaultsOnly, Category = "ALS|Input", BlueprintReadOnly)
  	float ViewModeSwitchHoldTime = 0.2f;
  
  	UPROPERTY(Category = "ALS|Input", BlueprintReadOnly)
  	int32 TimesPressedStance = 0;
  
  	UPROPERTY(Category = "ALS|Input", BlueprintReadOnly)
  	bool bBreakFall = false;
  
  	UPROPERTY(Category = "ALS|Input", BlueprintReadOnly)
  	bool bSprintHeld = false;
  
  	/** Camera System */
  
  	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "ALS|Camera System")
  	float ThirdPersonFOV = 90.0f;
  
  	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "ALS|Camera System")
  	float FirstPersonFOV = 90.0f;
  
  	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "ALS|Camera System")
  	bool bRightShoulder = false;
  
  	/** State Values */
  
  	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "ALS|State Values", ReplicatedUsing = OnRep_OverlayState)
  	EALSOverlayState OverlayState = EALSOverlayState::Default;
  
  	/** Movement System */
  
  	UPROPERTY(BlueprintReadOnly, Category = "ALS|Movement System")
  	FALSMovementSettings CurrentMovementSettings;
  
  	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "ALS|Movement System")
  	FDataTableRowHandle MovementModel;
  
  	/** Mantle System */
  
  	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "ALS|Mantle System")
  	FALSMantleTraceSettings GroundedTraceSettings;
  
  	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "ALS|Mantle System")
  	FALSMantleTraceSettings AutomaticTraceSettings;
  
  	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "ALS|Mantle System")
  	FALSMantleTraceSettings FallingTraceSettings;
  
  	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "ALS|Mantle System")
  	UCurveFloat* MantleTimelineCurve;
  
  	/** Components */
  
  	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "ALS|Components")
  	UTimelineComponent* MantleTimeline = nullptr;
  
  	/** Essential Information */
  
  	UPROPERTY(BlueprintReadOnly, Category = "ALS|Essential Information")
  	FVector Acceleration;
  
  	UPROPERTY(BlueprintReadOnly, Category = "ALS|Essential Information")
  	bool bIsMoving = false;
  
  	UPROPERTY(BlueprintReadOnly, Category = "ALS|Essential Information")
  	bool bHasMovementInput = false;
  
  	UPROPERTY(BlueprintReadOnly, Category = "ALS|Essential Information")
  	FRotator LastVelocityRotation;
  
  	UPROPERTY(BlueprintReadOnly, Category = "ALS|Essential Information")
  	FRotator LastMovementInputRotation;
  
  	UPROPERTY(BlueprintReadOnly, Category = "ALS|Essential Information")
  	float Speed = 0.0f;
  
  	UPROPERTY(BlueprintReadOnly, Category = "ALS|Essential Information")
  	float MovementInputAmount = 0.0f;
  
  	UPROPERTY(BlueprintReadOnly, Category = "ALS|Essential Information")
  	float AimYawRate = 0.0f;
  
  	/** Replicated Essential Information*/
  
  	UPROPERTY(BlueprintReadOnly, Category = "ALS|Essential Information")
  	float EasedMaxAcceleration;
  
  	UPROPERTY(BlueprintReadOnly, Replicated, Category = "ALS|Essential Information")
  	FVector ReplicatedCurrentAcceleration;
  
  	UPROPERTY(BlueprintReadOnly, Replicated, Category = "ALS|Essential Information")
  	FRotator ReplicatedControlRotation;
  
  	/** State Values */
  
  	UPROPERTY(BlueprintReadOnly, Category = "ALS|State Values")
  	EALSMovementState MovementState = EALSMovementState::None;
  
  	UPROPERTY(BlueprintReadOnly, Category = "ALS|State Values")
  	EALSMovementState PrevMovementState = EALSMovementState::None;
  
  	UPROPERTY(BlueprintReadOnly, Category = "ALS|State Values")
  	EALSMovementAction MovementAction = EALSMovementAction::None;
  
  	UPROPERTY(BlueprintReadOnly, Category = "ALS|State Values", ReplicatedUsing = OnRep_RotationMode)
  	EALSRotationMode RotationMode = EALSRotationMode::LookingDirection;
  
  	UPROPERTY(BlueprintReadOnly, Category = "ALS|State Values")
  	EALSGait Gait = EALSGait::Walking;
  
  	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "ALS|State Values")
  	EALSStance Stance = EALSStance::Standing;
  
  	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "ALS|State Values", ReplicatedUsing = OnRep_ViewMode)
  	EALSViewMode ViewMode = EALSViewMode::ThirdPerson;
  
  	/** Movement System */
  
  	UPROPERTY(BlueprintReadOnly, Category = "ALS|Movement System")
  	FALSMovementStateSettings MovementData;
  
  	/** Rotation System */
  
  	UPROPERTY(BlueprintReadOnly, Category = "ALS|Rotation System")
  	FRotator TargetRotation;
  
  	UPROPERTY(BlueprintReadOnly, Category = "ALS|Rotation System")
  	FRotator InAirRotation;
  
  	UPROPERTY(BlueprintReadOnly, Category = "ALS|Rotation System")
  	float YawOffset = 0.0f;
  
  	/** Mantle System */
  
  	UPROPERTY(BlueprintReadOnly, Category = "ALS|Mantle System")
  	FALSMantleParams MantleParams;
  
  	UPROPERTY(BlueprintReadOnly, Category = "ALS|Mantle System")
  	FALSComponentAndTransform MantleLedgeLS;
  
  	UPROPERTY(BlueprintReadOnly, Category = "ALS|Mantle System")
  	FTransform MantleTarget;
  
  	UPROPERTY(BlueprintReadOnly, Category = "ALS|Mantle System")
  	FTransform MantleActualStartOffset;
  
  	UPROPERTY(BlueprintReadOnly, Category = "ALS|Mantle System")
  	FTransform MantleAnimatedStartOffset;
  
  	/** Breakfall System */
  
  	/** If player hits to the ground with a specified amount of velocity, switch to breakfall state */
  	UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Category = "ALS|Breakfall System")
  	bool bBreakfallOnLand = true;
  
  	/** If player hits to the ground with an amount of velocity greater than specified value, switch to breakfall state */
  	UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Category = "ALS|Breakfall System", meta = (EditCondition = "bBreakfallOnLand"))
  	float BreakfallOnLandVelocity = 600.0f;
  
  	/** Ragdoll System */
  
  	/** If player hits to the ground with a specified amount of velocity, switch to ragdoll state */
  	UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Category = "ALS|Ragdoll System")
  	bool bRagdollOnLand = false;
  
  	/** If player hits to the ground with an amount of velocity greater than specified value, switch to ragdoll state */
  	UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Category = "ALS|Ragdoll System", meta = (EditCondition = "bRagdollOnLand"))
  	float RagdollOnLandVelocity = 1000.0f;
  
  	UPROPERTY(BlueprintReadOnly, Category = "ALS|Ragdoll System")
  	bool bRagdollOnGround = false;
  
  	UPROPERTY(BlueprintReadOnly, Category = "ALS|Ragdoll System")
  	bool bRagdollFaceUp = false;
  
  	UPROPERTY(BlueprintReadOnly, Category = "ALS|Ragdoll System")
  	FVector LastRagdollVelocity;
  
  	UPROPERTY(BlueprintReadOnly, Replicated, Category = "ALS|Ragdoll System")
  	FVector TargetRagdollLocation;
  
  	/* Server ragdoll pull force storage*/
  	float ServerRagdollPull = 0.0f;
  
  	/* Dedicated server mesh default visibility based anim tick option*/
  	EVisibilityBasedAnimTickOption DefVisBasedTickOp;
  
  	/** Cached Variables */
  
  	FVector PreviousVelocity;
  
  	float PreviousAimYaw = 0.0f;
  
  	UPROPERTY(BlueprintReadOnly)
  	UALSCharacterAnimInstance* MainAnimInstance = nullptr;
  
  	/** Last time the 'first' crouch/roll button is pressed */
  	float LastStanceInputTime = 0.0f;
  
  	/** Last time the camera action button is pressed */
  	float CameraActionPressedTime = 0.0f;
  
  	/* Timer to manage camera mode swap action */
  	FTimerHandle OnCameraModeSwapTimer;
  
  	/* Timer to manage reset of braking friction factor after on landed event */
  	FTimerHandle OnLandedFrictionResetTimer;
  
  	/* Smooth out aiming by interping control rotation*/
  	FRotator AimingRotation;
  
  	/** We won't use curve based movement on networked games */
  	bool bDisableCurvedMovement = false;
  };
  