// ***************************************************************************************** // ***************************************************************************************** // ***************************************************************************************** // // SCRIPT NAME : SPTT_Camera.sch // AUTHOR : Nicholas Zippmann // DESCRIPTION : Single Player Races - Camera procs/functions file // // ***************************************************************************************** // ***************************************************************************************** // ***************************************************************************************** USING "SPTT_Head.sch" USING "SPTT_Helpers.sch" // ----------------------------------- // FLY MODE PROCS/FUNCTIONS // ----------------------------------- PROC SPTT_Camera_FlyMode_Interp(SPTT_CAMERA_STRUCT& Camera, VECTOR vFocusPos, BOOL bFromGameCam) //DEBUG_MESSAGE("SPTT_Camera_FlyMode_Interp") // Local variables. INT iInterpTime FLOAT fDist, fScale VECTOR vStartPos, vStartRot, vFinishPos // Set camera start position/rotation. IF NOT bFromGameCam vStartPos = GET_CAM_COORD(Camera.Cur) vStartRot = GET_CAM_ROT(Camera.Cur) ELSE vStartPos = GET_GAMEPLAY_CAM_COORD() vStartRot = GET_GAMEPLAY_CAM_ROT() ENDIF // Calculate camera finish position (apply zoom). vFinishPos = vStartPos - vFocusPos vFinishPos = NORMALISE_VECTOR(vFinishPos) IF (Camera.eFocus = SPTT_CAMERA_FOCUS_GATES) fScale = Camera.fZoom * SPTT_CAM_GATE_FOCUS_DIST ELIF (Camera.eFocus = SPTT_CAMERA_FOCUS_RACERS) fScale = Camera.fZoom * SPTT_CAM_RACER_FOCUS_DIST ENDIF vFinishPos = vFinishPos * fScale vFinishPos = vFocusPos + vFinishPos // Set new camera positions/rotations. SET_CAM_COORD(Camera.Lst, vStartPos) SET_CAM_ROT(Camera.Lst, vStartRot) SET_CAM_COORD(Camera.Cur, vFinishPos) POINT_CAM_AT_COORD(Camera.Cur, vFocusPos) // Calculate camera interp speed (clamp to min/max). fDist = VDIST(vStartPos, vFinishPos) iInterpTime = FLOOR((fDist / SPTT_CAM_INTERP_SPEED) * 1000.0) IF (iInterpTime < SPTT_CAM_INTERP_TIME_MIN) iInterpTime = SPTT_CAM_INTERP_TIME_MIN ELIF (iInterpTime > SPTT_CAM_INTERP_TIME_MAX) iInterpTime = SPTT_CAM_INTERP_TIME_MAX ENDIF // Have cameras interp to focus on position. SET_CAM_ACTIVE_WITH_INTERP(Camera.Cur, Camera.Lst, iInterpTime) RENDER_SCRIPT_CAMS(TRUE, FALSE) // Teleport player/vehicle to focus position, if needed. IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID()) IF IS_ENTITY_DEAD(SPTT_Master.PlayerVeh) SET_ENTITY_COORDS(PLAYER_PED_ID(), vFocusPos, FALSE) SET_ENTITY_ROTATION(PLAYER_PED_ID(), <<0.0,0.0,0.0>>) ELSE SET_ENTITY_COORDS(SPTT_Master.PlayerVeh, vFocusPos, FALSE) SET_ENTITY_ROTATION(SPTT_Master.PlayerVeh, <<0.0,0.0,0.0>>) ENDIF ENDIF /* Debug info. DEBUG_MESSAGE("SPTT_Camera_FlyMode_Interp START") PRINTSTRING("FOCUS POS: ") PRINTVECTOR(vFocusPos) PRINTNL() PRINTSTRING("START POS: ") PRINTVECTOR(vStartPos) PRINTNL() PRINTSTRING("START ROT: ") PRINTVECTOR(vStartRot) PRINTNL() PRINTSTRING("FINISH POS: ") PRINTVECTOR(vFinishPos) PRINTNL() PRINTSTRING("DIST TO FINISH: ") PRINTFLOAT(fDist) PRINTNL() PRINTSTRING("INTERP TIME (MS): ") PRINTINT(iInterpTime) PRINTNL() DEBUG_MESSAGE("SPTT_Camera_FlyMode_Interp FINISH") */ ENDPROC PROC SPTT_Camera_FlyMode_Update(SPTT_CAMERA_STRUCT& Camera, SPTT_INPUT_STRUCT& Input, VECTOR vFocusPos) //DEBUG_MESSAGE("SPTT_Camera_FlyMode_Update") // If widget cameras don't exist, exit. IF NOT DOES_CAM_EXIST(Camera.Lst) OR NOT DOES_CAM_EXIST(Camera.Cur) EXIT ENDIF // If camera is still interpolating, exit. IF IS_CAM_INTERPOLATING(Camera.Cur) EXIT ENDIF // Local variables. FLOAT fYaw, fPitch BOOL bSticksMoved = FALSE // Get position of analog sticks for camera movement. GET_CONTROL_VALUE_OF_ANALOGUE_STICKS(Input.iLS_X, Input.iLS_Y, Input.iRS_X, Input.iRS_Y) // Update camera zoom using L-Stick y-value. IF (Input.iLS_Y < -SPTT_INPUT_STICK_DZ_Y) IF (Input.iLS_Y >= -SPTT_INPUT_STICK_LIMIT) Camera.fZoom -= SPTT_CAM_ZOOM_INC bSticksMoved = TRUE ENDIF ELIF (Input.iLS_Y > SPTT_INPUT_STICK_DZ_Y) IF (Input.iLS_Y <= SPTT_INPUT_STICK_LIMIT) Camera.fZoom += SPTT_CAM_ZOOM_INC bSticksMoved = TRUE ENDIF ENDIF // Clamp camera zoom to min/max, if needed. IF bSticksMoved IF (Camera.fZoom < SPTT_CAM_ZOOM_LIMIT_MIN) Camera.fZoom = SPTT_CAM_ZOOM_LIMIT_MIN ELIF (Camera.fZoom > SPTT_CAM_ZOOM_LIMIT_MAX) Camera.fZoom = SPTT_CAM_ZOOM_LIMIT_MAX ENDIF ENDIF // Set camera yaw change using R-Stick x-value. IF (Input.iRS_X < -SPTT_INPUT_STICK_DZ_X) IF (Input.iRS_X >= -SPTT_INPUT_STICK_LIMIT) fYaw = -SPTT_CAM_ROTATE_INC bSticksMoved = TRUE ENDIF ELIF (Input.iRS_X > SPTT_INPUT_STICK_DZ_X) IF (Input.iRS_X <= SPTT_INPUT_STICK_LIMIT) fYaw = SPTT_CAM_ROTATE_INC bSticksMoved = TRUE ENDIF ENDIF // Set camera pitch change using R-Stick y-value. IF (Input.iRS_Y < -SPTT_INPUT_STICK_DZ_Y) IF (Input.iRS_Y >= -SPTT_INPUT_STICK_LIMIT) fPitch = -SPTT_CAM_ROTATE_INC bSticksMoved = TRUE ENDIF ELIF (Input.iRS_Y > SPTT_INPUT_STICK_DZ_Y) IF (Input.iRS_Y <= SPTT_INPUT_STICK_LIMIT) fPitch = SPTT_CAM_ROTATE_INC bSticksMoved = TRUE ENDIF ENDIF // If sticks haven't moved, exit. IF NOT bSticksMoved EXIT ENDIF // Local variables. FLOAT fScale VECTOR vNewPos, vNewRot, vForward // Make new camera rotation using pitch/yaw. vNewRot = GET_CAM_ROT(Camera.Cur) vNewRot.x += fPitch vNewRot.z += fYaw // Clamp x-axis rotation to limit, if needed. IF (vNewRot.x < -SPTT_CAM_ROTATE_LIMIT) vNewRot.x = -SPTT_CAM_ROTATE_LIMIT ELIF (vNewRot.x > SPTT_CAM_ROTATE_LIMIT) vNewRot.x = SPTT_CAM_ROTATE_LIMIT ENDIF // Calculate new camera position by rotating dummy // camera to find new forward vector (apply zoom). SET_ENTITY_ROTATION(Camera.DummyCam, vNewRot) vForward = GET_ENTITY_FORWARD_VECTOR(Camera.DummyCam) IF (Camera.eFocus = SPTT_CAMERA_FOCUS_GATES) fScale = Camera.fZoom * SPTT_CAM_GATE_FOCUS_DIST ELIF (Camera.eFocus = SPTT_CAMERA_FOCUS_RACERS) fScale = Camera.fZoom * SPTT_CAM_RACER_FOCUS_DIST ENDIF vNewPos = vForward * fScale vNewPos = vFocusPos - vNewPos SET_CAM_COORD(Camera.Cur, vNewPos) /* Debug info. DEBUG_MESSAGE("SPTT_Camera_FlyMode_Update START") PRINTSTRING("L-STICK X: ") PRINTINT(Input.iLS_X) PRINTSTRING(", Y: ") PRINTINT(Input.iLS_Y) PRINTSTRING(", ZOOM: ") PRINTFLOAT(Camera.fZoom) PRINTNL() PRINTSTRING("R-STICK X: ") PRINTINT(Input.iRS_X) PRINTSTRING(", Y: ") PRINTINT(Input.iRS_Y) PRINTSTRING(", YAW: ") PRINTFLOAT(fYaw) PRINTSTRING(", PITCH: ") PRINTFLOAT(fPitch) PRINTNL() PRINTSTRING("CAM POS: ") PRINTVECTOR(vNewPos) PRINTNL() PRINTSTRING("CAM ROT: ") PRINTVECTOR(vNewRot) PRINTNL() PRINTSTRING("CAM FWD: ") PRINTVECTOR(vForward) PRINTNL() DEBUG_MESSAGE("SPTT_Camera_FlyMode_Update FINISH") */ ENDPROC // ----------------------------------- // MAIN PROCS/FUNCTIONS // ----------------------------------- PROC SPTT_Camera_Mode_Set(SPTT_CAMERA_STRUCT& Camera, SPTT_CAMERA_MODE_ENUM eMode, VECTOR vFocusPos) //DEBUG_MESSAGE("SPTT_Camera_Mode_Set") // Setup new camera mode accordingly. SWITCH (eMode) // Gameplay Mode. CASE SPTT_CAMERA_MODE_GAME // Activate/Show player/vehicle, if needed. IF NOT IS_ENTITY_DEAD(SPTT_Master.PlayerVeh) FREEZE_ENTITY_POSITION(SPTT_Master.PlayerVeh, FALSE) SET_ENTITY_COLLISION(SPTT_Master.PlayerVeh, TRUE) SET_ENTITY_VISIBLE(SPTT_Master.PlayerVeh, TRUE) ENDIF IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID()) IF NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) SET_ENTITY_COLLISION(PLAYER_PED_ID(), TRUE) ENDIF FREEZE_ENTITY_POSITION(PLAYER_PED_ID(), FALSE) SET_PED_GRAVITY(PLAYER_PED_ID(), TRUE) SET_ENTITY_VISIBLE(PLAYER_PED_ID(), TRUE) ENDIF // Reset gameplay camera behind player. SET_GAMEPLAY_CAM_RELATIVE_HEADING(0.0) SET_GAMEPLAY_CAM_RELATIVE_PITCH(-10.0) // Give back player control. SET_PLAYER_CONTROL(PLAYER_ID(), TRUE) // Set debug camera as inactive. SET_DEBUG_CAM_ACTIVE(FALSE, FALSE) // Switch back to gameplay camera. RENDER_SCRIPT_CAMS(FALSE, FALSE) BREAK // Free Mode. CASE SPTT_CAMERA_MODE_FREE // Set debug camera as active. SET_DEBUG_CAM_ACTIVE(TRUE, TRUE) // Take away player control. SET_PLAYER_CONTROL(PLAYER_ID(), FALSE) IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID()) // Freeze/Hide player/vehicle, if needed. SET_ENTITY_VISIBLE(PLAYER_PED_ID(), FALSE) SET_PED_GRAVITY(PLAYER_PED_ID(), FALSE) FREEZE_ENTITY_POSITION(PLAYER_PED_ID(), TRUE) IF NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) SET_ENTITY_COLLISION(PLAYER_PED_ID(), FALSE) ENDIF ENDIF IF NOT IS_ENTITY_DEAD(SPTT_Master.PlayerVeh) SET_ENTITY_VISIBLE(SPTT_Master.PlayerVeh, FALSE) SET_ENTITY_COLLISION(SPTT_Master.PlayerVeh, FALSE) FREEZE_ENTITY_POSITION(SPTT_Master.PlayerVeh, TRUE) ENDIF // TODO: Figure out why how to set cam pos and how to use on first controller. BREAK // Fly-Through Mode. CASE SPTT_CAMERA_MODE_FLY // Set debug camera as inactive. SET_DEBUG_CAM_ACTIVE(FALSE, FALSE) // Take away player control. SET_PLAYER_CONTROL(PLAYER_ID(), FALSE ) IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID()) // Freeze/Hide player/vehicle, if needed. SET_ENTITY_VISIBLE(PLAYER_PED_ID(), FALSE) SET_PED_GRAVITY(PLAYER_PED_ID(), FALSE) FREEZE_ENTITY_POSITION(PLAYER_PED_ID(), TRUE) IF NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) SET_ENTITY_COLLISION(PLAYER_PED_ID(), FALSE) ENDIF ENDIF IF NOT IS_ENTITY_DEAD(SPTT_Master.PlayerVeh) SET_ENTITY_VISIBLE(SPTT_Master.PlayerVeh, FALSE) SET_ENTITY_COLLISION(SPTT_Master.PlayerVeh, FALSE) FREEZE_ENTITY_POSITION(SPTT_Master.PlayerVeh, TRUE) ENDIF // Start Fly-Through Mode interp (from gameplay camera if needed). IF (Camera.eMode = SPTT_CAMERA_MODE_GAME) SPTT_Camera_FlyMode_Interp(Camera, vFocusPos, TRUE) ELSE SPTT_Camera_FlyMode_Interp(Camera, vFocusPos, FALSE) ENDIF BREAK ENDSWITCH // Update camera mode to new camera mode. Camera.eMode = eMode ENDPROC PROC SPTT_Camera_Focus_Set(SPTT_CAMERA_STRUCT& Camera, SPTT_CAMERA_FOCUS_ENUM eFocus, VECTOR vFocusPos) //DEBUG_MESSAGE("SPTT_Camera_Focus_Set") // Update camera focus to new camera focus. Camera.eFocus = eFocus // Set zoom so it has no effect on camera. Camera.fZoom = 1.0 // Setup new camera focus accordingly. SWITCH (Camera.eMode) // Gameplay Mode. CASE SPTT_CAMERA_MODE_GAME // TODO: Decide if anything is needed here... BREAK // Free Mode. CASE SPTT_CAMERA_MODE_FREE // TODO: Decide if anything is needed here... BREAK // Fly-Through Mode. CASE SPTT_CAMERA_MODE_FLY // Start Fly-Through Mode interp. SPTT_Camera_FlyMode_Interp(Camera, vFocusPos, FALSE) BREAK ENDSWITCH ENDPROC PROC SPTT_Camera_Setup(SPTT_CAMERA_STRUCT& Camera) //DEBUG_MESSAGE("SPTT_Camera_Setup") // Request dummy model. REQUEST_MODEL(PROP_POOL_BALL_01) // Create current/last cameras. Camera.Cur = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA") IF NOT DOES_CAM_EXIST(Camera.Cur) SCRIPT_ASSERT("Failed to create current camera!") EXIT ENDIF Camera.Lst = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA") IF NOT DOES_CAM_EXIST(Camera.Lst) SCRIPT_ASSERT("Failed to create last camera!") EXIT ENDIF // Create dummy camera and set it as invisible. Camera.DummyCam = CREATE_OBJECT(PROP_POOL_BALL_01, SPTT_Master.vDefRcrPos, FALSE) IF NOT DOES_ENTITY_EXIST(Camera.DummyCam) SCRIPT_ASSERT("Failed to create dummy object!") EXIT ENDIF SET_ENTITY_VISIBLE(Camera.DummyCam, FALSE) SET_ENTITY_COLLISION(Camera.DummyCam, FALSE) // Set zoom so it has no effect on camera. Camera.fZoom = 1.0 // Set camera to Gameplay Mode. SPTT_Camera_Mode_Set(Camera, SPTT_CAMERA_MODE_GAME, <<0.0,0.0,0.0>>) // Set camera to Gates Focus. SPTT_Camera_Focus_Set(Camera, SPTT_CAMERA_FOCUS_GATES, <<0.0,0.0,0.0>>) ENDPROC PROC SPTT_Camera_GetRelPos_Side(SPTT_CAMERA_STRUCT& Camera, VECTOR& vRelPos, FLOAT fDist, BOOL bAbsolute) //DEBUG_MESSAGE("SPTT_Camera_GetRelPos_Side") IF bAbsolute vRelPos = GET_CAM_COORD(Camera.Cur) ENDIF VECTOR vSide, vTmp1, vTmp2, vTmp3 IF (Camera.eMode = SPTT_CAMERA_MODE_GAME) vTmp1 = GET_GAMEPLAY_CAM_ROT() ELSE vTmp1 = GET_CAM_ROT(Camera.Cur) ENDIF SET_ENTITY_ROTATION(Camera.DummyCam, vTmp1) GET_ENTITY_MATRIX(Camera.DummyCam, vTmp1, vSide, vTmp2, vTmp3) vSide = vSide * fDist vRelPos = vRelPos + vSide ENDPROC PROC SPTT_Camera_GetRelPos_Fwd(SPTT_CAMERA_STRUCT& Camera, VECTOR& vRelPos, FLOAT fDist, BOOL bAbsolute) //DEBUG_MESSAGE("SPTT_Camera_GetRelPos_Fwd") IF bAbsolute vRelPos = GET_CAM_COORD(Camera.Cur) ENDIF VECTOR vFwd, vTmp1, vTmp2, vTmp3 IF (Camera.eMode = SPTT_CAMERA_MODE_GAME) vTmp1 = GET_GAMEPLAY_CAM_ROT() ELSE vTmp1 = GET_CAM_ROT(Camera.Cur) ENDIF SET_ENTITY_ROTATION(Camera.DummyCam, vTmp1) GET_ENTITY_MATRIX(Camera.DummyCam, vFwd, vTmp1, vTmp2, vTmp3) vFwd = vFwd * fDist vRelPos = vRelPos + vFwd ENDPROC PROC SPTT_Camera_GetRelPos_Up(SPTT_CAMERA_STRUCT& Camera, VECTOR& vRelPos, FLOAT fDist, BOOL bAbsolute) //DEBUG_MESSAGE("SPTT_Camera_GetRelPos_Up") IF bAbsolute vRelPos = GET_CAM_COORD(Camera.Cur) ENDIF VECTOR vUp, vTmp1, vTmp2, vTmp3 IF (Camera.eMode = SPTT_CAMERA_MODE_GAME) vTmp1 = GET_GAMEPLAY_CAM_ROT() ELSE vTmp1 = GET_CAM_ROT(Camera.Cur) ENDIF SET_ENTITY_ROTATION(Camera.DummyCam, vTmp1) GET_ENTITY_MATRIX(Camera.DummyCam, vTmp1, vTmp2, vUp, vTmp3) vUp = vUp * fDist vRelPos = vRelPos + vUp ENDPROC FUNC VECTOR SPTT_Camera_GetPlacementPos(SPTT_CAMERA_STRUCT& Camera) //DEBUG_MESSAGE("SPTT_Camera_GetPlacementPos") // Get placement position in front of camera according to mode. VECTOR vPlacePos SWITCH (Camera.eMode) // Gameplay Mode (player/vehicle pos). CASE SPTT_CAMERA_MODE_GAME vPlacePos = GET_GAMEPLAY_CAM_COORD() IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID()) IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) VEHICLE_INDEX Veh Veh = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()) IF NOT IS_ENTITY_DEAD(Veh) vPlacePos = GET_ENTITY_COORDS(Veh) ENDIF ELSE vPlacePos = GET_ENTITY_COORDS(PLAYER_PED_ID()) ENDIF ENDIF BREAK // Free/Fly-Through Modes (camera relative fwd pos). CASE SPTT_CAMERA_MODE_FREE CASE SPTT_CAMERA_MODE_FLY IF (Camera.eFocus = SPTT_CAMERA_FOCUS_GATES) SPTT_Camera_GetRelPos_Fwd(Camera, vPlacePos, SPTT_CAM_GATE_FOCUS_DIST, TRUE) ELIF (Camera.eFocus = SPTT_CAMERA_FOCUS_RACERS) SPTT_Camera_GetRelPos_Fwd(Camera, vPlacePos, SPTT_CAM_RACER_FOCUS_DIST, TRUE) ENDIF BREAK ENDSWITCH // Return placement position. RETURN vPlacePos ENDFUNC FUNC FLOAT SPTT_Camera_GetHeading(SPTT_CAMERA_STRUCT& Camera) //DEBUG_MESSAGE("SPTT_Camera_GetHeading") VECTOR vCamRot IF (Camera.eMode = SPTT_CAMERA_MODE_GAME) vCamRot = GET_GAMEPLAY_CAM_ROT() ELSE vCamRot = GET_CAM_ROT(Camera.Cur) ENDIF RETURN vCamRot.z ENDFUNC PROC SPTT_Camera_Interp(SPTT_CAMERA_STRUCT& Camera, VECTOR vFocusPos, BOOL bFromGameCam) //DEBUG_MESSAGE("SPTT_Camera_Interp") // Interp camera according to mode. SWITCH (Camera.eMode) // Gameplay Mode. CASE SPTT_CAMERA_MODE_GAME // TODO: Is something needed here? BREAK // Free Mode. CASE SPTT_CAMERA_MODE_FREE // TODO: Implement Free Mode. BREAK // Fly-Through Mode. CASE SPTT_CAMERA_MODE_FLY SPTT_Camera_FlyMode_Interp(Camera, vFocusPos, bFromGameCam) BREAK ENDSWITCH ENDPROC PROC SPTT_Camera_Update(SPTT_CAMERA_STRUCT& Camera, SPTT_INPUT_STRUCT& Input, VECTOR vFocusPos) //DEBUG_MESSAGE("SPTT_Camera_Update") // Update camera according to mode. SWITCH (Camera.eMode) // Gameplay Mode. CASE SPTT_CAMERA_MODE_GAME // TODO: Is something needed here? BREAK // Free Mode. CASE SPTT_CAMERA_MODE_FREE // TODO: Implement Free Mode. BREAK // Fly-Through Mode. CASE SPTT_CAMERA_MODE_FLY SPTT_Camera_FlyMode_Update(Camera, Input, vFocusPos) BREAK ENDSWITCH ENDPROC PROC SPTT_Camera_Cleanup(SPTT_CAMERA_STRUCT& Camera) //DEBUG_MESSAGE("SPTT_Camera_Cleanup") // Set camera to Gameplay mode. SPTT_Camera_Mode_Set(Camera, SPTT_CAMERA_MODE_GAME, <<0.0,0.0,0.0>>) // Evict dummy model. SET_MODEL_AS_NO_LONGER_NEEDED(PROP_POOL_BALL_01) // Destroy current/last cameras, if needed. IF DOES_CAM_EXIST(Camera.Lst) DESTROY_CAM(Camera.Lst) ENDIF IF DOES_CAM_EXIST(Camera.Cur) DESTROY_CAM(Camera.Cur) ENDIF // Destroy dummy camera, if needed IF DOES_ENTITY_EXIST(Camera.DummyCam) DELETE_OBJECT(Camera.DummyCam) ENDIF ENDPROC // END OF FILE! DO NOT ADD ANYTHING BELOW THIS LINE!