Files
gtav-src/script/dev_ng/shared/include/public/script_oddjob_funcs.sch
T
2025-09-29 00:52:08 +02:00

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