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