////////////////////////////////////////////////////////////////////////////////////////////////////////////// // 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 = -<> // 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