//============================================================================= // KFCustomizationCamera //============================================================================= // Class Description //============================================================================= // Killing Floor 2 // Copyright (C) 2015 Tripwire Interactive LLC // - Author 1/20/2014 //============================================================================= class KFCustomizationCamera extends GameCameraBase; var bool bInitialize; var byte BodyViewIndex; var byte CurrentViewIndex; var() Vector CharacterOffset; var() Vector HeadOffset; var float CharacterDistance; var float HeadDistance; var int RotationOffset; var int RotationRate; var int MaxRotationRate; var int LastRotation; var float FadeRotationStartTime; var float FadeRotationDuration; var float FadeRotationScaler; /** Called when the camera becomes active */ function OnBecomeActive( GameCameraBase OldCamera ) { SetCustomizationView( PlayerCamera, PlayerCamera.ViewTarget, CharacterOffset, CharacterDistance ); } function UpdateCamera(Pawn P, GamePlayerCamera CameraActor, float DeltaTime, out TViewTarget OutVT) { // OnBecomeActive doesn't have the customization pawn at the start of the game if ( !bInitialize && P != none ) { SetCustomizationView( CameraActor, OutVT, CharacterOffset, CharacterDistance ); bInitialize = true; } if( PlayerCamera.PCOwner.Pawn != none ) { PlayerCamera.PCOwner.SetViewTarget( PlayerCamera.PCOwner.Pawn ); } // cameraanims, fades, etc PlayerCamera.ApplyCameraModifiers( DeltaTime, OutVT.POV ); } function SetBodyView( byte Index, optional bool bForceView = false ) { if ( BodyViewIndex != Index || bForceView ) { BodyViewIndex = Index; BlendCustomizationPart( PlayerCamera, BodyViewIndex ); } } function BlendCustomizationPart( GamePlayerCamera CameraActor, byte Index ) { CurrentViewIndex = Index; CameraActor.ViewTarget.POV = CameraActor.CameraCache.POV; CameraActor.PendingViewTarget.Target = CameraActor.ViewTarget.Target; switch ( Index ) { case 0: SetCustomizationView( CameraActor, CameraActor.PendingViewTarget, CharacterOffset, CharacterDistance ); break; case 1: SetCustomizationView( CameraActor, CameraActor.PendingViewTarget, HeadOffset, HeadDistance ); break; } } function SetCustomizationView( GamePlayerCamera CameraActor, out TViewTarget OutVT, Vector Offset, float Distance ) { local vector Loc, Pos, HitLocation, HitNormal; local rotator Rot; local Actor HitActor; Loc = OutVT.Target.Location; Rot = OutVT.Target.Rotation; Rot.Yaw += RotationOffset; CameraActor.BlendTimeToGo = 0.5f; CameraActor.BlendParams.BlendTime = CameraActor.BlendTimeToGo; Loc += Offset >> Rot; Pos = Loc - Vector(Rot) * Distance; HitActor = CameraActor.Trace(HitLocation, HitNormal, Pos, Loc, FALSE, vect(12,12,12)); OutVT.POV.Location = (HitActor == None) ? Pos : HitLocation; OutVT.POV.Rotation = Rot; } /** This is used to remember the last known mouse input for fading out */ function RotatedCamera( int DirectionOffset ) { DirectionOffset = FClamp(DirectionOffset, -MaxRotationRate, MaxRotationRate); UpdateRotation( DirectionOffset ); // LastRotation is used for when the mouse is released LastRotation = DirectionOffset / FadeRotationScaler; } function UpdateRotation( int DirectionOffset ) { if( PlayerCamera.PCOwner.IsTimerActive(nameof(FadeCameraRotation)) ) { PlayerCamera.PCOwner.ClearTimer(nameof(FadeCameraRotation), self); } RotationOffset += DirectionOffset * RotationRate; //BlendCustomizationPart( PlayerCamera, CurrentViewIndex ); if( CurrentViewIndex == 0 ) { SetCustomizationView( PlayerCamera, PlayerCamera.ViewTarget, CharacterOffset, CharacterDistance ); } else { SetCustomizationView( PlayerCamera, PlayerCamera.ViewTarget, HeadOffset, HeadDistance ); } } /** Once we let go of the mouse, lerp the rotation to a halt */ function StartFadeRotation() { if( LastRotation != 0 ) { // Scale the duration of the fading rotation by how strong our mouse movement was FadeRotationDuration = Abs(LastRotation) * 0.01f; FadeRotationStartTime = PlayerCamera.PCOwner.WorldInfo.TimeSeconds; PlayerCamera.PCOwner.SetTimer( 0.01f, true, nameof(FadeCameraRotation), self ); } } /** Handles lerping the camera rotation once we let go */ function FadeCameraRotation() { local int NewRotation; local float RotationAlpha; RotationAlpha = (PlayerCamera.PCOwner.WorldInfo.TimeSeconds - FadeRotationStartTime) / FadeRotationDuration; RotationAlpha = FClamp(RotationAlpha, 0, 1); NewRotation = Lerp(LastRotation, 0, RotationAlpha); if( RotationAlpha >= 1 ) { PlayerCamera.PCOwner.ClearTimer(nameof(FadeCameraRotation), self); LastRotation = 0; NewRotation = 0; } UpdateRotation( NewRotation ); } /** Called when the camera becomes inactive */ function OnBecomeInActive( GameCameraBase NewCamera ) { super.OnBecomeInActive( NewCamera ); bInitialize = false; LastRotation = 0; } defaultproperties { CharacterOffset=(X=0,Y=-15,Z=6) HeadOffset=(X=0,Y=-15,Z=68) CharacterDistance=200 HeadDistance=70 RotationOffset=38500 RotationRate=50 MaxRotationRate=100 FadeRotationDuration=0.2f FadeRotationScaler=3.5f }