614 lines
20 KiB
Scheme
Executable File
614 lines
20 KiB
Scheme
Executable File
//////////////////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// SCRIPT NAME : script_oddjob_funcs //
|
|
// AUTHOR : Steven Messinger //
|
|
// DESCRIPTION : Common functions that are shared across ASSASSINations, //
|
|
// towing, drug traffickings, taxi and others. //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
USING "cutscene_public.sch"
|
|
USING "savegame_public.sch"
|
|
USING "commands_shapetest.sch"
|
|
USING "dialogue_public.sch"
|
|
USING "minigames_helpers.sch"
|
|
USING "cheat_controller_public.sch"
|
|
|
|
VECTOR SAVE_VEHICLE_RANGE = <<500, 500, 500>>
|
|
|
|
ENUM CUTSCENE_STATE
|
|
CUTSCENE_STATE_START = 0,
|
|
CUTSCENE_STATE_CUT,
|
|
CUTSCENE_STATE_CUSTOM,
|
|
CUTSCENE_STATE_END
|
|
ENDENUM
|
|
|
|
ENUM COLLISION_STATE
|
|
COLLISION_STATE_START = 0,
|
|
COLLISION_STATE_WAIT,
|
|
COLLISION_STATE_RESULTS,
|
|
COLLISION_STATE_RERUN_DELAY
|
|
ENDENUM
|
|
|
|
ENUM GIVEUP_STATE
|
|
GIVEUP_STATE_INIT = 0,
|
|
GIVEUP_STATE_CHECK
|
|
ENDENUM
|
|
|
|
STRUCT CUTSCENE_ARGS
|
|
structTimer cutSceneTimer
|
|
CUTSCENE_STATE cutsceneState
|
|
ENDSTRUCT
|
|
|
|
STRUCT VEHICLE_SAVE_ARGS
|
|
VEHICLE_INDEX playerVehicle
|
|
ENDSTRUCT
|
|
|
|
STRUCT GIVEUP_ARGS
|
|
GIVEUP_STATE curState
|
|
INT iStartTime
|
|
FLOAT fStartDist
|
|
ENDSTRUCT
|
|
|
|
STRUCT COLLISION_ARGS
|
|
COLLISION_STATE testState
|
|
SHAPETEST_INDEX sphereShapeTest
|
|
SHAPETEST_INDEX shapeTestIndex
|
|
VECTOR vCollision
|
|
VECTOR vNormal
|
|
INT hitData
|
|
INT iFrameCount
|
|
ENTITY_INDEX hitEntity
|
|
BOOL bFailedLosCheck = FALSE
|
|
ENDSTRUCT
|
|
|
|
FUNC BOOL UPDATE_GIVE_UP(GIVEUP_ARGS& giveUpArgs, ENTITY_INDEX myEntity, FLOAT fGiveUpDist = 150.0, INT fFailTime = 30000)
|
|
VECTOR vPlayerPostion, vPedPostion
|
|
|
|
fGiveUpDist = fGiveUpDist
|
|
fFailTime = fFailTime
|
|
|
|
SWITCH giveUpArgs.curState
|
|
CASE GIVEUP_STATE_INIT
|
|
giveUpArgs.iStartTime = GET_GAME_TIMER()
|
|
giveUpArgs.fStartDist = GET_PLAYER_DISTANCE_FROM_ENTITY(myEntity)
|
|
PRINTLN("START DISTANCE FROM PLAYER = ", giveUpArgs.fStartDist)
|
|
|
|
PRINTLN("GOING TO STATE - GIVEUP_STATE_CHECK")
|
|
giveUpArgs.curState = GIVEUP_STATE_CHECK
|
|
BREAK
|
|
CASE GIVEUP_STATE_CHECK
|
|
IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID())
|
|
vPlayerPostion = GET_ENTITY_COORDS(PLAYER_PED_ID())
|
|
ENDIF
|
|
IF NOT IS_ENTITY_DEAD(myEntity)
|
|
vPedPostion = GET_ENTITY_COORDS(myEntity)
|
|
ENDIF
|
|
|
|
IF VDIST2(vPlayerPostion, vPedPostion) > 22500 // 150m
|
|
PRINTLN("We are too far away")
|
|
RETURN TRUE
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
|
|
/// NAME:
|
|
/// UPDATE_COLLISION_TESTS
|
|
/// PURPOSE:
|
|
/// A state machine that can constantly run to check for possible collisions up ahead of the player
|
|
FUNC BOOL UPDATE_COLLISION_TESTS(COLLISION_ARGS& collisionArgs, ENTITY_INDEX myEntity, FLOAT yDist = 20.0)
|
|
VECTOR vCheckCoord
|
|
SWITCH collisionArgs.testState
|
|
CASE COLLISION_STATE_START
|
|
vCheckCoord = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(myEntity, <<0,yDist,0>>)
|
|
collisionArgs.sphereShapeTest = START_SHAPE_TEST_BOX(vCheckCoord , <<10,90,5>>, GET_ENTITY_ROTATION(myEntity))
|
|
collisionArgs.testState = COLLISION_STATE_START
|
|
BREAK
|
|
CASE COLLISION_STATE_WAIT
|
|
IF GET_SHAPE_TEST_RESULT(collisionArgs.sphereShapeTest, collisionArgs.hitData, collisionArgs.vCollision, collisionArgs.vNormal) = SHAPETEST_STATUS_RESULTS_READY
|
|
collisionArgs.testState = COLLISION_STATE_RESULTS
|
|
ENDIF
|
|
BREAK
|
|
CASE COLLISION_STATE_RESULTS
|
|
IF collisionArgs.hitData > 0
|
|
RETURN TRUE
|
|
ELSE
|
|
RETURN FALSE
|
|
ENDIF
|
|
collisionArgs.testState = COLLISION_STATE_RERUN_DELAY
|
|
BREAK
|
|
CASE COLLISION_STATE_RERUN_DELAY
|
|
//For the sake of performance lets add a 10 frame delay between shape tests
|
|
collisionArgs.iFrameCount++
|
|
IF collisionArgs.iFrameCount > 10
|
|
collisionArgs.iFrameCount = 0
|
|
collisionArgs.testState = COLLISION_STATE_START
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
RETURN FALSE
|
|
|
|
ENDFUNC
|
|
|
|
/// NAME:
|
|
/// UPDATE_COLLISION_TESTS
|
|
/// PURPOSE:
|
|
/// A state machine that can constantly run to check for possible collisions up ahead of the player
|
|
FUNC BOOL UPDATE_COLLISION_TESTS_NOW(COLLISION_ARGS& collisionArgs, ENTITY_INDEX myEntity, FLOAT yDist = 75.0)
|
|
//TODO
|
|
VECTOR vPos
|
|
FLOAT fAngle
|
|
|
|
VECTOR vFront, vSide, vUp
|
|
IF NOT IS_ENTITY_DEAD(myEntity)
|
|
GET_ENTITY_MATRIX(myEntity, vFront, vSide, vUp, vPos)
|
|
ENDIF
|
|
|
|
//> 0.9 || < -0.9 to check
|
|
vFront.z = 0
|
|
vFront = NORMALISE_VECTOR(vFront)
|
|
fAngle = -ATAN2(vFront.x, vFront.y) //GET_ANGLE_BETWEEN_2D_VECTORS(vFront.x, vFront.y, 0, 1)
|
|
|
|
VECTOR checkCoord = vPos + vFront * yDist
|
|
collisionArgs.sphereShapeTest = START_SHAPE_TEST_BOX(checkCoord, <<12,140,12>>, <<0, 0, fAngle>>, EULER_XYZ)
|
|
|
|
WHILE GET_SHAPE_TEST_RESULT(collisionArgs.sphereShapeTest, collisionArgs.hitData, collisionArgs.vCollision, collisionArgs.vNormal, collisionArgs.hitEntity) = SHAPETEST_STATUS_RESULTS_NOTREADY
|
|
PRINTLN("Waiting for shape test result")
|
|
//Will this cause an overrun?
|
|
ENDWHILE
|
|
|
|
IF collisionArgs.hitData > 0
|
|
PRINTLN("Shape test collision found")
|
|
RETURN TRUE
|
|
ELSE
|
|
PRINTLN("Shape test no collision found")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
|
|
ENDFUNC
|
|
|
|
FUNC BOOL COMPUTE_LOS_BETWEEN_COORDS(COLLISION_ARGS& collisionArgs, VECTOR vProbeStart, VECTOR vProbeEnd, ENTITY_INDEX excludeEntity = NULL)
|
|
collisionArgs.bFailedLosCheck = FALSE
|
|
ENTITY_INDEX eHitEntity = NULL
|
|
VECTOR vCollision, vNormal
|
|
|
|
SWITCH collisionArgs.testState
|
|
CASE COLLISION_STATE_START
|
|
// RESET_COLLISION_ARGS(collisionArgs)
|
|
CDEBUG2LN(DEBUG_SYSTEM, "RUN_CLEAR_LOS_CHECK: COLLISION_STATE_START")
|
|
collisionArgs.shapeTestIndex = START_SHAPE_TEST_LOS_PROBE(vProbeStart, vProbeEnd, SCRIPT_INCLUDE_MOVER | SCRIPT_INCLUDE_OBJECT | SCRIPT_INCLUDE_VEHICLE, excludeEntity)
|
|
// SET_SHAPE_TEST_TIMEOUT(collisionArgs.shapeTestIndex, 15)
|
|
collisionArgs.testState = COLLISION_STATE_WAIT
|
|
BREAK
|
|
CASE COLLISION_STATE_WAIT
|
|
CDEBUG2LN(DEBUG_SYSTEM, "RUN_CLEAR_LOS_CHECK: COLLISION_STATE_WAIT")
|
|
IF GET_SHAPE_TEST_RESULT(collisionArgs.shapeTestIndex, collisionArgs.hitData, vCollision, vNormal, eHitEntity) = SHAPETEST_STATUS_RESULTS_READY
|
|
IF collisionArgs.hitData = 0
|
|
CDEBUG2LN(DEBUG_SYSTEM, "RUN_CLEAR_LOS_CHECK: Shapetest returned no collision")
|
|
collisionArgs.testState = COLLISION_STATE_RERUN_DELAY
|
|
RETURN TRUE
|
|
ELSE
|
|
CDEBUG2LN(DEBUG_SYSTEM, "RUN_CLEAR_LOS_CHECK: Shapetest returned a collision")
|
|
collisionArgs.bFailedLosCheck = TRUE
|
|
collisionArgs.testState = COLLISION_STATE_START
|
|
RETURN FALSE
|
|
ENDIF
|
|
ELIF GET_SHAPE_TEST_RESULT(collisionArgs.shapeTestIndex, collisionArgs.hitData, vCollision, vNormal, eHitEntity) = SHAPETEST_STATUS_NONEXISTENT
|
|
CDEBUG2LN(DEBUG_SYSTEM, "RUN_CLEAR_LOS_CHECK: There are no results! Starting Over. (It's possible you waited too long before calling this again and results have been lost over frames)")
|
|
collisionArgs.testState = COLLISION_STATE_RERUN_DELAY
|
|
ENDIF
|
|
BREAK
|
|
CASE COLLISION_STATE_RERUN_DELAY
|
|
collisionArgs.testState = COLLISION_STATE_START
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
|
|
FUNC BOOL COMPUTE_LOS_BETWEEN_ENTITIES(COLLISION_ARGS& collisionArgs, ENTITY_INDEX startEnt, ENTITY_INDEX targetEnt)
|
|
|
|
IF NOT DOES_ENTITY_EXIST(startEnt)
|
|
CERRORLN(DEBUG_SYSTEM, "COMPUTE_LOS_BETWEEN_PEDS is failing because startEnt doesn't exist")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF NOT DOES_ENTITY_EXIST(targetEnt)
|
|
CERRORLN(DEBUG_SYSTEM, "COMPUTE_LOS_BETWEEN_PEDS is failing because targetEnt doesn't exist")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
VECTOR vProbeStart = GET_ENTITY_COORDS(startEnt)
|
|
vProbeStart.z += 0.45
|
|
VECTOR vProbeEnd = GET_ENTITY_COORDS(targetEnt)
|
|
vProbeEnd.z += 0.45
|
|
RETURN COMPUTE_LOS_BETWEEN_COORDS(collisionArgs, vProbeStart, vProbeEnd, targetEnt)
|
|
ENDFUNC
|
|
|
|
PROC SCRIPT_REMOVE_BLIP_SAFE(BLIP_INDEX myBlip)
|
|
IF DOES_BLIP_EXIST(myBlip)
|
|
REMOVE_BLIP(myBlip)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC ODDJOB_AUTO_SAVE()
|
|
MAKE_AUTOSAVE_REQUEST()
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Attempts to save the last vehicle the player was in and then returns whether the save was successful or not
|
|
/// PARAMS:
|
|
/// mySaveArgs - Custom struct
|
|
/// RETURNS:
|
|
/// TRUE/FALSE if the save was successful/unsuccessful
|
|
FUNC BOOL ODDJOB_SAVE_VEHICLE(VEHICLE_SAVE_ARGS &mySaveArgs)
|
|
VEHICLE_INDEX tempVeh = GET_PLAYERS_LAST_VEHICLE()
|
|
IF DOES_ENTITY_EXIST(tempVeh)
|
|
IF NOT IS_VEHICLE_FUCKED(tempVeh)
|
|
IF NOT IS_PED_INJURED(PLAYER_PED_ID()) AND IS_ENTITY_AT_ENTITY(tempVeh, PLAYER_PED_ID(), SAVE_VEHICLE_RANGE)
|
|
//save vehicle
|
|
SET_LAST_DRIVEN_VEHICLE(tempVeh)
|
|
SET_ENTITY_COLLISION(tempVeh, FALSE)
|
|
SET_ENTITY_VISIBLE(tempVeh, FALSE)
|
|
FREEZE_ENTITY_POSITION(tempVeh, TRUE)
|
|
SET_ENTITY_AS_MISSION_ENTITY(tempVeh, TRUE, TRUE)
|
|
mySaveArgs.playerVehicle = tempVeh
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Attempts to save the last vehicle the player was in and then returns whether the save was successful or not. Also warps the vehicle to a "safe" location of your choice
|
|
/// PARAMS:
|
|
/// mySaveArgs - Custom struct
|
|
/// mySafeVector - Coordinates where the vehicle will be warped to
|
|
/// bAlsoModifyHeading - Do we want to have control over the heading?
|
|
/// myNewVehicleHeading - New heading for the vehicle
|
|
/// RETURNS:
|
|
/// TRUE/FALSE if the save was successful/unsuccessful
|
|
FUNC BOOL ODDJOB_SAVE_VEHICLE_AND_WARP(VEHICLE_SAVE_ARGS &mySaveArgs, VECTOR mySafeVector, BOOL bAlsoModifyHeading = FALSE, FLOAT myNewVehicleHeading = 0.0)
|
|
IF ODDJOB_SAVE_VEHICLE(mySaveArgs)
|
|
SET_LAST_DRIVEN_VEHICLE(mySaveArgs.playerVehicle)
|
|
IF NOT IS_VECTOR_ZERO(mySafeVector)
|
|
SET_ENTITY_COORDS(mySaveArgs.playerVehicle, mySafeVector)
|
|
IF bAlsoModifyHeading
|
|
SET_ENTITY_HEADING(mySaveArgs.playerVehicle, myNewVehicleHeading)
|
|
ENDIF
|
|
SET_VEHICLE_ON_GROUND_PROPERLY(mySaveArgs.playerVehicle)
|
|
ENDIF
|
|
RETURN TRUE
|
|
ENDIF
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Restores a vehicle if it has been saved with ODDJOB_SAVE_VEHICLE or ODDJOB_SAVE_VEHICLE_AND_WARP
|
|
/// PARAMS:
|
|
/// mySaveArgs - Custom struct
|
|
PROC ODDJOB_RESTORE_SAVED_VEHICLE(VEHICLE_SAVE_ARGS &mySaveArgs)
|
|
VEHICLE_INDEX tempVeh = mySaveArgs.playerVehicle
|
|
IF DOES_ENTITY_EXIST(tempVeh)
|
|
IF NOT IS_VEHICLE_FUCKED(tempVeh)
|
|
//restore vehicle
|
|
SET_ENTITY_COLLISION(tempVeh, TRUE)
|
|
SET_ENTITY_VISIBLE(tempVeh, TRUE)
|
|
FREEZE_ENTITY_POSITION(tempVeh, FALSE)
|
|
ENDIF
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// NAME:
|
|
/// ODDJOB_ENTER_CUTSCENE()
|
|
/// PURPOSE:
|
|
/// Wrapper function to handle all calls needed when ENTERING a cutscene
|
|
PROC ODDJOB_ENTER_CUTSCENE(SET_PLAYER_CONTROL_FLAGS controlFlags = 0,BOOL bEnablePadShakeDuringCutscene = FALSE, BOOL bSetMultiheadBlinders= TRUE)
|
|
SET_PLAYER_CONTROL(GET_PLAYER_INDEX(), FALSE, controlFlags)
|
|
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
|
|
STOP_FIRE_IN_RANGE(GET_ENTITY_COORDS(PLAYER_PED_ID()), 15)
|
|
ENDIF
|
|
SET_PAD_CAN_SHAKE_DURING_CUTSCENE(bEnablePadShakeDuringCutscene)
|
|
HANG_UP_AND_PUT_AWAY_PHONE()
|
|
SET_SCRIPTS_SAFE_FOR_CUTSCENE(TRUE,DEFAULT,bSetMultiheadBlinders)
|
|
DISPLAY_RADAR(FALSE)
|
|
DISPLAY_HUD(FALSE)
|
|
DISABLE_CHEAT(CHEAT_TYPE_ALL, TRUE)
|
|
ENDPROC
|
|
|
|
/// NAME:
|
|
/// ODDJOB_EXIT_CUTSCNE()
|
|
/// PURPOSE:
|
|
/// Wrapper function to handle all calls needed when EXITING a cutscene
|
|
PROC ODDJOB_EXIT_CUTSCENE(BOOL bGivePlayerControl = TRUE, BOOL bRestoreUI = TRUE,BOOL bSetMultiheadBlinders= TRUE)
|
|
IF bGivePlayerControl
|
|
SET_PLAYER_CONTROL(GET_PLAYER_INDEX(), TRUE)
|
|
ENDIF
|
|
SET_PAD_CAN_SHAKE_DURING_CUTSCENE(TRUE)
|
|
SET_SCRIPTS_SAFE_FOR_CUTSCENE(FALSE,DEFAULT,bSetMultiheadBlinders)
|
|
IF bRestoreUI
|
|
DISPLAY_RADAR(TRUE)
|
|
DISPLAY_HUD(TRUE)
|
|
ENDIF
|
|
DISABLE_CHEAT(CHEAT_TYPE_ALL, FALSE)
|
|
ENDPROC
|
|
|
|
TYPEDEF FUNC BOOL CustomCutsceneCaller()
|
|
|
|
FUNC BOOL CustomCutsceneCalle_NULL()
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL DO_CUTSCENE_CUSTOM(CUTSCENE_STATE& myState, structTimer& myTimer, VECTOR camVec, VECTOR camOrien, CAMERA_INDEX& myCamera,
|
|
STRING sPrintHelp, CustomCutsceneCaller fpCutsceneCustom, BOOL skipCutscene = FALSE,
|
|
BOOL bDoInterpFromGameCam = TRUE, BOOL bDoInterpBackToGameCam = FALSE, FLOAT fStartCamDoF = 65.0, INT iInterpTime = 3000,
|
|
INT iInterpTimeBackToGameCamera = DEFAULT_INTERP_TO_FROM_GAME, BOOL bRenderCamsOnFirstFrame = TRUE)
|
|
|
|
IF skipCutscene
|
|
PRINTSTRING("CALLING SKIP CUTSCENE")
|
|
//DEBUG_PRINT("CALLING SKIP CUTSCENE")
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
SWITCH myState
|
|
CASE CUTSCENE_STATE_START
|
|
ODDJOB_ENTER_CUTSCENE()
|
|
myCamera = CREATE_CAM_WITH_PARAMS("DEFAULT_SCRIPTED_CAMERA", camVec, camOrien, fStartCamDoF, TRUE)
|
|
|
|
|
|
IF bDoInterpFromGameCam
|
|
|
|
IF VDIST(GET_GAMEPLAY_CAM_COORD(), camVec) > 150
|
|
PRINTLN("adding 3 seconds")
|
|
iInterpTime += 3000
|
|
ELIF VDIST(GET_GAMEPLAY_CAM_COORD(), camVec) > 75
|
|
PRINTLN("adding 2 seconds")
|
|
iInterpTime += 2000
|
|
ENDIF
|
|
|
|
IF bRenderCamsOnFirstFrame
|
|
RENDER_SCRIPT_CAMS(TRUE, TRUE, iInterpTime)
|
|
ELSE
|
|
PRINTLN("bRenderCamsOnFirstFrame IS SET TO FALSE, YOU MUST CALL RENDER CAMS YOURSELF")
|
|
ENDIF
|
|
ELSE
|
|
IF bRenderCamsOnFirstFrame
|
|
RENDER_SCRIPT_CAMS(TRUE, FALSE)
|
|
ELSE
|
|
PRINTLN("bRenderCamsOnFirstFrame IS SET TO FALSE, YOU MUST CALL RENDER CAMS YOURSELF")
|
|
ENDIF
|
|
ENDIF
|
|
|
|
SET_CAM_ACTIVE(myCamera, TRUE)
|
|
IF NOT IS_STRING_NULL(sPrintHelp)
|
|
CLEAR_PRINTS()
|
|
PRINT_HELP(sPrintHelp)
|
|
ENDIF
|
|
RESTART_TIMER_NOW(myTimer)
|
|
myState = CUTSCENE_STATE_CUSTOM
|
|
BREAK
|
|
CASE CUTSCENE_STATE_CUSTOM
|
|
|
|
IF CALL fpCutsceneCustom()
|
|
myState = CUTSCENE_STATE_END
|
|
ENDIF
|
|
BREAK
|
|
CASE CUTSCENE_STATE_END
|
|
RENDER_SCRIPT_CAMS(FALSE, bDoInterpBackToGameCam, iInterpTimeBackToGameCamera)
|
|
DESTROY_CAM(myCamera)
|
|
ODDJOB_EXIT_CUTSCENE()
|
|
RETURN TRUE
|
|
BREAK
|
|
ENDSWITCH
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// NAME:
|
|
/// SCRIPT_GET_RANDOM_INT_NOT_LAST
|
|
/// PURPOSE:
|
|
/// Get a random number that isn't equal to the one specified (typically ensuring we get a random number that wasn't returned the last time we called this)
|
|
/// RETURNS:
|
|
/// random INT
|
|
FUNC INT SCRIPT_GET_RANDOM_INT_NOT_LAST(INT min, INT max, INT notThis)
|
|
INT rand
|
|
|
|
//to avoid a frame overrun for the unlikley case that we can't find a unique random
|
|
INT failSafe = 0
|
|
|
|
IF min = max
|
|
SCRIPT_ASSERT("Min and Max are the same")
|
|
RETURN 0
|
|
ENDIF
|
|
|
|
rand = GET_RANDOM_INT_IN_RANGE(min, max)
|
|
WHILE rand = notThis OR failSafe < 50
|
|
failSafe++
|
|
rand = GET_RANDOM_INT_IN_RANGE(min, max)
|
|
ENDWHILE
|
|
|
|
RETURN rand
|
|
ENDFUNC
|
|
|
|
/// NAME:
|
|
/// ODDJOB_START_CONVERSATION
|
|
/// PURPOSE:
|
|
/// Wrapper functions for starting a conversation that ensures the speakers are in range of the player before playing
|
|
FUNC BOOL ODDJOB_START_CONVERSATION(structPedsForConversation myConvStruct, STRING myBlock, String myRoot, PED_INDEX& piSpeakers[], BOOL bShouted = FALSE)
|
|
INT idx
|
|
BOOL bPedsInRange = TRUE
|
|
|
|
INT iRange = 75
|
|
|
|
IF bShouted
|
|
iRange = 100
|
|
ENDIF
|
|
|
|
REPEAT 1 idx
|
|
IF GET_PLAYER_DISTANCE_FROM_ENTITY(piSpeakers[idx]) > iRange
|
|
bPedsInRange = FALSE
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
IF bPedsInRange
|
|
CREATE_CONVERSATION(myConvStruct, myBlock, myRoot, CONV_PRIORITY_VERY_HIGH)
|
|
RETURN TRUE
|
|
ELSE
|
|
PRINTLN("Ped in conversation are over 250m away so we're not going trigger this conversation: ", myBlock, myRoot)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
ENDFUNC
|
|
|
|
|
|
/// NAME:
|
|
/// ODDJOB_STOP_SOUND
|
|
/// PURPOSE:
|
|
/// Wrapper functions for playing sound effects. Avoids asserts by checking for -1. Note must init soundId to -1
|
|
PROC ODDJOB_STOP_SOUND(INT& soundID)
|
|
IF soundID <> -1
|
|
PRINTSTRING(GET_THIS_SCRIPT_NAME())
|
|
PRINTSTRING(" is calling ODDJOB_STOP_SOUND")
|
|
PRINTNL()
|
|
STOP_SOUND(soundID)
|
|
RELEASE_SOUND_ID(soundID)
|
|
soundID = -1
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// NAME:
|
|
/// ODDJOB_PLAY_SOUND
|
|
/// PURPOSE:
|
|
/// Wrapper functions for playing sound effects. This handles looping sounds by getting sound id's
|
|
/// PARAMTERS:
|
|
/// STRING soundName - the sound effect you want to play
|
|
/// INT soundID - sound id that's stored off and passed back by reference. Used for looping sounds
|
|
/// BOOL bLooping - bool to specify if the sound should loop
|
|
/// ENTITY_INDEX myVehicle - Defaults to null but if you specifcy an entity here it will play sound from this entity
|
|
PROC ODDJOB_PLAY_SOUND(STRING soundName, INT& soundID, BOOL bLooping = FALSE, ENTITY_INDEX myVehicle = NULL, FLOAT fX = 0.0, FLOAT fY = 0.0, FLOAT fZ = 0.0, STRING soundSetName = NULL)
|
|
|
|
ODDJOB_STOP_SOUND(soundID)
|
|
IF bLooping
|
|
soundID = GET_SOUND_ID()
|
|
ELSE
|
|
soundID = -1
|
|
ENDIF
|
|
|
|
DEBUG_MESSAGE("Play sound front end: ", soundName)
|
|
|
|
IF myVehicle <> NULL
|
|
PLAY_SOUND_FROM_ENTITY(soundID, soundName, myVehicle, soundSetName)
|
|
PRINTLN("PLAYING SOUND FROM ENTITY")
|
|
ELIF fx <> 0 OR fY <> 0 OR fZ <> 0
|
|
PLAY_SOUND_FROM_COORD(soundId, soundName, <<fX, fY, fZ>>, soundSetName)
|
|
PRINTLN("PLAYING SOUND FROM COORD")
|
|
ELSE
|
|
PLAY_SOUND_FRONTEND(soundID, soundName, soundSetName)
|
|
PRINTLN("PLAYING SOUND FROM FRONTEND")
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
|
|
/// NAME:
|
|
/// HANDLE_SKIP_CUTSCENE
|
|
/// PURPOSE:
|
|
/// Wrapper function including all the things you need to call when skipping a cut scene
|
|
/// INPUT:
|
|
/// INT iAllowSkipCutsceneTime - gametime of when the cutscene started
|
|
FUNC BOOL HANDLE_SKIP_CUTSCENE(INT iAllowSkipCutsceneTime)
|
|
IF IS_CUTSCENE_SKIP_BUTTON_JUST_PRESSED()
|
|
AND GET_GAME_TIMER() >= iAllowSkipCutsceneTime + 1000
|
|
DEBUG_MESSAGE("SKipped")
|
|
DO_SCREEN_FADE_OUT(500)
|
|
WHILE NOT IS_SCREEN_FADED_OUT()
|
|
WAIT(0)
|
|
ENDWHILE
|
|
|
|
HANG_UP_AND_PUT_AWAY_PHONE()
|
|
KILL_ANY_CONVERSATION()
|
|
RETURN TRUE
|
|
ENDIF
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
///Name:
|
|
/// SHOULD_TRIGGER_ENTITY
|
|
///Purpose:
|
|
/// Takes into account how long a ped is visible on screen, your distance from the ped, and your current speed to nicely handle if the ped should be "triggred"
|
|
/// For example turning to talk to you or triggereing dialouge.
|
|
FUNC BOOL SHOULD_TRIGGER_ENTITY(ENTITY_INDEX myEntity, ENTITY_INDEX myVehicle, INT& iFrameCount, INT frametime = 70, FLOAT minDist = 35.0, FLOAT minSpeed = 4.0, BOOL bDebugSpew = FALSE)
|
|
PED_INDEX myPed
|
|
//INT iNative = NATIVE_TO_INT(myEntity)
|
|
//myPed = INT_TO_NATIVE(PED_INDEX, iNative))
|
|
|
|
IF DOES_ENTITY_EXIST(myEntity)
|
|
IF IS_ENTITY_A_PED(myEntity)
|
|
myPed = GET_PED_INDEX_FROM_ENTITY_INDEX(myEntity)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF DOES_ENTITY_EXIST(myEntity)
|
|
IF NOT IS_ENTITY_DEAD(myPed) AND IS_PED_INJURED(myPed)
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF DOES_ENTITY_EXIST(myEntity) AND DOES_ENTITY_EXIST(myVehicle)
|
|
IF NOT IS_ENTITY_DEAD(myEntity) AND NOT IS_ENTITY_DEAD(myVehicle)
|
|
IF bDebugSpew
|
|
PRINTLN("Visible frame count: ", iFrameCount, " Player Distance: ", GET_PLAYER_DISTANCE_FROM_ENTITY(myEntity))
|
|
ENDIF
|
|
|
|
IF NOT IS_ENTITY_OCCLUDED(myEntity) AND GET_PLAYER_DISTANCE_FROM_ENTITY(myEntity) < minDist
|
|
iFrameCount++
|
|
ELSE
|
|
iFrameCount = 0
|
|
ENDIF
|
|
IF (iFrameCount > frametime OR GET_PLAYER_DISTANCE_FROM_ENTITY(myEntity) < 8)
|
|
AND GET_ENTITY_SPEED(myVehicle) < minSpeed AND NOT IS_ENTITY_OCCLUDED(myEntity)
|
|
iFrameCount = 0
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
IF bDebugSpew
|
|
PRINTLN("Should trigger Ped is false")
|
|
ENDIF
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
/// PURPOSE:
|
|
///
|
|
/// PARAMS:
|
|
/// wtWeapon - the weapon to check
|
|
/// RETURNS:TRUE if it's considered lethal/deadly, FALSE otherwise
|
|
///
|
|
FUNC BOOL IS_WEAPON_NON_LETHAL(WEAPON_TYPE &wtWeapon)
|
|
|
|
IF wtWeapon = WEAPONTYPE_UNARMED
|
|
OR wtWeapon = WEAPONTYPE_SMOKEGRENADE
|
|
OR wtWeapon = WEAPONTYPE_FIREEXTINGUISHER
|
|
OR wtWeapon = WEAPONTYPE_PETROLCAN
|
|
OR wtWeapon = WEAPONTYPE_DLC_RUBBERGUN
|
|
#IF IS_DEBUG_BUILD
|
|
PRINTLN("The current weapon, ", "", wtWeapon, "", " is NON LETHAL")
|
|
#ENDIF
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
|
|
ENDFUNC
|
|
|
|
//EOF
|
|
|
|
|
|
|