// ***************************************************************************************** // ***************************************************************************************** // // 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()) + <>) 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, <> + <>) ENDIF ENDIF ENDIF ENDPROC