Files
2025-09-29 00:52:08 +02:00

366 lines
13 KiB
Scheme
Executable File

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Description: A bunch of methods common to many scripted weapon implementations //
// //
// Written by: Online Technical Team: Orlando C-H //
// Date: 12/09/2018 //
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
USING "globals.sch"
USING "script_blip.sch"
USING "net_hud_displays.sch"
USING "rc_helper_functions.sch"
USING "script_maths.sch"
USING "turret_cam_public_def.sch"
/// PURPOSE:
/// Returns the screen space distance of "entity" from the
/// screen centre.
FUNC FLOAT GET_ENT_DIST2_TO_SCREEN_CENTRE(ENTITY_INDEX entity)
VECTOR vPos = GET_ENTITY_COORDS(entity)
IF NOT GET_SCREEN_COORD_FROM_WORLD_COORD(vPos, vPos.x, vPos.y)
RETURN 1.0
ENDIF
vPos -= <<0.5,0.5,0>> //We want dist from centre of screen
vPos.z = 0
RETURN VMAG2(vPos)
ENDFUNC
/// PURPOSE:
/// Set whether zoom bar is visibale or not on an "ARENA_GUN_CAM_[X]" HUD.
PROC ARENA_HUD_SET_ZOOM_IS_VISIBLE(SCALEFORM_INDEX scaleformId, BOOL bZoomVisible)
BEGIN_SCALEFORM_MOVIE_METHOD(scaleformId, "SET_ZOOM_VISIBLE")
SCALEFORM_MOVIE_METHOD_ADD_PARAM_BOOL(bZoomVisible)
END_SCALEFORM_MOVIE_METHOD()
ENDPROC
/// PURPOSE:
/// Set weapon icons on an "ARENA_GUN_CAM_[X]" HUD.
PROC ARENA_HUD_SET_WEAPON_ICONS(SCALEFORM_INDEX scaleformId, ARENA_HUD_WEAPON_ICON eIconMg, ARENA_HUD_WEAPON_ICON eIconHm, ARENA_HUD_WEAPON_ICON eIconPm)
BEGIN_SCALEFORM_MOVIE_METHOD(scaleformId, "SET_WEAPON_VALUES")
SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(ENUM_TO_INT(eIconMg))
SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(ENUM_TO_INT(eIconHm))
SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(ENUM_TO_INT(eIconPm))
END_SCALEFORM_MOVIE_METHOD()
ENDPROC
/// PURPOSE:
/// Update a "turret_cam" scaleform hud.
PROC UPDATE_HUD_TURRET_CAM(SCALEFORM_INDEX scaleformId, FLOAT fCurAltitude, FLOAT fFov, FLOAT fMinFov, FLOAT fMaxFov, FLOAT fHeading)
fFov = (fFov - fMinFov) / (fMaxFov - fMinFov)
BEGIN_SCALEFORM_MOVIE_METHOD(scaleformId, "SET_ALT_FOV_HEADING")
SCALEFORM_MOVIE_METHOD_ADD_PARAM_FLOAT(fCurAltitude)
SCALEFORM_MOVIE_METHOD_ADD_PARAM_FLOAT(fFov)
SCALEFORM_MOVIE_METHOD_ADD_PARAM_FLOAT(fHeading)
END_SCALEFORM_MOVIE_METHOD()
ENDPROC
/// PURPOSE:
/// Convert Euler rotation to a direction vector.
///
FUNC VECTOR EULER_TO_DIRECTION_VECTOR(VECTOR vEuler)
VECTOR vResult
vResult.x = COS(vEuler.x)
vResult.y = COS(vEuler.z)
vResult.z = SIN(vEuler.x)
vResult.y *= vResult.x
vResult.x *= -SIN(vEuler.z)
RETURN vResult
ENDFUNC
/// PURPOSE:
/// This function returns an endpoint vector to pass into SHOOT_SINGLE_BULLET_BETWEEN_COORDS_IGNORE_ENTITY_NEW.
/// However it is simple and only uses rotation of the camera to determine the endpoint irrespective of camera distance
/// from vStartCoord (If the camera is far away from vStartCoord then the projectile will not end up where you're pointing).
/// PARAMS:
/// vStartCoord - Where the projectile is to be fired from.
/// fEndPointDistance - How far away from vStartCoord to set the endpoint.
/// RETURNS:
///
FUNC VECTOR GET_TURRET_PROJECTILE_ENDPOINT(VECTOR vStartCoord, FLOAT fEndPointDistance = 1.0)
VECTOR vRot = GET_FINAL_RENDERED_CAM_ROT()
VECTOR vDir = EULER_TO_DIRECTION_VECTOR(vRot)
RETURN vStartCoord + (fEndPointDistance * vDir)
ENDFUNC
/// PURPOSE:
/// Creates and updates a vehicle weapon blip.
/// Caller is responsible for cleaning up the blips.
PROC MAINTAIN_TURRET_WEAPON_BLIP(BLIP_INDEX& ref_blipFront, BLIP_INDEX& ref_blipBack)
HIDE_PLAYER_ARROW_THIS_FRAME()
VECTOR vCamCoord = GET_FINAL_RENDERED_CAM_COORD()
IF IS_PAUSE_MENU_ACTIVE()
OR IS_PAUSE_MENU_ACTIVE_EX()
OR IS_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, INPUT_FRONTEND_PAUSE)
OR IS_CONTROL_PRESSED(FRONTEND_CONTROL, INPUT_FRONTEND_PAUSE)
OR IS_CONTROL_JUST_RELEASED(FRONTEND_CONTROL, INPUT_FRONTEND_PAUSE)
SET_FAKE_PAUSEMAP_PLAYER_POSITION_THIS_FRAME(vCamCoord.x,vCamCoord.y)
SET_FAKE_GPS_PLAYER_POSITION_THIS_FRAME(vCamCoord.x, vCamCoord.y)
IF IS_PAUSE_MENU_ACTIVE()
OR IS_PAUSE_MENU_ACTIVE_EX()
IF DOES_BLIP_EXIST(GET_MAIN_PLAYER_BLIP_ID())
SET_BLIP_ALPHA(GET_MAIN_PLAYER_BLIP_ID(), 255)
ENDIF
ENDIF
ELSE
IF DOES_BLIP_EXIST(GET_MAIN_PLAYER_BLIP_ID())
SET_BLIP_ALPHA(GET_MAIN_PLAYER_BLIP_ID(), 0)
ENDIF
ENDIF
LOCK_MINIMAP_POSITION(vCamCoord.x,vCamCoord.y)
CAMERA_INDEX cam = GET_RENDERING_CAM()
IF DOES_CAM_EXIST(cam)
SET_CAM_CONTROLS_MINI_MAP_HEADING(cam, TRUE)
ENDIF
VECTOR vRot
vRot = GET_FINAL_RENDERED_CAM_ROT(EULER_XYZ)
vRot = EULER_TO_DIRECTION_VECTOR(vRot)
IF NOT DOES_BLIP_EXIST(ref_blipFront)
ref_blipBack = CREATE_BLIP_FOR_COORD(vCamCoord)
SET_BLIP_SPRITE(ref_blipBack, RADAR_TRACE_CENTRE_STROKE)
SHOW_HEIGHT_ON_BLIP(ref_blipBack, FALSE)
SET_BLIP_DISPLAY(ref_blipBack, DISPLAY_BOTH)
SET_BLIP_COLOUR(ref_blipBack,GET_BLIP_COLOUR_FROM_HUD_COLOUR(HUD_COLOUR_BLACK))
SET_BLIP_SHOW_CONE(ref_blipBack, TRUE)
SET_BLIP_SCALE(ref_blipBack, 0.54)
SET_BLIP_PRIORITY(ref_blipBack, INT_TO_ENUM(BLIP_PRIORITY, (ENUM_TO_INT(BLIPPRIORITY_OVER_CENTRE_BLIP)+1)))
ref_blipFront = CREATE_BLIP_FOR_COORD(vCamCoord)
SET_BLIP_SPRITE(ref_blipFront, RADAR_TRACE_CENTRE_STROKE)
SHOW_HEIGHT_ON_BLIP(ref_blipFront, FALSE)
SET_BLIP_DISPLAY(ref_blipFront, DISPLAY_BOTH)
SET_BLIP_COLOUR(ref_blipFront,GET_BLIP_COLOUR_FROM_HUD_COLOUR(HUD_COLOUR_GREEN))
SET_BLIP_SHOW_CONE(ref_blipFront, TRUE)
SET_BLIP_SCALE(ref_blipFront, 0.44)
SET_BLIP_PRIORITY(ref_blipFront, INT_TO_ENUM(BLIP_PRIORITY, (ENUM_TO_INT(BLIPPRIORITY_OVER_CENTRE_BLIP)+1)))
SET_BLIP_HIDDEN_ON_LEGEND(ref_blipFront, TRUE)
SET_BLIP_ROTATION(ref_blipFront, ROUND(GET_HEADING_FROM_VECTOR_2D(vRot.x, vRot.y)))
SET_BLIP_HIDDEN_ON_LEGEND(ref_blipBack, TRUE)
SET_BLIP_ROTATION(ref_blipBack, ROUND(GET_HEADING_FROM_VECTOR_2D(vRot.x, vRot.y)))
ELSE
SET_BLIP_COORDS(ref_blipFront, vCamCoord)
SET_BLIP_ROTATION(ref_blipFront, ROUND(GET_HEADING_FROM_VECTOR_2D(vRot.x, vRot.y)))
SET_BLIP_DISPLAY(ref_blipFront, DISPLAY_RADAR_ONLY)
SET_BLIP_COORDS(ref_blipBack, vCamCoord)
SET_BLIP_ROTATION(ref_blipBack, ROUND(GET_HEADING_FROM_VECTOR_2D(vRot.x, vRot.y)))
SET_BLIP_DISPLAY(ref_blipBack, DISPLAY_RADAR_ONLY)
ENDIF
ENDPROC
PROC REMOVE_BLIP_IF_EXIST(BLIP_INDEX blip)
IF DOES_BLIP_EXIST(blip)
REMOVE_BLIP(blip)
ENDIF
ENDPROC
STRUCT CAM_OUTPUT
FLOAT fFovChange
VECTOR vRotChange
ENDSTRUCT
/// PURPOSE:
/// Use default camera controls to calculate ref_vCamRotation.
/// The CAM_OUTPUT struct describes (current - prev) states.
/// Unlike rotation, fov changes are applied in this function.
///
/// If limits.fMinHeading > limits.fMaxHeading the cam will loop 360* instead of clamping.
FUNC CAM_OUTPUT UPDATE_TURRET_TRANSFORM(CAMERA_INDEX cam, VECTOR& ref_vCamRotation, CAM_CONTROL_LIMITS limits, FLOAT fRotSpeed = 0.6, FLOAT fZoomSpeed = 20.0)
FLOAT fCurrentFov = GET_CAM_FOV(cam)
// Set up outputs
//
CAM_OUTPUT output
output.fFovChange = -fCurrentFov
output.vRotChange = -ref_vCamRotation
// Cam controls
//
FLOAT fZoom = GET_DISABLED_CONTROL_NORMAL(PLAYER_CONTROL, INPUT_SNIPER_ZOOM)
VECTOR vRStick = -<<GET_DISABLED_CONTROL_UNBOUND_NORMAL(PLAYER_CONTROL, INPUT_SCALED_LOOK_UD), 0, GET_DISABLED_CONTROL_UNBOUND_NORMAL(PLAYER_CONTROL, INPUT_SCALED_LOOK_LR)>>
// No need to dead-zone on mouse
IF IS_USING_KEYBOARD_AND_MOUSE(FRONTEND_CONTROL)
fRotSpeed *= 8
ELSE
CONST_FLOAT cfDEADZONE_MAG 0.06
// Deadzone zoom
IF ABSF(fZoom) < cfDEADZONE_MAG
fZoom = 0
ENDIF
// Deadzone camera movement
IF VMAG(vRStick) < cfDEADZONE_MAG
vRStick = <<0,0,0>>
ENDIF
ENDIF
FLOAT fFrameTime = GET_FRAME_TIME()
FLOAT fFov = CLAMP(fCurrentFov + (fZoom * fZoomSpeed * fFrameTime), limits.fMinFov, limits.fMaxFov)
SET_CAM_FOV(cam, fFov)
SET_CAM_NEAR_CLIP(cam, 0.01)
FLOAT fBlurOverride = (fFov - 5.0) /42.0
SET_GAMEPLAY_CAM_MOTION_BLUR_SCALING_THIS_UPDATE(1.0)
SET_DISTANCE_BLUR_STRENGTH_OVERRIDE(fBlurOverride)
VECTOR vMin, vMax
vMin.x = limits.fMinPitch
vMin.y = 0 // no roll
vMin.z = limits.fMinHeading
vMax.x = limits.fMaxPitch
vMax.y = 0 // no roll
vMax.z = limits.fMaxHeading
FLOAT fCamRotSpeed = fFrameTime * fFov * fRotSpeed * (1 + (fFov - limits.fMinFov) / (limits.fMaxFov - limits.fMinFov))
VECTOR vPan = vRStick
vPan.z *= fCamRotSpeed
vPan.x *= fCamRotSpeed
ref_vCamRotation += vPan
BOOL bLoopHeading = vMin.z > vMax.z
IF bLoopHeading
ref_vCamRotation.x = CLAMP(ref_vCamRotation.x, vMin.x, vMax.x)
ref_vCamRotation.y = CLAMP(ref_vCamRotation.y, vMin.y, vMax.y)
ref_vCamRotation.z = NORMALIZE_ANGLE(ref_vCamRotation.z)
ELSE
ref_vCamRotation = CLAMP_VECTOR_COMPONENTS(ref_vCamRotation, vMin, vMax)
ENDIF
output.fFovChange += fFov
output.vRotChange += ref_vCamRotation
RETURN output
ENDFUNC
PROC APPLY_TURRET_TRANSFORM_UPDATE_STATIC(CAMERA_INDEX cam, VECTOR vPos, VECTOR vRot)
SET_CAM_COORD(cam, vPos)
SET_CAM_ROT(cam, vRot)
ENDPROC
PROC APPLY_TURRET_TRANSFORM_UPDATE_VEH(CAMERA_INDEX cam, VECTOR vOffsetPos, VECTOR vOffsetRot, VEHICLE_INDEX vehParent, INT iBoneIndex)
ATTACH_CAM_TO_VEHICLE_BONE(cam, vehParent, iBoneIndex, TRUE, vOffsetRot, vOffsetPos, TRUE)
ENDPROC
PROC APPLY_TURRET_TRANSFORM_UPDATE_ENT_HEADING(CAMERA_INDEX cam, VECTOR vOffsetPos, VECTOR vOffsetRot, ENTITY_INDEX entity)
ATTACH_CAM_TO_ENTITY(cam, entity, vOffsetPos)
SET_CAM_ROT(cam, vOffsetRot + GET_ENTITY_ROTATION(entity))
ENDPROC
PROC INIT_CAM_AUDIO_POLICE_CHOPPER(INT& ref_iPanSoundId, INT& ref_iZoomSoundId, INT& ref_iBackgroundSoundId)
HINT_SCRIPT_AUDIO_BANK("SCRIPT\\POLICE_CHOPPER_CAM")
ref_iPanSoundId = GET_SOUND_ID()
ref_iZoomSoundId = GET_SOUND_ID()
ref_iBackgroundSoundId = GET_SOUND_ID()
ENDPROC
/// PURPOSE:
/// Plays HUD sounds. Assumes that the "Zoom" sound has "Ctrl" and "Dir" variables,
/// and the "Pan" sound has a "Ctrl" variable.
/// Any soundId that is -1 will be ignored.
/// PARAMS:
/// sBank - Ambient bank e.g. SCRIPT\\POLICE_CHOPPER_CAM
/// sSoundSet - Soundset for these sounds
/// iDamageTaken - damage suffered this frame
/// bHeadshot - suffered a headshot this frame?
PROC MAINTAIN_CAM_HUD_AUDIO(STRING sBank, STRING sSoundSet,
INT iPanSoundId, STRING sPanSound,
INT iZoomSoundId, STRING sZoomSound,
INT iBackgroundSoundId, STRING sBackgroundSound,
INT iTakeDamageId, STRING sTakeDamageSound,
INT iLowHealthLoop, STRING sLowHealthLoopSound,
FLOAT fZoomChange, VECTOR vRotChange,
INT iDamageTaken, BOOL bSufferedHeadshot)
IF IS_STRING_NULL_OR_EMPTY(sBank)
OR REQUEST_SCRIPT_AUDIO_BANK(sBank)
IF fZoomChange <> 0
IF iZoomSoundId != -1
IF HAS_SOUND_FINISHED(iZoomSoundId)
PLAY_SOUND_FRONTEND(iZoomSoundId, sZoomSound, sSoundSet)
ENDIF
SET_VARIABLE_ON_SOUND(iZoomSoundId, "Ctrl", fZoomChange)
IF fZoomChange < 0
SET_VARIABLE_ON_SOUND(iZoomSoundId,"Dir",-1)
ELSE
SET_VARIABLE_ON_SOUND(iZoomSoundId,"Dir", 1)
ENDIF
ENDIF
ELSE
IF iZoomSoundId != -1
IF NOT HAS_SOUND_FINISHED(iZoomSoundId)
STOP_SOUND(iZoomSoundId)
ENDIF
ENDIF
ENDIF
FLOAT fLookMag = VMAG(vRotChange)
IF fLookMag > 0
IF iPanSoundId != -1
IF HAS_SOUND_FINISHED(iPanSoundId)
PLAY_SOUND_FRONTEND(iPanSoundId, sPanSound, sSoundSet)
ENDIF
SET_VARIABLE_ON_SOUND(iPanSoundId, "Ctrl", fLookMag)
ENDIF
ELSE
IF iPanSoundId != -1
IF NOT HAS_SOUND_FINISHED(iPanSoundId)
STOP_SOUND(iPanSoundId)
ENDIF
ENDIF
ENDIF
IF iBackgroundSoundId != -1
IF HAS_SOUND_FINISHED(iBackgroundSoundId)
PLAY_SOUND_FRONTEND(iBackgroundSoundId, sBackgroundSound, sSoundSet)
ENDIF
ENDIF
// Damage sounds...
PED_INDEX pedLocal = PLAYER_PED_ID()
ENTITY_INDEX playerEntity
IF IS_PED_IN_ANY_VEHICLE(pedLocal)
playerEntity = GET_VEHICLE_PED_IS_IN(pedLocal)
ELSE
playerEntity = pedLocal
ENDIF
IF iTakeDamageId != -1
BOOL bPlaySound = bSufferedHeadshot
IF NOT bPlaySound
FLOAT fMaxHealth = TO_FLOAT(GET_ENTITY_MAX_HEALTH(playerEntity))
bPlaySound = iDamageTaken / fMaxHealth > 0.10 // 10 % Damage in one frame?
ENDIF
IF bPlaySound
IF HAS_SOUND_FINISHED(iTakeDamageId)
PLAY_SOUND_FRONTEND(iTakeDamageId, sTakeDamageSound, sTakeDamageSound)
ENDIF
ENDIF
ENDIF
IF iLowHealthLoop != -1
// Check ped and vehicle...
IF GET_ENTITY_HEALTH(pedLocal) / TO_FLOAT(GET_ENTITY_MAX_HEALTH(pedLocal)) < 0.15 // 15% health is low
OR GET_ENTITY_HEALTH(playerEntity) / TO_FLOAT(GET_ENTITY_MAX_HEALTH(playerEntity)) < 0.15 // Check vehicle
IF HAS_SOUND_FINISHED(iLowHealthLoop)
PLAY_SOUND_FRONTEND(iLowHealthLoop, sLowHealthLoopSound, sSoundSet)
ENDIF
ELSE
IF NOT HAS_SOUND_FINISHED(iLowHealthLoop)
STOP_SOUND(iLowHealthLoop)
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC