//============================================================================= // KFPlayerZedWaitingCamera //============================================================================= // Camera class for waiting zed players //============================================================================= // Killing Floor 2 // Copyright (C) 2015 Tripwire Interactive LLC // Matt "Squirrlz" Farber //============================================================================= class KFPlayerZedWaitingCamera extends GameFixedCamera; /** Actor we're currently using as an anchor for our fixed camera */ var Actor FocalPoint; /** Array of player starts, filled when the camera goes live */ var array AvailableFocalPoints; /** Location offset from focal point base */ var vector CameraOffset; /** Angle to pitch the camera at */ var int CameraPitchAngle; /** How long the camera should linger on a focal point */ var float CameraLingerDuration; /** Last time we changed camera focal points */ var float LastCameraChangeTime; /** FOV angle used for this camera mode */ var float CameraFOV; /** Interpolated camera yaw value */ var float CameraYaw; /** Multiplier used to control how fast the camera pans */ var float CameraPanSpeed; /** Color to use when fading between camera points */ var color FadeColor; /** Fade time */ var float FadeTime; /** Whether we've played a camera fade out before swapping focal points or not */ var bool bPlayedCameraFade; /** Color to fade out with when switching away from this camera mode */ var color ExitFadeColor; /** Whether we've played our camera swap fade */ var bool bPlayedExitFade; /** Light component for our focal point */ var PointLightComponent CameraLightTemplate; var transient PointLightComponent CameraLight; /** Called when the camera becomes active */ function OnBecomeActive( GameCameraBase OldCamera ) { super.OnBecomeActive( OldCamera ); // Fade in if( PlayerCamera != none && PlayerCamera.PCOwner != none ) { PlayerCamera.PCOwner.ClientSetCameraFade( true, FadeColor, vect2d(1.f, 0.f), FadeTime, true ); } CameraOffset = default.CameraOffset; bPlayedCameraFade = false; bPlayedExitFade = false; // Create our light if( CameraLight == none && CameraLightTemplate != none ) { CameraLight = new(self) class'PointLightComponent'( CameraLightTemplate ); } // Pick a focal point UpdateCameraFocalPoint(); } /** Fills our array of focal points */ function PopulateFocalPoints() { local KFPlayerStart KFPS; local KFTraderTrigger KFTT; local KFPathnode KFPN; local bool bHostileGroundsHackFix; // @TODO: HACK FIXME! REMOVE WHEN RENDERER CRASH HAS BEEN SOLVED bHostileGroundsHackFix = InStr( class'WorldInfo'.static.GetWorldInfo().GetMapName(), "hostilegrounds",, true ) != INDEX_NONE; `if(`notdefined(ShippingPC) ) if( `TimeSinceEx(PlayerCamera, PlayerCamera.CreationTime) < 5.f ) { `log( "[DEBUGVERSUS] KF-HostileGrounds hack fix applied in KFPlayerZedWaitingCamera! FIXME!" ); } `endif // Fill out focal points array with player starts foreach PlayerCamera.WorldInfo.AllNavigationPoints( class'KFPlayerStart', KFPS ) { if( bHostileGroundsHackFix && (KFPS.Name == 'KFPlayerStart_44' || KFPS.Name == 'KFPlayerStart_37') ) { AvailableFocalPoints[AvailableFocalPoints.Length] = KFPS; } } if( bHostileGroundsHackFix ) { return; } // Fill out focal points array with path nodes near trader triggers foreach PlayerCamera.WorldInfo.AllNavigationPoints( class'KFPathnode', KFPN ) { foreach PlayerCamera.DynamicActors( class'KFTraderTrigger', KFTT ) { if( VSizeSQ(KFTT.Location - KFPN.Location) <= 160000.f ) { AvailableFocalPoints[AvailableFocalPoints.Length] = KFPN; break; } } } } /** Gets a new focal point for the camera */ function UpdateCameraFocalPoint() { local int FocalPointNum; local vector HitLocation, HitNormal; local vector Projection; local KFTraderTrigger KFTT; if( PlayerCamera != none && PlayerCamera.PCOwner != none && PlayerCamera.WorldInfo.NetMode != NM_DedicatedServer ) { if( AvailableFocalPoints.Length == 0 ) { PopulateFocalPoints(); } if( FocalPoint != none ) { // Make sure our current focal point is not the next one chosen FocalPointNum = AvailableFocalPoints.Find( FocalPoint ); if( FocalPointNum != INDEX_NONE ) { AvailableFocalPoints.Remove( FocalPointNum, 1 ); } // In case we just cleared focal points, repopulate the list if( AvailableFocalPoints.Length == 0 ) { PopulateFocalPoints(); } // Detach our ambient light FocalPoint.DetachComponent( CameraLight ); } LastCameraChangeTime = PlayerCamera.WorldInfo.TimeSeconds; FocalPoint = AvailableFocalPoints[Rand(AvailableFocalPoints.Length)]; // Set our initial rotation to face away from the trader (if we're a pathnode) foreach FocalPoint.AllActors( class'KFTraderTrigger', KFTT ) { Projection = FocalPoint.Location - KFTT.Location; if( VSizeSQ(Projection) <= 160000.f ) { CameraYaw = ( rotator(Projection).Yaw + (8192 - Rand(16384)) ) & 65535; break; } } PlayerCamera.PCOwner.SetViewTarget( FocalPoint ); if( FocalPoint != none ) { // Make sure the camera is in a valid location FocalPoint.Trace( HitLocation, HitNormal, FocalPoint.Location + (vect(0,0,1) * (default.CameraOffset.Z + 30.f)), FocalPoint.Location, false,,, FocalPoint.TRACEFLAG_Bullet ); // Offset it if we would have been inside geometry if( !IsZero(HitLocation) ) { CameraOffset.Z = VSize( HitLocation - FocalPoint.Location ) - 30.f; } else { CameraOffset = default.CameraOffset; } // Attach our ambient light FocalPoint.AttachComponent( CameraLight ); CameraLight.SetEnabled( true ); } // Play a camera fade PlayerCamera.PCOwner.ClientSetCameraFade( true, FadeColor, vect2d(1.f, 0.f), FadeTime, true ); bPlayedCameraFade = false; } else if( FocalPoint != none ) { FocalPoint.DetachComponent( CameraLight ); FocalPoint = none; } } /** Expected to fill in OutVT with new camera pos/loc/fov. */ simulated function UpdateCamera( Pawn P, GamePlayerCamera CameraActor, float DeltaTime, out TViewTarget OutVT ) { if( PlayerCamera != none && (PlayerCamera.WorldInfo.TimeSeconds - LastCameraChangeTime) >= (CameraLingerDuration - FadeTime) ) { if( !bPlayedCameraFade ) { // Play a camera fade PlayerCamera.PCOwner.ClientSetCameraFade( true, FadeColor, vect2d(0.f, 1.f), FadeTime, true ); bPlayedCameraFade = true; } if( PlayerCamera.WorldInfo.TimeSeconds - LastCameraChangeTime >= CameraLingerDuration ) { UpdateCameraFocalPoint(); } } if( FocalPoint != none ) { // Set location and rotation OutVT.POV.Location = FocalPoint.Location + CameraOffset; OutVT.POV.Rotation.Pitch = CameraPitchAngle; CameraYaw = ( CameraYaw + (CameraPanSpeed * DeltaTime) ) & 65535; OutVT.POV.Rotation.Yaw = CameraYaw; // Set FOV OutVT.POV.FOV = CameraFOV; // cameraanims, fades, etc PlayerCamera.ApplyCameraModifiers( DeltaTime, OutVT.POV ); } // if we had to reset camera interpolation, then turn off flag once it's been processed. bResetCameraInterpolation = false; super(GameCameraBase).UpdateCamera( P, CameraActor, DeltaTime, OutVT ); } /** Fades out when leaving this camera mode */ function PlayExitFade() { if( !bPlayedExitFade ) { PlayerCamera.PCOwner.ClientSetCameraFade( true, ExitFadeColor, vect2d(1.f, 0.f), FadeTime, true ); bPlayedExitFade = true; } } /** Called when the camera becomes inactive */ function OnBecomeInActive( GameCameraBase NewCamera ) { super.OnBecomeInActive( NewCamera ); // Detach and de-reference our light if( CameraLight != none ) { if( FocalPoint != none ) { FocalPoint.DetachComponent( CameraLight ); } CameraLight.SetEnabled( false ); CameraLight = none; } // Fade out our camera transition PlayExitFade(); // Restore defaults CameraOffset = default.CameraOffset; FocalPoint = none; bPlayedCameraFade = false; } DefaultProperties { CameraOffset=(X=0,Y=0,Z=300.f) CameraPitchAngle=-3072 CameraLingerDuration=12.f CameraFOV=160.f CameraPanSpeed=256.f FadeColor=(R=0,G=0,B=0) FadeTime=1.f ExitFadeColor=(R=255,G=255,B=255) Begin Object Class=PointLightComponent Name=PointLightTemplate_0 LightColor=(R=230,G=255,B=235,A=255) Brightness=0.2f Radius=2000.f FalloffExponent=10.f CastShadows=false CastStaticShadows=false CastDynamicShadows=false bCastPerObjectShadows=false bEnabled=false LightingChannels=(Indoor=TRUE,Outdoor=TRUE,bInitialized=TRUE) End Object CameraLightTemplate=PointLightTemplate_0 }