Files
gtav-src/script/dev_ng/singleplayer/include/public/RC_Camera_Public.sch
T
2025-09-29 00:52:08 +02:00

467 lines
13 KiB
Scheme
Executable File

// *****************************************************************************************
// *****************************************************************************************
//
// MISSION NAME : RC_Camera_Public.sch
// AUTHOR : Aaron Gandaa
// DESCRIPTION : Camera Helper Functions
//
// *****************************************************************************************
// *****************************************************************************************
//----------------------
// INCLUDES
//----------------------
USING "rage_builtins.sch"
USING "globals.sch"
USING "rgeneral_include.sch"
USING "RC_Helper_Functions.sch"
//----------------------
// CONSTANTS
//----------------------
CONST_FLOAT FPSCAM_LIMITYAW 80.0
CONST_FLOAT FPSCAM_LIMITPITCH 30.0
CONST_FLOAT FPSCAM_LOOKSPEED 60.0
CONST_FLOAT FPSCAM_MINZOOM 20.0
CONST_FLOAT FPSCAM_MAXZOOM 50.0
CONST_FLOAT CAMERA_NOSWITCHRATIO -99.0
//----------------------
// STRUCT
//----------------------
STRUCT BASIC_CAMERA
BOOL bFPSMode = FALSE
BOOL bSetup = FALSE
VECTOR vPosition
VECTOR vLookAt
ENTITY_INDEX sourceID
ENTITY_INDEX targetID // if this is set - look at is ignored
CAMERA_INDEX cameraID
FLOAT fLookPitch = 0.0
FLOAT fLookYaw = 0.0
FLOAT fFov = 0.0
BOOL bWrapLookPitch = FALSE
BOOL bWrapLookYaw = FALSE
ENDSTRUCT
STRUCT CAMERA_STRUCT
BOOL bSetup = FALSE
VECTOR vPosition[2]
VECTOR vRotation[2]
FLOAT fFov[2]
FLOAT fHeightOffset // Bump the camera up this amount for large vehicles
INT iActivationTime // the time the camera turned on
INT iInterpolateTime // time to move from point a to b (in ms)
ENTITY_INDEX targetID // if this is set - rotation is ignored
FLOAT fSwitchRatio = CAMERA_NOSWITCHRATIO
ENDSTRUCT
//----------------------
// CAMERA FUNCTIONS
//----------------------
/// PURPOSE:
/// Shutdown and Destroy A Camera
/// PARAMS:
/// cameraID - camera index
/// bInterp - set this to interpolate back to game camera
PROC SHUTDOWN_CAMERA(CAMERA_INDEX &cameraID, BOOL bInterp = FALSE)
IF DOES_CAM_EXIST(cameraID)
RENDER_SCRIPT_CAMS(FALSE, bInterp)
SET_CAM_ACTIVE(cameraID, FALSE)
DESTROY_CAM(cameraID)
cameraID = NULL
ENDIF
ENDPROC
//----------------------
// STRUCT FUNCTIONS
//----------------------
/// PURPOSE:
/// Resets the camera struct to zero
/// PARAMS:
/// cr - camera struct reference
PROC ZERO_CAMERA_STRUCT(CAMERA_STRUCT &cr)
cr.bSetup = FALSE
cr.vPosition[0] = <<0, 0, 0>>
cr.vPosition[1] = <<0, 0, 0>>
cr.vRotation[0] = <<0, 0, 0>>
cr.vRotation[1] = <<0, 0, 0>>
cr.fFov[0] = 50.0
cr.fFov[1] = 0.0
cr.targetID = NULL
cr.iInterpolateTime = 0
ENDPROC
/// PURPOSE:
/// Sets up a single non moving camera struct
/// PARAMS:
/// cr - camera reference
/// pos - position of camera
/// rot - rotation of camera
PROC SETUP_CAMERA_STRUCT(CAMERA_STRUCT &cr, VECTOR pos, VECTOR rot, ENTITY_INDEX tgtent = NULL, FLOAT fHeightOffset = 0.0)
ZERO_CAMERA_STRUCT(cr)
cr.vPosition[0] = pos
cr.vRotation[0] = rot
cr.bSetup = TRUE
cr.targetID = tgtent // if this is set - rotation is ignored
cr.fHeightOffset = fHeightOffset
cr.iInterpolateTime = 0
ENDPROC
/// PURPOSE:
/// Sets up a single non moving camera struct
/// PARAMS:
/// cr - camera reference
/// pos - position of camera
/// rot - rotation of camera
PROC SETUP_CAMERA_STRUCT_END_SHOT(CAMERA_STRUCT &cr, VECTOR pos, VECTOR rot, INT iTime)
cr.vPosition[1] = pos
cr.vRotation[1] = rot
cr.bSetup = TRUE
cr.iInterpolateTime = iTime
ENDPROC
/// PURPOSE:
/// Sets up a tracking camera struct
/// PARAMS:
/// cr - camera reference
/// pos - position of start camera
/// rot - rotation of start camera
/// pos2 - position of end camera
/// rot2 - rotation of end camera
/// iTime - time to interpolate
PROC SETUP_CAMERA_STRUCT_INTERPOLATE(CAMERA_STRUCT &cr, VECTOR pos1, VECTOR rot1, VECTOR pos2, VECTOR rot2, INT iTime, FLOAT fHeightOffset = 0.0)
SETUP_CAMERA_STRUCT(cr, pos1, rot1, DEFAULT, fHeightOffset)
SETUP_CAMERA_STRUCT_END_SHOT(cr, pos2, rot2, iTime)
ENDPROC
PROC SETUP_CAMERA_SWITCH_RATIO(CAMERA_STRUCT &cr, FLOAT swr)
cr.fSwitchRatio = swr
ENDPROC
/// PURPOSE:
/// Sets the camera fov
/// PARAMS:
/// cr - camera reference
/// fov1 - start field of view
/// fov2 - end field of view - set this to zero to ignore
PROC SETUP_CAMERA_STRUCT_FOV(CAMERA_STRUCT &cr, FLOAT fov1, FLOAT fov2 = 0.0)
cr.fFov[0] = fov1
IF (fov2 = 0.0)
cr.fFov[1] = fov1
ELSE
cr.fFov[1] = fov2
ENDIF
ENDPROC
PROC SETUP_CAMERA_STRUCT_INTERPOLATE_TIME(CAMERA_STRUCT &cr, INT iTime)
cr.iInterpolateTime = iTime
ENDPROC
/// PURPOSE:
/// Enables the camera struct
/// PARAMS:
/// cr - camera reference
/// cameraID - camera index to write to
PROC ENABLE_CAMERA_STRUCT(CAMERA_STRUCT &cr, CAMERA_INDEX &cameraID, BOOL bBigVehicle = FALSE, BOOL bDontLerp = FALSE, CAMERA_GRAPH_TYPE cameraGraphPos = GRAPH_TYPE_SIN_ACCEL_DECEL, CAMERA_GRAPH_TYPE cameraGraphRot = GRAPH_TYPE_SIN_ACCEL_DECEL)
VECTOR vPos
FLOAT fov = cr.fFov[1]
IF (cr.bSetup = FALSE)
EXIT
ENDIF
SHUTDOWN_CAMERA(cameraID)
vPos = cr.vPosition[0]
IF bBigVehicle
vPos.z += cr.fHeightOffset
ENDIF
cameraID = CREATE_CAM_WITH_PARAMS("DEFAULT_SCRIPTED_CAMERA", vPos, cr.vRotation[0], cr.fFov[0], TRUE)
IF NOT DOES_CAM_EXIST(cameraID)
EXIT
ENDIF
cr.iActivationTime = GET_GAME_TIMER()
SET_CAM_ACTIVE(cameraID, TRUE)
RENDER_SCRIPT_CAMS(TRUE, FALSE)
IF (NOT bDontLerp) AND (cr.iInterpolateTime > 0) AND NOT IS_VECTOR_ZERO(cr.vPosition[1])
vPos = cr.vPosition[1]
IF bBigVehicle
vPos.z += cr.fHeightOffset
ENDIF
IF (fov = 0.0)
fov = cr.fFov[0]
ENDIF
SET_CAM_PARAMS(cameraID, vPos, cr.vRotation[1], fov, cr.iInterpolateTime, cameraGraphPos, cameraGraphRot)
ELIF IS_ENTITY_OK(cr.targetID)
POINT_CAM_AT_ENTITY(cameraID, cr.targetID, <<0, 0, 0>>)
ENDIF
ENDPROC
/// PURPOSE:
/// Enables the camera struct
/// PARAMS:
/// cr - camera reference
/// cameraID - camera index to write to
PROC ENABLE_CAMERA_STRUCT_REVERSE_INTERPOLATE(CAMERA_STRUCT &cr, CAMERA_INDEX &cameraID)
FLOAT fov = cr.fFov[1]
IF (cr.bSetup = FALSE)
EXIT
ENDIF
IF (cr.iInterpolateTime <= 0) OR IS_VECTOR_ZERO(cr.vPosition[1])
ENABLE_CAMERA_STRUCT(cr, cameraID)
EXIT
ENDIF
IF (fov = 0.0)
fov = cr.fFov[0]
ENDIF
SHUTDOWN_CAMERA(cameraID)
cameraID = CREATE_CAM_WITH_PARAMS("DEFAULT_SCRIPTED_CAMERA", cr.vPosition[1], cr.vRotation[1], fov, TRUE)
IF NOT DOES_CAM_EXIST(cameraID)
EXIT
ENDIF
cr.iActivationTime = GET_GAME_TIMER()
SET_CAM_ACTIVE(cameraID, TRUE)
RENDER_SCRIPT_CAMS(TRUE, FALSE)
SET_CAM_PARAMS(cameraID, cr.vPosition[0], cr.vRotation[0], cr.fFov[0], cr.iInterpolateTime)
IF IS_ENTITY_OK(cr.targetID)
POINT_CAM_AT_ENTITY(cameraID, cr.targetID, <<0, 0, 0>>)
ENDIF
ENDPROC
/// PURPOSE:
/// Check if camera has finished interpolating
/// PARAMS:
/// cr - camera struct
/// RETURNS:
///
FUNC BOOL HAS_CAMERA_STRUCT_FINISHED_INTERPOLATING(CAMERA_STRUCT &cr, FLOAT fCheckRatio = CAMERA_NOSWITCHRATIO)
BOOL bUseSwitchRatio = (fCheckRatio <> CAMERA_NOSWITCHRATIO) AND (cr.fSwitchRatio <> CAMERA_NOSWITCHRATIO)
IF NOT (cr.bSetup = TRUE)
RETURN FALSE
ENDIF
IF (bUseSwitchRatio) AND (fCheckRatio >= cr.fSwitchRatio)
CPRINTLN(DEBUG_AMBIENT, "SWITCHING CAMERA GONE PAST SWITCH RATIO")
RETURN TRUE
ENDIF
IF (GET_GAME_TIMER() > (cr.iActivationTime + cr.iInterpolateTime))
CPRINTLN(DEBUG_AMBIENT, "SWITCHING CAMERA - INTERPOLATION HAS FINISHED - SWITCH RATIO STATUS:", (fCheckRatio >= cr.fSwitchRatio))
RETURN (fCheckRatio >= cr.fSwitchRatio)
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Gets ratio of camera interpolate -
/// PARAMS:
/// cr - camera struct
/// RETURNS:
/// 0 is not start, 1 is done
FUNC FLOAT GET_CAMERA_STRUCT_INTERPOLATE_RATIO(CAMERA_STRUCT &cr)
IF (cr.iInterpolateTime <= 0)
RETURN 1.0
ENDIF
IF (GET_GAME_TIMER() > (cr.iActivationTime + cr.iInterpolateTime))
RETURN 1.0
ENDIF
IF (GET_GAME_TIMER() <= cr.iActivationTime)
RETURN 0.0
ENDIF
RETURN TO_FLOAT(GET_GAME_TIMER() - cr.iActivationTime) / TO_FLOAT(cr.iInterpolateTime)
ENDFUNC
FUNC BOOL IS_POINT_IN_CAMERA_STRUCT_CONE(CAMERA_STRUCT &cr, VECTOR pos)
VECTOR fwd = <<-SIN(cr.vRotation[0].z) * COS(cr.vRotation[0].x), COS(cr.vRotation[0].z) * COS(cr.vRotation[0].x), SIN(cr.vRotation[0].x)>>
VECTOR vNormalisedVec = NORMALISE_VECTOR(pos - cr.vPosition[0])
FLOAT fViewAngle = DOT_PRODUCT(fwd, vNormalisedVec)
IF fViewAngle <= COS(cr.fFov[0] / 2.0)
RETURN FALSE
ENDIF
RETURN TRUE
ENDFUNC
//----------------------
// FUNCTIONS
//-----------------------
PROC SETUP_BASIC_ENTITY_TARGET_CAMERA(BASIC_CAMERA &cr, ENTITY_INDEX srcent, ENTITY_INDEX tgtent = NULL, BOOL bFPS = FALSE)
cr.bSetup = TRUE
cr.sourceID = srcent
cr.targetID = tgtent
cr.bFPSMode = bFPS
ENDPROC
PROC SETUP_BASIC_TARGET_CAMERA(BASIC_CAMERA &cr, VECTOR pos, VECTOR tgt, ENTITY_INDEX tgtent = NULL)
cr.bSetup = TRUE
cr.vPosition = pos
cr.vLookAt = tgt
cr.targetID = tgtent // if this is set - look at is ignored
ENDPROC
PROC SETUP_BASIC_FPS_CAMERA(BASIC_CAMERA &cr, BOOL b360Look = FALSE)
cr.bFPSMode = TRUE
cr.bSetup = TRUE
cr.targetID = PLAYER_PED_ID()
cr.fLookPitch = 0.0
cr.fLookYaw = 0.0
IF (b360Look)
cr.bWrapLookYaw = TRUE
ENDIF
ENDPROC
PROC DISABLE_BASIC_CAMERA(BASIC_CAMERA &cr)
IF DOES_CAM_EXIST(cr.cameraID)
RENDER_SCRIPT_CAMS(FALSE, FALSE)
SET_CAM_ACTIVE(cr.cameraID, FALSE)
ENDIF
ENDPROC
PROC DESTROY_BASIC_CAMERA(BASIC_CAMERA &cr)
IF DOES_CAM_EXIST(cr.cameraID)
DISABLE_BASIC_CAMERA(cr)
DESTROY_CAM(cr.cameraID)
ENDIF
cr.cameraID = NULL
ENDPROC
FUNC BOOL ENABLE_BASIC_CAMERA(BASIC_CAMERA &cr, BOOL interp = FALSE, INT time = DEFAULT_INTERP_TO_FROM_GAME)
IF NOT (cr.bSetup = TRUE)
RETURN FALSE
ENDIF
cr.fFov = 50.0
IF NOT DOES_CAM_EXIST(cr.cameraID)
cr.cameraID = CREATE_CAM_WITH_PARAMS("DEFAULT_SCRIPTED_CAMERA", cr.vPosition, cr.vLookAt, 50.000, TRUE)
ENDIF
IF IS_ENTITY_OK(cr.sourceID)
ATTACH_CAM_TO_ENTITY(cr.cameraID, cr.sourceID, <<0, 0, 0>>)
ENDIF
IF (cr.bFPSMode = TRUE)
IF IS_ENTITY_OK(PLAYER_PED_ID()) AND NOT IS_ENTITY_OK(cr.sourceID)
ATTACH_CAM_TO_PED_BONE(cr.cameraID, PLAYER_PED_ID(), BONETAG_HEAD, <<0, 0.2, 0>>)
ENDIF
cr.fLookPitch = 0.0
cr.fLookYaw = 0.0
ELIF IS_ENTITY_OK(cr.targetID)
POINT_CAM_AT_ENTITY(cr.cameraID, cr.targetID, <<0, 0, 0>>)
ENDIF
IF DOES_CAM_EXIST(cr.cameraID)
SET_CAM_ACTIVE(cr.cameraID, TRUE)
RENDER_SCRIPT_CAMS(TRUE, interp, time)
ENDIF
RETURN TRUE
ENDFUNC
PROC UPDATE_BASIC_CAMERA(BASIC_CAMERA &cr)
IF NOT (cr.bSetup = TRUE)
EXIT
ENDIF
FLOAT pitch, yaw
FLOAT cpi
ALLOW_ALTERNATIVE_SCRIPT_CONTROLS_LAYOUT(FRONTEND_CONTROL)
IF (cr.bFPSMode = TRUE)
IF ABSF(GET_CONTROL_NORMAL(FRONTEND_CONTROL, INPUT_SCRIPT_RIGHT_AXIS_X)) > 0.1
cr.fLookYaw -= (GET_CONTROL_NORMAL(FRONTEND_CONTROL, INPUT_SCRIPT_RIGHT_AXIS_X) * FPSCAM_LOOKSPEED * TIMESTEP())
IF (cr.bWrapLookYaw)
IF (cr.fLookYaw < -180.0)
cr.fLookYaw += 360.0
ENDIF
IF (cr.fLookYaw > 180.0)
cr.fLookYaw -= 360.0
ENDIF
ELSE
cr.fLookYaw = CLAMP(cr.fLookYaw, -FPSCAM_LIMITYAW, FPSCAM_LIMITYAW)
ENDIF
//CPRINTLN(DEBUG_AMBIENT, "YAW:", cr.fLookYaw)
ENDIF
IF ABSF(GET_CONTROL_NORMAL(FRONTEND_CONTROL, INPUT_SCRIPT_RIGHT_AXIS_Y)) > 0.1
cpi = (GET_CONTROL_NORMAL(FRONTEND_CONTROL, INPUT_SCRIPT_RIGHT_AXIS_Y) * FPSCAM_LOOKSPEED * TIMESTEP())
IF IS_LOOK_INVERTED()
cpi *= -1
ENDIF
cr.fLookPitch -= cpi
IF (cr.bWrapLookPitch)
IF (cr.fLookPitch < -180.0)
cr.fLookPitch += 360.0
ENDIF
IF (cr.fLookPitch > 180.0)
cr.fLookPitch -= 360.0
ENDIF
ELSE
cr.fLookPitch = CLAMP(cr.fLookPitch, -FPSCAM_LIMITPITCH, FPSCAM_LIMITPITCH)
ENDIF
ENDIF
IF IS_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, INPUT_SCRIPT_RS)
cr.fLookPitch = 0.0
cr.fLookYaw = 0.0
ENDIF
// zoom
IF ABSF(GET_CONTROL_NORMAL(FRONTEND_CONTROL, INPUT_SCRIPT_LEFT_AXIS_Y)) > 0.1
cpi = (GET_CONTROL_NORMAL(FRONTEND_CONTROL, INPUT_SCRIPT_LEFT_AXIS_Y) * (FPSCAM_LOOKSPEED / 2.0) * TIMESTEP())
cr.fFov += cpi
cr.fFov = CLAMP(cr.fFov, FPSCAM_MINZOOM, FPSCAM_MAXZOOM)
ENDIF
IF DOES_CAM_EXIST(cr.cameraID)
SET_CAM_FOV(cr.cameraID, cr.fFov)
IF NOT IS_ENTITY_OK(cr.sourceID) AND IS_ENTITY_OK(PLAYER_PED_ID())
SET_CAM_ROT(cr.cameraID, GET_ENTITY_ROTATION(PLAYER_PED_ID()) + <<cr.fLookPitch, 0, cr.fLookYaw>>)
ELIF IS_ENTITY_OK(cr.sourceID) AND IS_ENTITY_OK(cr.targetID)
GET_PITCH_AND_HEADING_FROM_COORDS(GET_ENTITY_COORDS(cr.sourceID), GET_ENTITY_COORDS(cr.targetID), pitch, yaw)
SET_CAM_ROT(cr.cameraID, <<pitch, 0, yaw>> + <<cr.fLookPitch, 0, cr.fLookYaw>>)
ENDIF
ENDIF
ENDIF
ENDPROC