1901 lines
62 KiB
Scheme
Executable File
1901 lines
62 KiB
Scheme
Executable File
|
|
// This section holds most/all of the USINGS for native commands and commonly used script helpers
|
|
USING "rage_builtins.sch"
|
|
USING "globals.sch"
|
|
USING "commands_audio.sch"
|
|
USING "commands_camera.sch"
|
|
USING "commands_event.sch"
|
|
USING "commands_clock.sch"
|
|
USING "commands_debug.sch"
|
|
USING "commands_fire.sch"
|
|
USING "commands_graphics.sch"
|
|
USING "commands_hud.sch"
|
|
USING "commands_misc.sch"
|
|
USING "commands_object.sch"
|
|
USING "commands_pad.sch"
|
|
USING "commands_player.sch"
|
|
USING "commands_script.sch"
|
|
USING "commands_streaming.sch"
|
|
USING "commands_task.sch"
|
|
USING "commands_vehicle.sch"
|
|
USING "commands_interiors.sch"
|
|
USING "commands_entity.sch"
|
|
USING "commands_physics.sch"
|
|
|
|
USING "script_maths.sch"
|
|
USING "script_blips.sch"
|
|
USING "script_ped.sch"
|
|
USING "script_player.sch"
|
|
USING "script_misc.sch"
|
|
USING "script_drawing.sch"
|
|
USING "locates_public.sch"
|
|
USING "timer_public.sch"
|
|
USING "mission_control_public.sch"
|
|
USING "brains.sch"
|
|
USING "ambience_run_checks.sch"
|
|
USING "flow_public_core_override.sch"
|
|
USING "model_enums.sch"
|
|
USING "help_at_location.sch"
|
|
USING "load_queue_public.sch"
|
|
|
|
/// PURPOSE: Enumeration for control types for minigame players so minigames can be used in both SP and MP
|
|
ENUM PLAYER_CONTROL_TYPE
|
|
CONTROL_NONE,
|
|
HUMAN_LOCAL,
|
|
HUMAN_LOCAL_MP,
|
|
HUMAN_NETWORK,
|
|
COMPUTER
|
|
ENDENUM
|
|
|
|
/// PURPOSE:
|
|
/// Helper function to get a color that matches hud
|
|
/// PARAMS:
|
|
/// hudColor - The hud color you want to match
|
|
/// RETURNS:
|
|
/// The INT_COLOR of the hud color you pass in
|
|
FUNC INT GetTextColor(HUD_COLOURS hudColor, INT iAlpha = -1)
|
|
|
|
INT iR,iG,iB,iA
|
|
GET_HUD_COLOUR(hudColor, iR, iG, iB, iA)
|
|
|
|
IF iAlpha = -1
|
|
RETURN INT_COLOUR(iR, iG, iB, iA)
|
|
ELSE
|
|
RETURN INT_COLOUR(iR, iG, iB, iAlpha)
|
|
ENDIF
|
|
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Procedure that prints an integer as bits to the console (NOT the game screen)
|
|
/// Goes from most significant bit to least.
|
|
/// You'll need to follow it with PRINTNL() if you want to
|
|
PROC PRINTBITS(INT bits, INT spacing = 4)
|
|
INT i
|
|
|
|
FOR i=31 TO 0 STEP -1
|
|
IF IS_BIT_SET( bits, i)
|
|
PRINTINT(1)
|
|
ELSE
|
|
PRINTINT(0)
|
|
ENDIF
|
|
|
|
IF i%spacing = 0 AND i > 0
|
|
PRINTSTRING(" ")
|
|
ENDIF
|
|
ENDFOR
|
|
ENDPROC
|
|
|
|
|
|
//FUNC CONTROL_ACTION TRANSLATE_INSTR_BUTTON_TO_CONTROL_ACTION(TEXT_LABEL_63 instrButton)
|
|
// SWITCH(instrButton)
|
|
// CASE ICON_LSTICK_LEFTRIGHT
|
|
// RETURN INPUT_FRONTEND_AXIS_X //LEFTSTICKX
|
|
// BREAK
|
|
// CASE ICON_LSTICK_UPDOWN
|
|
// RETURN INPUT_FRONTEND_AXIS_Y //LEFTSTICKY
|
|
// BREAK
|
|
// CASE ICON_RSTICK_LEFTRIGHT
|
|
// RETURN INPUT_FRONTEND_RIGHT_AXIS_X //RIGHTSTICKX
|
|
// BREAK
|
|
// CASE ICON_RSTICK_UPDOWN
|
|
// RETURN INPUT_FRONTEND_RIGHT_AXIS_Y //RIGHTSTICKY
|
|
// BREAK
|
|
// CASE ICON_UP
|
|
// CASE ICON_DPAD_UP
|
|
// RETURN INPUT_FRONTEND_UP
|
|
// BREAK
|
|
// CASE ICON_DOWN
|
|
// CASE ICON_DPAD_DOWN
|
|
// RETURN INPUT_FRONTEND_DOWN
|
|
// BREAK
|
|
// CASE ICON_LEFT
|
|
// CASE ICON_DPAD_LEFT
|
|
// RETURN INPUT_FRONTEND_LEFT
|
|
// BREAK
|
|
// CASE ICON_RIGHT
|
|
// CASE ICON_DPAD_RIGHT
|
|
// RETURN INPUT_FRONTEND_RIGHT
|
|
// BREAK
|
|
// CASE ICON_BUTTON_START
|
|
// RETURN INPUT_FRONTEND_PAUSE
|
|
// BREAK
|
|
// CASE ICON_BUTTON_BACK
|
|
// RETURN INPUT_FRONTEND_SELECT
|
|
// BREAK
|
|
// CASE ICON_BUTTON_X
|
|
// RETURN INPUT_FRONTEND_X
|
|
// BREAK
|
|
// CASE ICON_BUTTON_Y
|
|
// RETURN INPUT_FRONTEND_Y
|
|
// BREAK
|
|
// CASE ICON_BUTTON_A
|
|
// RETURN INPUT_FRONTEND_ACCEPT
|
|
// BREAK
|
|
// CASE ICON_BUTTON_B
|
|
// RETURN INPUT_FRONTEND_CANCEL
|
|
// BREAK
|
|
// //CASE ICON_LSTICK_NONE
|
|
// // //RETURN ? //LEFTSHOCK
|
|
// //BREAK
|
|
// //CASE ICON_RSTICK_NONE
|
|
// // //RETURN ? //RIGHTSHOCK
|
|
// //BREAK
|
|
// CASE ICON_BUTTON_LB
|
|
// RETURN INPUT_FRONTEND_LB
|
|
// BREAK
|
|
// CASE ICON_BUTTON_LT
|
|
// RETURN INPUT_FRONTEND_LT
|
|
// BREAK
|
|
// CASE ICON_BUTTON_RB
|
|
// RETURN INPUT_FRONTEND_RB
|
|
// BREAK
|
|
// CASE ICON_BUTTON_RT
|
|
// RETURN INPUT_FRONTEND_RT
|
|
// BREAK
|
|
// ENDSWITCH
|
|
//
|
|
// RETURN INT_TO_ENUM(CONTROL_ACTION, -1)
|
|
//ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Gets a random float in [mean-deviation, mean+deviation]. Uses trig functions to cluster these around mean and spreads out toward +-deviation.
|
|
/// PARAMS:
|
|
/// mean - Value to cluster the randoms around
|
|
/// deviation - maximum deviator away from mean
|
|
/// RETURNS:
|
|
/// A random value in in [mean-deviation, mean+deviation], tending to cluster around mean.
|
|
FUNC FLOAT GET_RANDOM_FLOAT_POLAR(FLOAT mean = 0.0, FLOAT deviation = 1.0)
|
|
FLOAT randTri = SIN(GET_RANDOM_FLOAT_IN_RANGE(-180.0, 180))
|
|
IF randTri < 0
|
|
randTri++
|
|
ELSE
|
|
randTri--
|
|
ENDIF
|
|
RETURN mean + randTri * deviation
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Fades down and lets us know when it's complete.
|
|
/// RETURNS:
|
|
/// TRUE when fully faded.
|
|
FUNC BOOL FADE_DOWN(INT iFadeTime = DEFAULT_FADE_TIME)
|
|
DO_SCREEN_FADE_OUT(iFadeTime)
|
|
WHILE NOT IS_SCREEN_FADED_OUT()
|
|
WAIT(0)
|
|
ENDWHILE
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Fades up and lets us know when it's complete.
|
|
/// RETURNS:
|
|
/// TRUE when fully faded.
|
|
FUNC BOOL FADE_UP(INT iFadeTime = DEFAULT_FADE_TIME)
|
|
DO_SCREEN_FADE_IN(iFadeTime)
|
|
WHILE NOT IS_SCREEN_FADED_IN()
|
|
WAIT(0)
|
|
ENDWHILE
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Make an array of strings point at an array of text labels.
|
|
PROC POINT_STRINGS_AT_TEXT_LABEL_3(STRING& sStrings[], TEXT_LABEL_3& sLabels[], INT iStrings)
|
|
INT iCounter
|
|
REPEAT iStrings iCounter
|
|
sStrings[iCounter] = TEXT_LABEL_TO_STRING(sLabels[iCounter])
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Make an array of strings point at an array of text labels.
|
|
PROC POINT_STRINGS_AT_TEXT_LABEL_7(STRING& sStrings[], TEXT_LABEL_7& sLabels[], INT iStrings)
|
|
INT iCounter
|
|
REPEAT iStrings iCounter
|
|
sStrings[iCounter] = TEXT_LABEL_TO_STRING(sLabels[iCounter])
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Make an array of strings point at an array of text labels.
|
|
PROC POINT_STRINGS_AT_TEXT_LABEL_15(STRING& sStrings[], TEXT_LABEL_15& sLabels[], INT iStrings)
|
|
INT iCounter
|
|
REPEAT iStrings iCounter
|
|
sStrings[iCounter] = TEXT_LABEL_TO_STRING(sLabels[iCounter])
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Make an array of strings point at an array of text labels.
|
|
PROC POINT_STRINGS_AT_TEXT_LABEL_23(STRING& sStrings[], TEXT_LABEL_23& sLabels[], INT iStrings)
|
|
INT iCounter
|
|
REPEAT iStrings iCounter
|
|
sStrings[iCounter] = TEXT_LABEL_TO_STRING(sLabels[iCounter])
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Make an array of strings point at an array of text labels.
|
|
PROC POINT_STRINGS_AT_TEXT_LABEL_31(STRING& sStrings[], TEXT_LABEL_31& sLabels[], INT iStrings)
|
|
INT iCounter
|
|
REPEAT iStrings iCounter
|
|
sStrings[iCounter] = TEXT_LABEL_TO_STRING(sLabels[iCounter])
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Make an array of strings point at an array of text labels.
|
|
PROC POINT_STRINGS_AT_TEXT_LABEL_63(STRING& sStrings[], TEXT_LABEL_63& sLabels[], INT iStrings)
|
|
INT iCounter
|
|
REPEAT iStrings iCounter
|
|
sStrings[iCounter] = TEXT_LABEL_TO_STRING(sLabels[iCounter])
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Prints the name of the script, and then the printed message
|
|
/// PARAMS:
|
|
/// strMessage - Message to print
|
|
/// strMessage[2-6] - Optional messages to print
|
|
/// separator - optional separator, will go between messages 2-6.
|
|
DEBUGONLY PROC DEBUG_MESSAGE(STRING strMessage, STRING strMessage2 = NULL, STRING strMessage3 = NULL, STRING strMessage4 = NULL, STRING strMessage5 = NULL, STRING strMessage6 = NULL, STRING separator = NULL )
|
|
PRINTSTRING(GET_THIS_SCRIPT_NAME())
|
|
PRINTSTRING(": ")
|
|
PRINTINT(GET_GAME_TIMER())
|
|
PRINTSTRING(": ")
|
|
IF NOT IS_STRING_NULL( strMessage ) PRINTSTRING(strMessage) ENDIF
|
|
|
|
IF NOT IS_STRING_NULL( strMessage2 ) PRINTSTRING( strMessage2 ) ENDIF
|
|
IF NOT IS_STRING_NULL( separator ) PRINTSTRING( separator ) ENDIF
|
|
|
|
IF NOT IS_STRING_NULL( strMessage3 ) PRINTSTRING( strMessage3 ) ENDIF
|
|
IF NOT IS_STRING_NULL( separator ) PRINTSTRING( separator ) ENDIF
|
|
|
|
IF NOT IS_STRING_NULL( strMessage4 ) PRINTSTRING( strMessage4 ) ENDIF
|
|
IF NOT IS_STRING_NULL( separator ) PRINTSTRING( separator ) ENDIF
|
|
|
|
IF NOT IS_STRING_NULL( strMessage5 ) PRINTSTRING( strMessage5 ) ENDIF
|
|
IF NOT IS_STRING_NULL( separator ) PRINTSTRING( separator ) ENDIF
|
|
|
|
IF NOT IS_STRING_NULL( strMessage6 ) PRINTSTRING( strMessage6 ) ENDIF
|
|
PRINTNL()
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Convert a given vector into a printable string format. Similar (but clunkier) usage to V2STR from RDR2.
|
|
/// PARAMS:
|
|
/// v - valid vector to be converted to prinatable format
|
|
/// RETURNS:
|
|
/// text label containing
|
|
FUNC TEXT_LABEL_31 V2STR(VECTOR v)
|
|
TEXT_LABEL_31 retVal = "<< "
|
|
retVal += CEIL(v.x)
|
|
retVal += ", "
|
|
retVal += CEIL(v.y)
|
|
retVal += ", "
|
|
retVal += CEIL(v.z)
|
|
retVal += " >>"
|
|
RETURN retVal
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Prints the name of the script, and then the printed message. Throttles the given print to once a second
|
|
/// PARAMS:
|
|
/// strMessage - Message to print
|
|
/// messageThrottle
|
|
/// strMessage[2-6] - Optional messages to print
|
|
/// separator - optional separator, will go between messages 2-6.
|
|
/// throttleFrequency - sets how often it'll print (1 second or so)
|
|
PROC DEBUG_MESSAGE_PERIODIC(STRING strMessage, INT &fMessageThrottle, STRING strMessage2 = NULL, STRING strMessage3 = NULL, STRING strMessage4 = NULL, STRING strMessage5 = NULL, STRING strMessage6 = NULL, STRING separator = NULL, INT throttleFrequency = 1000 )
|
|
IF GET_GAME_TIMER() < fMessageThrottle + throttleFrequency
|
|
EXIT
|
|
ENDIF
|
|
fMessageThrottle = GET_GAME_TIMER()
|
|
DEBUG_MESSAGE( strMessage, strMessage2, strMessage3, strMessage4, strMessage5, strMessage6, separator )
|
|
ENDPROC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Prints the name of the script, and then the printed message. Throttles the given print to once a second
|
|
/// PARAMS:
|
|
/// strMessage - Message to print
|
|
/// messageThrottle
|
|
/// throttleFrequency - sets how often it'll print (1 second or so)
|
|
PROC CDEBUG_MESSAGE_OJ_TAXI_PERIODIC(STRING strMessage, INT &fMessageThrottle,INT throttleFrequency = 1000)
|
|
IF GET_GAME_TIMER() < fMessageThrottle + throttleFrequency
|
|
EXIT
|
|
ENDIF
|
|
fMessageThrottle = GET_GAME_TIMER()
|
|
CDEBUG1LN(DEBUG_OJ_TAXI,strMessage)
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Checks if a string is null/empty.
|
|
/// PARAMS:
|
|
/// sString - String to check if null/empty
|
|
/// RETURNS:
|
|
/// TRUE if string is null/empty, FALSE otherwise.
|
|
FUNC BOOL IS_STRING_EMPTY(STRING sString)
|
|
IF IS_STRING_NULL(sString)
|
|
//DEBUG_MESSAGE("IS_STRING_EMPTY: String is null!")
|
|
RETURN TRUE
|
|
ENDIF
|
|
IF (GET_LENGTH_OF_LITERAL_STRING(sString) <= 0)
|
|
//DEBUG_MESSAGE("IS_STRING_EMPTY: String is empty!")
|
|
RETURN TRUE
|
|
ENDIF
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
//FUNC VECTOR CONVERT_ROTATION_TO_DIRECTION_VECTOR(VECTOR v_rot)
|
|
// RETURN <<-SIN(v_rot.z) * COS(v_rot.x), COS(v_rot.z) * COS(v_rot.x), SIN(v_rot.x)>>
|
|
//ENDFUNC
|
|
|
|
/// PURPOSE: Struct for building streaming helpers (if needed)
|
|
STRUCT STREAMED_MODEL
|
|
MODEL_NAMES thisModel = DUMMY_MODEL_FOR_SCRIPT
|
|
ENDSTRUCT
|
|
|
|
/// PURPOSE:
|
|
/// Finds the first uninitialized element in a streaming array. Returns -1 if the array is full.
|
|
/// PARAMS:
|
|
/// streamedModel - streaming array to search in
|
|
/// RETURNS:
|
|
/// The index of the first uninitialized element in a streaming array. -1 if the array is full. The return value must be tested before being used!
|
|
FUNC INT GET_EMPTY_STREAMED_MODEL(STREAMED_MODEL &streamedModel[])
|
|
INT modelIndex
|
|
REPEAT COUNT_OF(streamedModel) modelIndex
|
|
IF streamedModel[modelIndex].thisModel = DUMMY_MODEL_FOR_SCRIPT // IS THIS THE CORRECT NULL CHECK??
|
|
RETURN modelIndex
|
|
ENDIF
|
|
ENDREPEAT
|
|
RETURN -1
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Adds a model to the first uninitialized element of a streaming array.
|
|
/// PARAMS:
|
|
/// streamedModel - Streaming array to add to
|
|
/// newModel - MODEL_NAMES to add
|
|
/// RETURNS:
|
|
/// TRUE if the model was successfully added, FALSE otherwise (the array was full)
|
|
FUNC BOOL ADD_STREAMED_MODEL(STREAMED_MODEL &streamedModel[], MODEL_NAMES newModel)
|
|
INT iModelIndex
|
|
REPEAT COUNT_OF(streamedModel) iModelIndex
|
|
IF streamedModel[iModelIndex].thisModel != DUMMY_MODEL_FOR_SCRIPT
|
|
IF streamedModel[iModelIndex].thisModel = newModel
|
|
DEBUG_MESSAGE("ADD_STREAMED_MODEL returning FALSE, model already in the index")
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
INT modelIndex = GET_EMPTY_STREAMED_MODEL(streamedModel)
|
|
IF modelIndex < 0 OR modelIndex >= COUNT_OF(streamedModel)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
streamedModel[modelIndex].thisModel = newModel
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Requests all initialized models in a streaming array
|
|
/// PARAMS:
|
|
/// streamedModel - Streaming array to request
|
|
PROC REQUEST_ALL_MODELS(STREAMED_MODEL &streamedModel[])
|
|
INT modelIndex
|
|
REPEAT COUNT_OF(streamedModel) modelIndex
|
|
IF streamedModel[modelIndex].thisModel != DUMMY_MODEL_FOR_SCRIPT // IS THIS THE CORRECT NULL CHECK??
|
|
REQUEST_MODEL(streamedModel[modelIndex].thisModel)
|
|
// REQUEST_COLLISION_FOR_MODEL(streamedModel[modelIndex].thisModel)
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Checks to see if all models in a streaming array are in memory
|
|
/// PARAMS:
|
|
/// streamedModel - Streaming array to check
|
|
/// RETURNS:
|
|
/// TRUE if every initialized element in a streaming array is in memory, FALSE if at least one is not in memory
|
|
FUNC BOOL ARE_MODELS_STREAMED(STREAMED_MODEL &streamedModel[])
|
|
INT modelIndex
|
|
REPEAT COUNT_OF(streamedModel) modelIndex
|
|
IF streamedModel[modelIndex].thisModel != DUMMY_MODEL_FOR_SCRIPT // IS THIS THE CORRECT NULL CHECK??
|
|
IF NOT HAS_MODEL_LOADED(streamedModel[modelIndex].thisModel) //OR NOT HAS_COLLISION_FOR_MODEL_LOADED(streamedModel[modelIndex].thisModel)
|
|
IF NOT HAS_MODEL_LOADED(streamedModel[modelIndex].thisModel)
|
|
#IF IS_DEBUG_BUILD
|
|
DEBUG_MESSAGE("Waiting to stream model ", GET_MODEL_NAME_FOR_DEBUG(streamedModel[modelIndex].thisModel))
|
|
#ENDIF // IS_DEBUG_BUILD
|
|
ENDIF
|
|
// IF NOT HAS_COLLISION_FOR_MODEL_LOADED(streamedModel[modelIndex].thisModel)
|
|
// DEBUG_MESSAGE("Waiting to stream collision for ", GET_MODEL_NAME_FOR_DEBUG(streamedModel[modelIndex].thisModel))
|
|
// ENDIF
|
|
RETURN FALSE
|
|
ELSE
|
|
#IF IS_DEBUG_BUILD
|
|
DEBUG_MESSAGE("STREAMED IN ", GET_MODEL_NAME_FOR_DEBUG(streamedModel[modelIndex].thisModel))
|
|
#ENDIF // IS_DEBUG_BUILD
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Sets all of the models in the streaming array as no longer needed
|
|
/// Only necessary for streaming in and out during missions...scripts auto-do this when they clean up
|
|
/// PARAMS:
|
|
/// streamedModel - Streaming array to request
|
|
PROC SET_ALL_MODELS_AS_NO_LONGER_NEEDED(STREAMED_MODEL &streamedModel[])
|
|
INT modelIndex
|
|
REPEAT COUNT_OF(streamedModel) modelIndex
|
|
IF streamedModel[modelIndex].thisModel != DUMMY_MODEL_FOR_SCRIPT // IS THIS THE CORRECT NULL CHECK??
|
|
SET_MODEL_AS_NO_LONGER_NEEDED(streamedModel[modelIndex].thisModel)
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
/// PURPOSE: Struct for building streaming helpers
|
|
STRUCT STREAMED_ANIM
|
|
STRING thisAnim
|
|
ENDSTRUCT
|
|
|
|
/// PURPOSE:
|
|
/// Finds the first uninitialized element in a streaming array. Returns -1 if the array is full.
|
|
/// PARAMS:
|
|
/// streamedAnim - streaming array to search in
|
|
/// RETURNS:
|
|
/// The index of the first uninitialized element in a streaming array. -1 if the array is full. The return value must be tested before being used!
|
|
FUNC INT GET_EMPTY_STREAMED_ANIM(STREAMED_ANIM &streamedAnim[])
|
|
INT animIndex
|
|
REPEAT COUNT_OF(streamedAnim) animIndex
|
|
IF IS_STRING_NULL(streamedAnim[animIndex].thisAnim)
|
|
RETURN animIndex
|
|
ENDIF
|
|
ENDREPEAT
|
|
RETURN -1
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Adds an anim dict to the first uninitialized element of a streaming array.
|
|
/// PARAMS:
|
|
/// streamedAnim - Streaming array to add to
|
|
/// newAnim- STRING of anim name to add
|
|
/// RETURNS:
|
|
/// TRUE if the anim string was successfully added, FALSE otherwise (the array was full)
|
|
FUNC BOOL ADD_STREAMED_ANIM(STREAMED_ANIM &streamedAnim[], STRING newAnim)
|
|
INT iAnimIndex
|
|
REPEAT COUNT_OF(streamedAnim) iAnimIndex
|
|
IF NOT IS_STRING_NULL(streamedAnim[iAnimIndex].thisAnim)
|
|
IF ARE_STRINGS_EQUAL(streamedAnim[iAnimIndex].thisAnim, newAnim)
|
|
DEBUG_MESSAGE("ADD_STREAMED_ANIM returning FALSE, anim already in the index")
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
INT animIndex = GET_EMPTY_STREAMED_ANIM(streamedAnim)
|
|
IF animIndex < 0 OR animIndex >= COUNT_OF(streamedAnim)
|
|
DEBUG_MESSAGE("ADD_STREAMED_ANIM returning FALSE, array is full")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
streamedAnim[animIndex].thisAnim = newAnim
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Requests all initialized anims in a streaming array
|
|
/// PARAMS:
|
|
/// streamedAnim - Streaming array to request
|
|
PROC REQUEST_ALL_ANIMS(STREAMED_ANIM &streamedAnim[], LoadQueueLarge &sLoadQueue)
|
|
INT animIndex
|
|
REPEAT COUNT_OF(streamedAnim) animIndex
|
|
IF NOT IS_STRING_NULL(streamedAnim[animIndex].thisAnim)
|
|
LOAD_QUEUE_LARGE_ADD_ANIM_DICT(sLoadQueue, streamedAnim[animIndex].thisAnim)
|
|
DEBUG_MESSAGE("ADDING ANIM DICT TO QUEUE: ", streamedAnim[animIndex].thisAnim)
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Checks to see if all anims in a streaming array are in memory
|
|
/// PARAMS:
|
|
/// streamedAnim - Streaming array to check
|
|
/// RETURNS:
|
|
/// TRUE if every initialized element in a streaming array is in memory, FALSE if at least one is not in memory
|
|
FUNC BOOL ARE_ANIMS_STREAMED(LoadQueueLarge &sLoadQueue)
|
|
RETURN HAS_LOAD_QUEUE_LARGE_LOADED(sLoadQueue)
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Sets all of the models in the streaming array as no longer needed
|
|
/// Only necessary for streaming in and out during missions...scripts auto-do this when they clean up
|
|
/// PARAMS:
|
|
/// streamedModel - Streaming array to request
|
|
PROC SET_ALL_ANIMS_AS_NO_LONGER_NEEDED(STREAMED_ANIM &streamedAnim[])
|
|
INT animIndex
|
|
REPEAT COUNT_OF(streamedAnim) animIndex
|
|
IF NOT IS_STRING_NULL_OR_EMPTY(streamedAnim[animIndex].thisAnim)
|
|
REMOVE_ANIM_DICT(streamedAnim[animIndex].thisAnim)
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
|
|
/*
|
|
/// PURPOSE: Struct for building streaming helpers
|
|
STRUCT STREAMED_VEHICLE_RECORDING
|
|
INT thisRecordingIndex
|
|
STRING thisRecording
|
|
ENDSTRUCT
|
|
|
|
/// PURPOSE:
|
|
/// Finds the first uninitialized element in a streaming array. Returns -1 if the array is full.
|
|
/// PARAMS:
|
|
/// streamedRecordings - streaming array to search in
|
|
/// RETURNS:
|
|
/// The index of the first uninitialized element in a streaming array. -1 if the array is full. The return value must be tested before being used!
|
|
FUNC INT GET_EMPTY_STREAMED_VEHICLE_RECORDING(STREAMED_VEHICLE_RECORDING &streamedRecordings[])
|
|
INT recordingIndex
|
|
REPEAT COUNT_OF(streamedRecordings) recordingIndex
|
|
IF IS_STRING_NULL(streamedRecordings[recordingIndex].thisRecording)
|
|
RETURN recordingIndex
|
|
ENDIF
|
|
ENDREPEAT
|
|
RETURN -1
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Adds an anim dict to the first uninitialized element of a streaming array.
|
|
/// PARAMS:
|
|
/// streamedRecordings - Streaming array to add to
|
|
/// newAnim- STRING of anim name to add
|
|
/// RETURNS:
|
|
/// TRUE if the anim string was successfully added, FALSE otherwise (the array was full)
|
|
FUNC BOOL ADD_STREAMED_VEHICLE_RECORDING(STREAMED_VEHICLE_RECORDING &streamedRecordings[], INT iNewRecording, STRING newRecording)
|
|
IF NOT DOES_VEHICLE_RECORDING_FILE_EXIST_IN_CDIMAGE(iNewRecording, newRecording)
|
|
TEXT_LABEL_63 tlTempAssert = "\n\nVehicle recording doesn't exist: "
|
|
tlTempAssert += iNewRecording
|
|
tlTempAssert += " in "
|
|
tlTempAssert += newRecording
|
|
SCRIPT_ASSERT(tlTempAssert)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
INT iRecordingIndex
|
|
REPEAT COUNT_OF(streamedRecordings) iRecordingIndex
|
|
IF NOT IS_STRING_NULL(streamedRecordings[iRecordingIndex].thisRecording)
|
|
IF ARE_STRINGS_EQUAL(streamedRecordings[iRecordingIndex].thisRecording, newRecording)
|
|
AND streamedRecordings[iRecordingIndex].thisRecordingIndex = iNewRecording
|
|
DEBUG_MESSAGE("ADD_STREAMED_VEHICLE_RECORDING returning FALSE, recording already in the index")
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
INT recordingIndex = GET_EMPTY_STREAMED_VEHICLE_RECORDING(streamedRecordings)
|
|
IF recordingIndex < 0 OR recordingIndex >= COUNT_OF(streamedRecordings)
|
|
DEBUG_MESSAGE("ADD_STREAMED_VEHICLE_RECORDING returning FALSE, couldn't find empty array index")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF iNewRecording < 0
|
|
DEBUG_MESSAGE("ADD_STREAMED_VEHICLE_RECORDING returning FALSE, iNewRecording is less than 0")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
streamedRecordings[recordingIndex].thisRecording = newRecording
|
|
streamedRecordings[recordingIndex].thisRecordingIndex = iNewRecording
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Requests all initialized anims in a streaming array
|
|
/// PARAMS:
|
|
/// streamedRecordings - Streaming array to request
|
|
PROC REQUEST_ALL_VEHICLE_RECORDINGS(STREAMED_VEHICLE_RECORDING &streamedRecordings[])
|
|
INT recordingIndex
|
|
REPEAT COUNT_OF(streamedRecordings) recordingIndex
|
|
IF NOT IS_STRING_NULL(streamedRecordings[recordingIndex].thisRecording)
|
|
REQUEST_VEHICLE_RECORDING(streamedRecordings[recordingIndex].thisRecordingIndex, streamedRecordings[recordingIndex].thisRecording)
|
|
#IF IS_DEBUG_BUILD
|
|
DEBUG_MESSAGE("REQUESTING RECORDING ", streamedRecordings[recordingIndex].thisRecording, " index ", GET_STRING_FROM_INT(streamedRecordings[recordingIndex].thisRecordingIndex))
|
|
#ENDIF // IS_DEBUG_BUILD
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Checks to see if all anims in a streaming array are in memory
|
|
/// PARAMS:
|
|
/// streamedRecordings - Streaming array to check
|
|
/// RETURNS:
|
|
/// TRUE if every initialized element in a streaming array is in memory, FALSE if at least one is not in memory
|
|
FUNC BOOL ARE_VEHICLE_RECORDINGS_STREAMED(STREAMED_VEHICLE_RECORDING &streamedRecordings[])
|
|
INT recordingIndex
|
|
REPEAT COUNT_OF(streamedRecordings) recordingIndex
|
|
IF NOT IS_STRING_NULL(streamedRecordings[recordingIndex].thisRecording)
|
|
IF NOT HAS_VEHICLE_RECORDING_BEEN_LOADED(streamedRecordings[recordingIndex].thisRecordingIndex, streamedRecordings[recordingIndex].thisRecording)
|
|
#IF IS_DEBUG_BUILD
|
|
IF NOT DOES_VEHICLE_RECORDING_FILE_EXIST(streamedRecordings[recordingIndex].thisRecordingIndex, streamedRecordings[recordingIndex].thisRecording)
|
|
DEBUG_MESSAGE("Vehicle recording doesn't exist ", streamedRecordings[recordingIndex].thisRecording, " index ", GET_STRING_FROM_INT(streamedRecordings[recordingIndex].thisRecordingIndex))
|
|
ELSE
|
|
DEBUG_MESSAGE("Waiting to stream recording ", streamedRecordings[recordingIndex].thisRecording, " index ", GET_STRING_FROM_INT(streamedRecordings[recordingIndex].thisRecordingIndex))
|
|
ENDIF
|
|
#ENDIF // IS_DEBUG_BUILD
|
|
RETURN FALSE
|
|
ELSE
|
|
DEBUG_MESSAGE("STREAMED IN RECORDING ", streamedRecordings[recordingIndex].thisRecording)
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Removes a streamed vehicle recording
|
|
/// PARAMS:
|
|
/// streamedRecordings - Streaming array to check
|
|
PROC REMOVE_STREAMED_VEHICLE_RECORDING(STREAMED_VEHICLE_RECORDING& streamedRecording)
|
|
IF NOT IS_STRING_NULL(streamedRecording.thisRecording)
|
|
REMOVE_VEHICLE_RECORDING(streamedRecording.thisRecordingIndex, streamedRecording.thisRecording)
|
|
streamedRecording.thisRecording = NULL
|
|
streamedRecording.thisRecordingIndex = -1
|
|
#IF IS_DEBUG_BUILD
|
|
DEBUG_MESSAGE("Removed vehicle recording ", streamedRecording.thisRecording, " index ", GET_STRING_FROM_INT(streamedRecording.thisRecordingIndex))
|
|
#ENDIF // IS_DEBUG_BUILD
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Removes a streamed vehicle recording from memory and clears all recoridng references from the array
|
|
/// PARAMS:
|
|
/// streamedRecordings - Streaming array to check
|
|
PROC SET_STREAMED_VEHICLE_RECORDING_AS_NO_LONGER_NEEDED(STREAMED_VEHICLE_RECORDING &streamedRecordings[], INT iRecordingIndex, STRING sRecording)
|
|
INT recordingIndex
|
|
REPEAT COUNT_OF(streamedRecordings) recordingIndex
|
|
IF NOT IS_STRING_NULL(streamedRecordings[recordingIndex].thisRecording)
|
|
IF streamedRecordings[recordingIndex].thisRecordingIndex = iRecordingIndex
|
|
AND ARE_STRINGS_EQUAL(streamedRecordings[recordingIndex].thisRecording, sRecording)
|
|
REMOVE_STREAMED_VEHICLE_RECORDING(streamedRecordings[recordingIndex])
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDPROC
|
|
*/
|
|
|
|
/// PURPOSE:
|
|
/// Draws a vector from V1 to V2, and takes the flat heading of that vector.
|
|
/// PARAMS:
|
|
/// V1 -
|
|
/// V2 -
|
|
/// RETURNS:
|
|
///
|
|
FUNC FLOAT GET_HEADING_BETWEEN_VECTORS(VECTOR V1, VECTOR V2)
|
|
RETURN GET_HEADING_FROM_VECTOR_2D(V2.x-V1.x,V2.y-V1.y)
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Prints a help message once if the bit in the bitfieldis not set, and sets the passed in bit so I won't be set again
|
|
/// PARAMS:
|
|
/// msg - message to print
|
|
/// bitField - bitfield that stores the permanent print status
|
|
/// bit - bit to check
|
|
PROC PRINT_HELP_ONCE(STRING msg, INT &bitField, ENUM_TO_INT bit, BOOL bForever = FALSE)
|
|
IF IS_BITMASK_SET(ENUM_TO_INT(bitField), ENUM_TO_INT(bit))
|
|
EXIT
|
|
ENDIF
|
|
IF NOT bForever
|
|
PRINT_HELP(msg)
|
|
ELSE
|
|
PRINT_HELP_FOREVER(msg)
|
|
ENDIF
|
|
SET_BITMASK(bitField, ENUM_TO_INT(bit))
|
|
ENDPROC
|
|
|
|
/// bit - bit to check
|
|
PROC PRINT_HELP_ONCE_AT_WORLD_POSITION(STRING msg, INT &bitField, ENUM_TO_INT bit, VECTOR vWorldPosition, eARROW_DIRECTION iArrowPosition = 0, BOOL bForever = FALSE)
|
|
|
|
BOOL bUpdatePosition
|
|
IF IS_BITMASK_SET(ENUM_TO_INT(bitField), ENUM_TO_INT(bit))
|
|
IF NOT IS_THIS_HELP_MESSAGE_BEING_DISPLAYED(msg)
|
|
EXIT
|
|
ENDIF
|
|
bUpdatePosition = TRUE
|
|
ENDIF
|
|
IF NOT bUpdatePosition
|
|
HELP_AT_LOCATION(msg, vWorldPosition, iArrowPosition, PICK_INT(bForever, FLOATING_HELP_PRINT_FOREVER, DEFAULT_GOD_TEXT_TIME), FLOATING_HELP_FIND_NEXT_FREE_SLOT)
|
|
SET_BITMASK(bitField, ENUM_TO_INT(bit))
|
|
ENDIF
|
|
UPDATE_FLOATING_HELP_WORLD_POSITION(msg, vWorldPosition)
|
|
ENDPROC
|
|
|
|
/// bit - bit to check
|
|
PROC PRINT_HELP_ONCE_AT_ENTITY(STRING msg, INT &bitField, ENUM_TO_INT bit, ENTITY_INDEX eEntityPrint, eARROW_DIRECTION iArrowPosition = 0, BOOL bForever = FALSE)
|
|
|
|
BOOL bUpdatePosition
|
|
IF IS_BITMASK_SET(ENUM_TO_INT(bitField), ENUM_TO_INT(bit))
|
|
IF NOT IS_THIS_HELP_MESSAGE_BEING_DISPLAYED(msg)
|
|
EXIT
|
|
ENDIF
|
|
bUpdatePosition = TRUE
|
|
ENDIF
|
|
IF NOT bUpdatePosition
|
|
HELP_AT_ENTITY(msg, eEntityPrint, iArrowPosition, PICK_INT(bForever, FLOATING_HELP_PRINT_FOREVER, DEFAULT_GOD_TEXT_TIME), FLOATING_HELP_FIND_NEXT_FREE_SLOT)
|
|
SET_BITMASK(bitField, ENUM_TO_INT(bit))
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// bit - bit to check
|
|
PROC PRINT_HELP_ONCE_AT_ENTITY_OFFSET(STRING msg, INT &bitField, ENUM_TO_INT bit, ENTITY_INDEX eEntityPrint, VECTOR vOffsetPosition, eARROW_DIRECTION iArrowPosition = 0, BOOL bForever = FALSE)
|
|
|
|
BOOL bUpdatePosition
|
|
IF IS_BITMASK_SET(ENUM_TO_INT(bitField), ENUM_TO_INT(bit))
|
|
IF NOT IS_THIS_HELP_MESSAGE_BEING_DISPLAYED(msg)
|
|
EXIT
|
|
ENDIF
|
|
bUpdatePosition = TRUE
|
|
ENDIF
|
|
IF NOT bUpdatePosition
|
|
HELP_AT_ENTITY_OFFSET(msg, eEntityPrint, vOffsetPosition, iArrowPosition, PICK_INT(bForever, FLOATING_HELP_PRINT_FOREVER, DEFAULT_GOD_TEXT_TIME), FLOATING_HELP_FIND_NEXT_FREE_SLOT)
|
|
SET_BITMASK(bitField, ENUM_TO_INT(bit))
|
|
ENDIF
|
|
UPDATE_FLOATING_HELP_ENTITY_OFFSET(msg, eEntityPrint, vOffsetPosition)
|
|
ENDPROC
|
|
|
|
|
|
/// bit - bit to check
|
|
PROC PRINT_HELP_ONCE_AT_SCREEN_POSITION(STRING msg, INT &bitField, ENUM_TO_INT bit, FLOAT fScreenX, FLOAT fScreenY, eARROW_DIRECTION iArrowPosition = 0, BOOL bForever = FALSE)
|
|
BOOL bUpdatePosition
|
|
IF IS_BITMASK_SET(ENUM_TO_INT(bitField), ENUM_TO_INT(bit))
|
|
IF NOT IS_THIS_HELP_MESSAGE_BEING_DISPLAYED(msg)
|
|
EXIT
|
|
ENDIF
|
|
bUpdatePosition = TRUE
|
|
ENDIF
|
|
IF NOT bUpdatePosition
|
|
HELP_AT_SCREEN_LOCATION(msg, fScreenX, fScreenY, iArrowPosition, PICK_INT(bForever, FLOATING_HELP_PRINT_FOREVER, DEFAULT_GOD_TEXT_TIME), FLOATING_HELP_FIND_NEXT_FREE_SLOT)
|
|
SET_BITMASK(bitField, ENUM_TO_INT(bit))
|
|
ENDIF
|
|
UPDATE_FLOATING_HELP_SCREEN_POSITION(msg, fScreenX, fScreenY)
|
|
ENDPROC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Prints an objective once if the bit in the bitfield is not set, and sets the passed in bit so I won't be set again
|
|
/// PARAMS:
|
|
/// msg - message to print
|
|
// Duration is an INT in milliseconds (1000 = 1 sec).
|
|
// Colour is an INT and should correspond to the person that speaks.
|
|
//PARAM NOTES: Colour 0 = White
|
|
// 1 = Red
|
|
// 2 = Green
|
|
// 3 = Blue
|
|
// 4 = Purple
|
|
// 5 = Yellow
|
|
// 6 = Black
|
|
/// bitField - bitfield that stores the permanent print status
|
|
/// bit - bit to check
|
|
PROC PRINT_NOW_ONCE(STRING msg, INT Duration, INT Colour, INT &bitField, ENUM_TO_INT bit)
|
|
IF IS_BITMASK_SET(ENUM_TO_INT(bitField), ENUM_TO_INT(bit))
|
|
EXIT
|
|
ENDIF
|
|
PRINT_NOW(msg, Duration, Colour)
|
|
SET_BITMASK(bitField, ENUM_TO_INT(bit))
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Extract the minutes and seconds from a struct timer
|
|
PROC GET_TIMER_TIME(structTimer myTimer, INT& hours, INT& minutes, INT& seconds)
|
|
FLOAT totalSeconds
|
|
hours = 0
|
|
totalSeconds = GET_TIMER_IN_SECONDS(myTimer)
|
|
minutes = FLOOR(totalSeconds / 60)
|
|
seconds = FLOOR(totalSeconds - (minutes * 60))
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// To check if there are alive entities in an array
|
|
/// PARAMS:
|
|
/// myEntities - an array of entities
|
|
/// RETURNS:
|
|
/// BOOL - True if any entities are alive, False if all entities are dead
|
|
FUNC BOOL IS_ANY_ENTITY_ALIVE(ENTITY_INDEX& myEntities[])
|
|
INT idx
|
|
REPEAT COUNT_OF(myEntities) idx
|
|
IF NOT IS_ENTITY_DEAD(myEntities[idx])
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDREPEAT
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/* duplicate function - already in script_ped.sch
|
|
/// PURPOSE:
|
|
/// To get the distance between two entities
|
|
/// PARAMS:
|
|
/// ENTITY_INDEX ent1 - First ped
|
|
/// ENTITY_INDEX ent2 - Second ped
|
|
/// RETURNS:
|
|
/// FLOAT - Distance between entities, -1 if any entity is invalid
|
|
FUNC FLOAT GET_DISTANCE_BETWEEN_ENTITIES(ENTITY_INDEX ent1, ENTITY_INDEX ent2, BOOL bCheck3d = TRUE)
|
|
|
|
IF IS_ENTITY_DEAD(ent1) OR IS_ENTITY_DEAD(ent2)
|
|
SCRIPT_ASSERT("GET_DISTANCE_BETWEEN_ENTITIES: Invalid entity passed in")
|
|
RETURN -1.0
|
|
ELSE
|
|
RETURN GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(ent1), GET_ENTITY_COORDS(ent2), bCheck3d)
|
|
ENDIF
|
|
|
|
ENDFUNC
|
|
*/
|
|
|
|
/// PURPOSE:
|
|
/// To find the closest location to the current vector
|
|
/// PARAMS:
|
|
/// VECTOR vArray[] - Array of locations
|
|
/// VECTOR myCurLocation - The current location we're comparing against
|
|
/// RETURNS:
|
|
/// INT - the index of the closest location
|
|
FUNC INT FIND_CLOSEST_LOCATION_INDEX(VECTOR& vArray[], VECTOR myCurLocation, FLOAT minDistance = 0.0)
|
|
INT idx
|
|
INT closestIndex = 0
|
|
FLOAT fClosestDist = 1000000000 //VDIST2(vArray[0], myCurLocation) //assumes first locaiton is valid
|
|
FLOAT fDist
|
|
|
|
REPEAT COUNT_OF(vArray) idx
|
|
IF NOT IS_VECTOR_ZERO(vArray[idx])
|
|
fDist = VDIST2(vArray[idx], myCurLocation)
|
|
IF fDist < fClosestDist AND fDist > minDistance
|
|
fClosestDist = fDist
|
|
closestIndex = idx
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
IF closestIndex = -1
|
|
SCRIPT_ASSERT("FIND_CLOSEST_LOCATION_INDEX returning -1")
|
|
ENDIF
|
|
|
|
RETURN closestIndex
|
|
ENDFUNC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// To get the distance between an entity and a vector
|
|
/// PARAMS:
|
|
/// ENTITY_INDEX ent1 - First entity
|
|
/// VECTOR - vLocation
|
|
/// RETURNS:
|
|
/// FLOAT - Distance between an entity and vector, -1 if the entity is invalid
|
|
FUNC FLOAT GET_ENTITY_DISTANCE_FROM_LOCATION(ENTITY_INDEX ped1, VECTOR vLocation, BOOL bCheck3d = TRUE)
|
|
|
|
IF IS_ENTITY_DEAD(ped1)
|
|
PRINTLN("GET_ENTITY_DISTANCE_FROM_LOCATION: Invalid ped passed in")
|
|
RETURN -1.0
|
|
ELSE
|
|
RETURN GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(ped1),vLocation, bCheck3d)
|
|
ENDIF
|
|
|
|
ENDFUNC
|
|
|
|
/// RETURNS:
|
|
/// INT - the index of the closest location, -1 if no valid location found
|
|
FUNC INT FIND_CLOSEST_ENTITY_INDEX(ENTITY_INDEX& eArray[], VECTOR myCurLocation)
|
|
INT idx
|
|
INT closestIndex = -1
|
|
FLOAT fClosestDist = -1.0
|
|
|
|
VECTOR vTempCoord
|
|
FLOAT fCurDist
|
|
|
|
REPEAT COUNT_OF(eArray) idx
|
|
IF NOT IS_ENTITY_DEAD(eArray[idx])
|
|
vTempCoord = GET_ENTITY_COORDS(eArray[idx])
|
|
fCurDist = VDIST2(vTempCoord, myCurLocation)
|
|
|
|
IF closestIndex = -1
|
|
fClosestDist = fCurDist
|
|
closestIndex = idx
|
|
ELIF fCurDist < fClosestDist
|
|
fClosestDist = fCurDist
|
|
closestIndex = idx
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
// IF closestIndex = -1
|
|
// SCRIPT_ASSERT("FIND_CLOSEST_ENTITY_INDEX returning -1")
|
|
// ENDIF
|
|
|
|
RETURN closestIndex
|
|
ENDFUNC
|
|
|
|
FUNC FLOAT GET_PLAYER_DISTANCE_FROM_ENTITY(ENTITY_INDEX myObject, BOOL bCheck3d = TRUE)
|
|
RETURN GET_DISTANCE_BETWEEN_ENTITIES(GET_PLAYER_PED(GET_PLAYER_INDEX()), myObject, bCheck3d)
|
|
ENDFUNC
|
|
|
|
|
|
FUNC FLOAT GET_PLAYER_DISTANCE_FROM_LOCATION(VECTOR vLocation, BOOL bCheck3d = TRUE)
|
|
RETURN GET_ENTITY_DISTANCE_FROM_LOCATION(GET_PLAYER_PED(GET_PLAYER_INDEX()), vLocation, bCheck3d)
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Fly a plane level at desired speed indefinately
|
|
/// PARAMS:
|
|
/// Plane - The plane to fly in auto-pilot
|
|
/// fSpeed - The speed to fly the plane in auto-pilot
|
|
/// bRotInterp - Whether or not to interpolate the plane rotating
|
|
PROC PLANE_AUTOPILOT(VEHICLE_INDEX Plane, FLOAT fSpeed, BOOL bRotInterp, FLOAT xRot = 0.0, FLOAT yRot = 0.0)
|
|
|
|
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_EXIT)
|
|
|
|
// Error checking.
|
|
IF IS_ENTITY_DEAD(Plane)
|
|
DEBUG_MESSAGE("PLANE_AUTOPILOT: Plane not alive, exiting!")
|
|
EXIT
|
|
ENDIF
|
|
|
|
// TODO: May want to add a check to see if vehicle is a plane.
|
|
|
|
// If Plane speed is below desired speed change it.
|
|
IF (GET_ENTITY_SPEED(Plane) < fSpeed)
|
|
SET_VEHICLE_FORWARD_SPEED(Plane, fSpeed)
|
|
ENDIF
|
|
|
|
// If Plane isn't level, rotate it (interp if desired).
|
|
VECTOR vRot = GET_ENTITY_ROTATION(Plane)
|
|
BOOL bPlaneRotated = FALSE
|
|
IF bRotInterp
|
|
FLOAT fRotInterp = GET_FRAME_TIME() * 45.0
|
|
IF (vRot.x < -fRotInterp)
|
|
bPlaneRotated = TRUE
|
|
vRot.x += fRotInterp
|
|
ELIF (vRot.x < xRot)
|
|
bPlaneRotated = TRUE
|
|
vRot.x = xRot
|
|
ELIF (vRot.x > fRotInterp)
|
|
bPlaneRotated = TRUE
|
|
vRot.x -= fRotInterp
|
|
ELIF (vRot.x > xRot)
|
|
bPlaneRotated = TRUE
|
|
vRot.x = xRot
|
|
ENDIF
|
|
IF (vRot.y < -fRotInterp)
|
|
bPlaneRotated = TRUE
|
|
vRot.y += fRotInterp
|
|
ELIF (vRot.y < yRot)
|
|
bPlaneRotated = TRUE
|
|
vRot.y = yRot
|
|
ELIF (vRot.y > fRotInterp)
|
|
bPlaneRotated = TRUE
|
|
vRot.y -= fRotInterp
|
|
ELIF (vRot.y > yRot)
|
|
bPlaneRotated = TRUE
|
|
vRot.y = yRot
|
|
ENDIF
|
|
ELSE
|
|
IF (vRot.x <> xRot)
|
|
bPlaneRotated = TRUE
|
|
vRot.x = xRot
|
|
ENDIF
|
|
IF (vRot.y <> yRot)
|
|
bPlaneRotated = TRUE
|
|
vRot.y = yRot
|
|
ENDIF
|
|
ENDIF
|
|
IF bPlaneRotated
|
|
SET_ENTITY_ROTATION(Plane, vRot)
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Fly a plane circling at desired speed indefinately
|
|
/// PARAMS:
|
|
/// Plane - The plane to fly in auto-circle
|
|
/// fSpeed - The speed to fly the plane in auto-circle
|
|
/// bRotInterp - Whether or not to interpolate the plane rotating
|
|
PROC PLANE_AUTOCIRCLE(VEHICLE_INDEX Plane, FLOAT fSpeed, BOOL bRotInterp)
|
|
|
|
// Error checking.
|
|
IF IS_ENTITY_DEAD(Plane)
|
|
DEBUG_MESSAGE("PLANE_AUTOCIRCLE: Plane not alive, exiting!")
|
|
EXIT
|
|
ENDIF
|
|
|
|
// TODO: May want to add a check to see if vehicle is a plane.
|
|
|
|
// If Plane speed is below desired speed change it.
|
|
IF (GET_ENTITY_SPEED(Plane) < fSpeed)
|
|
SET_VEHICLE_FORWARD_SPEED(Plane, fSpeed)
|
|
ENDIF
|
|
|
|
// If Plane isn't circling, rotate it (interp if desired).
|
|
VECTOR vRot = GET_ENTITY_ROTATION(Plane)
|
|
BOOL bPlaneRotated = FALSE
|
|
FLOAT fPitch = 5.0
|
|
FLOAT fRoll = 45.0
|
|
IF bRotInterp
|
|
FLOAT fRotInterp = GET_FRAME_TIME() * 45.0
|
|
IF (vRot.x < (fPitch - fRotInterp))
|
|
bPlaneRotated = TRUE
|
|
vRot.x += fRotInterp
|
|
ELIF (vRot.x < fPitch)
|
|
bPlaneRotated = TRUE
|
|
vRot.x = fPitch
|
|
ELIF (vRot.x > (fPitch + fRotInterp))
|
|
bPlaneRotated = TRUE
|
|
vRot.x -= fRotInterp
|
|
ELIF (vRot.x > fPitch)
|
|
bPlaneRotated = TRUE
|
|
vRot.x = fPitch
|
|
ENDIF
|
|
IF (vRot.y < (fRoll - fRotInterp))
|
|
bPlaneRotated = TRUE
|
|
vRot.y += fRotInterp
|
|
ELIF (vRot.y < fRoll)
|
|
bPlaneRotated = TRUE
|
|
vRot.y = fRoll
|
|
ELIF (vRot.y > (fRoll + fRotInterp))
|
|
bPlaneRotated = TRUE
|
|
vRot.y -= fRotInterp
|
|
ELIF (vRot.y > fRoll)
|
|
bPlaneRotated = TRUE
|
|
vRot.y = fRoll
|
|
ENDIF
|
|
ELSE
|
|
IF (vRot.x <> fPitch)
|
|
bPlaneRotated = TRUE
|
|
vRot.x = fPitch
|
|
ENDIF
|
|
IF (vRot.y <> fRoll)
|
|
bPlaneRotated = TRUE
|
|
vRot.y = fRoll
|
|
ENDIF
|
|
ENDIF
|
|
IF bPlaneRotated
|
|
SET_ENTITY_ROTATION(Plane, vRot)
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Snaps a position to the ground
|
|
/// PARAMS:
|
|
/// vSnappedPos - position to snap to the ground
|
|
/// fAddHeight - additional height to add after the snap, defaults to 0.0
|
|
/// RETURNS:
|
|
/// TRUE if the ground z was found, FALSE if it wasn't found and vector didn't change
|
|
FUNC BOOL SNAP_3D_COORD_TO_GROUND(VECTOR& vSnappedPos, FLOAT fAddHeight = 0.0)
|
|
FLOAT fGroundZ = 0.0
|
|
IF GET_GROUND_Z_FOR_3D_COORD(vSnappedPos, fGroundZ)
|
|
vSnappedPos.z = fGroundZ
|
|
vSnappedPos.z += fAddHeight
|
|
RETURN TRUE
|
|
ENDIF
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Given an array of numbers, gets a random number inside a range that's not already inside of the array.
|
|
/// RETURNS:
|
|
/// A number if found, -1 otherwise.
|
|
FUNC INT GET_RANDOM_INT_IN_RANGE_NOT_IN_ARRAY(INT & iArray[], INT iArraySize, INT intMin, INT intMax)
|
|
BOOL bAlreadyPresent = TRUE
|
|
INT index, iRuns = 0, iResult
|
|
|
|
WHILE bAlreadyPresent AND iRuns < 50
|
|
bAlreadyPresent = FALSE
|
|
iResult = (GET_RANDOM_INT_IN_RANGE(0, 50000) % (intMax - intMin)) + intMin
|
|
PRINTLN("Trying number ", iResult)
|
|
|
|
FOR index = 0 TO iArraySize - 1
|
|
IF (iArray[index] = iResult)
|
|
bAlreadyPresent = TRUE
|
|
index = 999999
|
|
ENDIF
|
|
ENDFOR
|
|
|
|
iRuns += 1
|
|
ENDWHILE
|
|
|
|
IF iRuns = 50
|
|
RETURN -1
|
|
ENDIF
|
|
|
|
RETURN iResult
|
|
ENDFUNC
|
|
|
|
|
|
ENUM COUNTDOWN_UI_FLAGS
|
|
CNTDWN_UI_Played_3 = BIT0,
|
|
CNTDWN_UI_Played_2 = BIT1,
|
|
CNTDWN_UI_Played_1 = BIT2,
|
|
CNTDWN_UI_Played_Go = BIT3,
|
|
CNTDWN_UI_Played_Race_Go = BIT4
|
|
ENDENUM
|
|
|
|
STRUCT COUNTDOWN_UI
|
|
SCALEFORM_INDEX uiCountdown
|
|
INT iBitFlags
|
|
structTimer CountdownTimer
|
|
ENDSTRUCT
|
|
|
|
/// PURPOSE:
|
|
/// Provides the scripter with a handle to the countdown UI.
|
|
PROC REQUEST_MINIGAME_COUNTDOWN_UI(COUNTDOWN_UI & uiToRequest)
|
|
uiToRequest.uiCountdown = REQUEST_SCALEFORM_MOVIE("COUNTDOWN")
|
|
REQUEST_SCRIPT_AUDIO_BANK("HUD_321_GO")
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Lets the scripter know if the countdown UI is ready for use. Should be done in streaming checks.
|
|
FUNC BOOL HAS_MINIGAME_COUNTDOWN_UI_LOADED(COUNTDOWN_UI & uiToCheck)
|
|
RETURN (HAS_SCALEFORM_MOVIE_LOADED(uiToCheck.uiCountdown) AND REQUEST_SCRIPT_AUDIO_BANK("HUD_321_GO"))
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Clears the scritpers handle to the countdown UI.
|
|
PROC RELEASE_MINIGAME_COUNTDOWN_UI(COUNTDOWN_UI & uiToRelease)
|
|
SET_SCALEFORM_MOVIE_AS_NO_LONGER_NEEDED(uiToRelease.uiCountdown)
|
|
RELEASE_SCRIPT_AUDIO_BANK()
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Private minigame countdown UI func.
|
|
PROC SET_MINIGAME_COUNTDOWN_UI_NUMBER(COUNTDOWN_UI & uiToUpdate, INT iNum)
|
|
INT iR, iG, iB, iA
|
|
GET_HUD_COLOUR(HUD_COLOUR_YELLOW, iR, iG, iB, iA)
|
|
|
|
BEGIN_SCALEFORM_MOVIE_METHOD(uiToUpdate.uiCountdown, "SET_MESSAGE")
|
|
SET_COLOUR_OF_NEXT_TEXT_COMPONENT(INT_TO_ENUM(HUD_COLOURS, -1))
|
|
BEGIN_TEXT_COMMAND_SCALEFORM_STRING("NUMBER")
|
|
ADD_TEXT_COMPONENT_INTEGER(ABSI(iNum))
|
|
END_TEXT_COMMAND_SCALEFORM_STRING()
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(iR)
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(iG)
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(iB)
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_BOOL(TRUE)
|
|
END_SCALEFORM_MOVIE_METHOD()
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Display an on-screen countdown UI
|
|
/// PARAMS:
|
|
/// uiToUpdate - Your countdown UI struct.
|
|
/// iCountdownLength - Between 0 and 3
|
|
/// bLoudVersion - Use the sounds in the HUD_MINIGAME_SOUNDSET or the ...
|
|
/// RETURNS:
|
|
/// TRUE one second after the countdown is done.
|
|
FUNC BOOL UPDATE_MINIGAME_COUNTDOWN_UI(COUNTDOWN_UI & uiToUpdate, BOOL bWaitExtraSec = TRUE, BOOL bSkipOnButtonPress = FALSE, BOOL bCancelTimerAtEnd = TRUE, INT iCountdownLength = 3, BOOL bLoudVersionSounds = TRUE, BOOL bTriggerGoQuick = FALSE, BOOL bIsRaceCreator = FALSE)
|
|
// Make sure we have a timer.
|
|
|
|
IF bIsRaceCreator
|
|
FORCE_TIMER_TO_USE_GAME_TIME(uiToUpdate.CountdownTimer, TRUE)
|
|
ENDIF
|
|
|
|
IF NOT IS_TIMER_STARTED(uiToUpdate.CountdownTimer)
|
|
PRINTLN("[TimerBroken] RESTARTING TIMER")
|
|
RESTART_TIMER_NOW(uiToUpdate.CountdownTimer)
|
|
ENDIF
|
|
|
|
// Always draw the movie.
|
|
SET_SCRIPT_GFX_DRAW_ORDER(GFX_ORDER_BEFORE_HUD)
|
|
DRAW_SCALEFORM_MOVIE(uiToUpdate.uiCountdown, 0.5, 0.5, 1.0, 1.0, 255, 255, 255, 100)
|
|
|
|
//Make sure Countdown Length is within limits
|
|
IF iCountdownLength > 3
|
|
iCountdownLength = 3
|
|
ELIF iCountdownLength < 0
|
|
iCountdownLength = 0
|
|
ENDIF
|
|
|
|
//select sfx
|
|
STRING sCountSound, sGoSound, sSoundSet
|
|
IF bLoudVersionSounds
|
|
sCountSound = "3_2_1"
|
|
sGoSound = "GO"
|
|
sSoundSet = "HUD_MINI_GAME_SOUNDSET"
|
|
ELSE
|
|
sCountSound = "3_2_1"
|
|
sGoSound = "GO"
|
|
sSoundSet = "321_GO_LOW_VOL_SOUNDSET"
|
|
ENDIF
|
|
|
|
// Get the timer values.
|
|
FLOAT fScratchTime
|
|
INT iTimerVal
|
|
|
|
IF bisRaceCreator
|
|
IF IS_TIMER_STARTED(uiToUpdate.CountdownTimer)
|
|
IF IS_TIMER_PAUSED(uiToUpdate.CountdownTimer)
|
|
PRINTLN("[TimerBroken] IS_TIMER_PAUSED : YES" )
|
|
fScratchTime = uiToUpdate.CountdownTimer.PauseTime
|
|
ELSE
|
|
fScratchTime = (GetGameTimerSeconds(TRUE) - uiToUpdate.CountdownTimer.StartTime)
|
|
IF fScratchTime < 0
|
|
PRINTLN("[TimerBroken] Timer is fucked, rebooting it")
|
|
fScratchTime = 0
|
|
CANCEL_TIMER(uiToUpdate.CountdownTimer)
|
|
|
|
IF IS_BITMASK_AS_ENUM_SET(uiToUpdate.iBitFlags, CNTDWN_UI_Played_3)
|
|
SET_BITMASK_AS_ENUM(uiToUpdate.iBitFlags, CNTDWN_UI_Played_Go)
|
|
INT iR, iG, iB, iA
|
|
GET_HUD_COLOUR(HUD_COLOUR_GREEN, iR, iG, iB, iA)
|
|
BEGIN_SCALEFORM_MOVIE_METHOD(uiToUpdate.uiCountdown, "SET_MESSAGE")
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_STRING("CNTDWN_GO")
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(iR)
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(iG)
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(iB)
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_BOOL(TRUE)
|
|
END_SCALEFORM_MOVIE_METHOD()
|
|
|
|
PRINTLN("[TimerBroken] Failsafe Bail" )
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
RESTART_TIMER_NOW(uiToUpdate.CountdownTimer)
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
PRINTLN("[TimerBroken] IS_TIMER_STARTED : NO" )
|
|
fScratchTime = uiToUpdate.CountdownTimer.StartTime
|
|
ENDIF
|
|
|
|
PRINTLN("[TimerBroken] fScratchTime ", fScratchTime)
|
|
|
|
iTimerVal = FLOOR(fScratchTime)
|
|
ELSE
|
|
iTimerVal = FLOOR(GET_TIMER_IN_SECONDS(uiToUpdate.CountdownTimer))
|
|
ENDIF
|
|
|
|
INT iSeconds = iTimerVal - iCountdownLength
|
|
BOOL bForceEnd = FALSE
|
|
|
|
PRINTLN("[TimerBroken] UPDATE_MINIGAME_COUNTDOWN_UI iTimerVal = ", iTimerVal, ", iSeconds = ", iSeconds, " uiToUpdate.CountdownTimer.StartTime = ", uiToUpdate.CountdownTimer.StartTime )
|
|
|
|
IF NOT IS_BITMASK_AS_ENUM_SET(uiToUpdate.iBitFlags, CNTDWN_UI_Played_Go)
|
|
// See if we're due to update.
|
|
IF (iSeconds >= -3) AND NOT IS_BITMASK_AS_ENUM_SET(uiToUpdate.iBitFlags, CNTDWN_UI_Played_3)
|
|
SET_BITMASK_AS_ENUM(uiToUpdate.iBitFlags, CNTDWN_UI_Played_3)
|
|
PRINTLN("Playing SFX for NUMBER 3")
|
|
PLAY_SOUND_FRONTEND(-1, sCountSound, sSoundSet)
|
|
SET_MINIGAME_COUNTDOWN_UI_NUMBER(uiToUpdate, iSeconds)
|
|
|
|
ELIF (iSeconds >= -2) AND NOT IS_BITMASK_AS_ENUM_SET(uiToUpdate.iBitFlags, CNTDWN_UI_Played_2)
|
|
SET_BITMASK_AS_ENUM(uiToUpdate.iBitFlags, CNTDWN_UI_Played_2)
|
|
PRINTLN("Playing SFX for NUMBER 2")
|
|
PLAY_SOUND_FRONTEND(-1, sCountSound, sSoundSet)
|
|
SET_MINIGAME_COUNTDOWN_UI_NUMBER(uiToUpdate, iSeconds)
|
|
|
|
ELIF (iSeconds >= -1) AND NOT IS_BITMASK_AS_ENUM_SET(uiToUpdate.iBitFlags, CNTDWN_UI_Played_1)
|
|
SET_BITMASK_AS_ENUM(uiToUpdate.iBitFlags, CNTDWN_UI_Played_1)
|
|
PRINTLN("Playing SFX for NUMBER 1")
|
|
PLAY_SOUND_FRONTEND(-1, sCountSound, sSoundSet)
|
|
SET_MINIGAME_COUNTDOWN_UI_NUMBER(uiToUpdate, iSeconds)
|
|
|
|
ELIF (iSeconds >= -1) AND NOT IS_BITMASK_AS_ENUM_SET(uiToUpdate.iBitFlags, CNTDWN_UI_Played_Race_Go)
|
|
IF ABSF(GET_TIMER_IN_SECONDS(uiToUpdate.CountdownTimer) - iCountdownLength) < 0.65 //countdown timer is going BACKWARDS!
|
|
IF bLoudVersionSounds OR bTriggerGoQuick
|
|
PRINTLN("Playing SFX for RACE GO")
|
|
SET_BITMASK_AS_ENUM(uiToUpdate.iBitFlags, CNTDWN_UI_Played_Race_Go)
|
|
PLAY_SOUND_FRONTEND(-1, sGoSound, sSoundSet)
|
|
ENDIF
|
|
ENDIF
|
|
ELIF (iSeconds >= 0) AND NOT IS_BITMASK_AS_ENUM_SET(uiToUpdate.iBitFlags, CNTDWN_UI_Played_Go)
|
|
IF NOT bLoudVersionSounds AND NOT bTriggerGoQuick
|
|
// These get played a but later, for some reason... Not going to change the architecture...
|
|
PRINTLN("Playing SFX for GO")
|
|
PLAY_SOUND_FRONTEND(-1, sGoSound, sSoundSet)
|
|
ENDIF
|
|
|
|
SET_BITMASK_AS_ENUM(uiToUpdate.iBitFlags, CNTDWN_UI_Played_Go)
|
|
INT iR, iG, iB, iA
|
|
GET_HUD_COLOUR(HUD_COLOUR_GREEN, iR, iG, iB, iA)
|
|
BEGIN_SCALEFORM_MOVIE_METHOD(uiToUpdate.uiCountdown, "SET_MESSAGE")
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_STRING("CNTDWN_GO")
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(iR)
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(iG)
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(iB)
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_BOOL(TRUE)
|
|
END_SCALEFORM_MOVIE_METHOD()
|
|
|
|
IF NOT bWaitExtraSec
|
|
bForceEnd = TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
IF (iSeconds = 1)
|
|
bForceEnd = TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
//check for a button press to skip the countdown
|
|
IF (bSkipOnButtonPress AND IS_CUTSCENE_SKIP_BUTTON_PRESSED()) OR iTimerVal > 5
|
|
bForceEnd = TRUE
|
|
ENDIF
|
|
|
|
// If we've been ordered to leave, do so.
|
|
IF bForceEnd
|
|
IF bCancelTimerAtEnd
|
|
// Reset our vars.
|
|
uiToUpdate.iBitFlags = 0
|
|
CANCEL_TIMER(uiToUpdate.CountdownTimer)
|
|
ENDIF
|
|
|
|
// We're done.
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Packs a vector into a single INT
|
|
/// Bits 0-14 are the X value, and Bits 15-29 are the Y value.
|
|
/// Z value is dropped
|
|
/// Bit 30 is sign X and Bit 31 is SignY
|
|
/// All values are currently rounded, giving you ~1m accuracy
|
|
/// Does not work for values outside of (-32767, 32767)
|
|
/// PARAMS:
|
|
/// vPos - Vector to pack
|
|
/// RETURNS:
|
|
/// The packed int
|
|
FUNC INT VECTOR_FLAT_PACK(VECTOR vPacked)
|
|
//Truncate the x value to the first fifteen bits
|
|
// Or is with the Truncated 15 bits of Z, shifted up to the next 15 bits
|
|
INT retVal = (ROUND(ABSF(vPacked.x)) & 32767) | SHIFT_LEFT((ROUND(ABSF(vPacked.y)) & 32767), 15)
|
|
IF vPacked.x > 0
|
|
retVal |= BIT30
|
|
ENDIF
|
|
IF vPacked.y > 0
|
|
retVal |= (BIT30 * 2)
|
|
ENDIF
|
|
RETURN retVal
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Unpacks an int that was packed with PACK_POSITION_FLAT
|
|
/// PARAMS:
|
|
/// packedPosition -
|
|
/// RETURNS:
|
|
///
|
|
FUNC VECTOR VECTOR_FLAT_UNPACK(INT packedPosition)
|
|
VECTOR retVal
|
|
INT unpackedX = packedPosition & 32767
|
|
INT unpackedZ = SHIFT_RIGHT(packedPosition, 15) & 32767
|
|
retVal.x = TO_FLOAT(unpackedX) // Mask off all but the first 15 bits
|
|
retVal.y = TO_FLOAT(unpackedZ) // Shift the next 15 bits down to first 15, then mask them off
|
|
IF (packedPosition & BIT30) = 0 // Reset the sign of the X value
|
|
retVal.x *= -1
|
|
ENDIF
|
|
IF (packedPosition & (BIT30 * 2)) = 0 // Reset the sign of the Z value
|
|
retVal.y *= -1
|
|
ENDIF
|
|
RETURN retVal
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// To convert the INT packed by VECTOR_FLAT_PACK to a world position, using the ground check
|
|
/// RETURNS:
|
|
///
|
|
FUNC VECTOR GET_WORLD_POSITION_FROM_PACKED_INT(INT packedPosition)
|
|
VECTOR retVal = VECTOR_FLAT_UNPACK(packedPosition)
|
|
IF NOT GET_GROUND_Z_FOR_3D_COORD(retVal, retVal.z)
|
|
SCRIPT_ASSERT("GET_GROUND_Z_FOR_3D_COORD failed in the designer defined func: GET_WORLD_POSITION_FROM_PACKED_INT")
|
|
ENDIF
|
|
RETURN retVal
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Stops peds from spawning, walking, and activating scenarios in an area. Rectangle created is axis aligned.
|
|
/// Does cause some awkward standing around from peds
|
|
/// PARAMS:
|
|
/// vMin -
|
|
/// vMax -
|
|
/// RETURNS:
|
|
/// A scenario blocking index, store this and use it to remove the blocking area when the script cleans up
|
|
FUNC SCENARIO_BLOCKING_INDEX PREVENT_PEDS_FROM_BEING_IN_AREA(VECTOR vMin, VECTOR vMax)
|
|
SET_PED_NON_CREATION_AREA(vMin, vMax)
|
|
DISABLE_NAVMESH_IN_AREA(vMin, vMax, TRUE)
|
|
RETURN ADD_SCENARIO_BLOCKING_AREA(vMin, vMax)
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Clean up all the work done by PREVENT_PEDS_FROM_BEING_IN_AREA
|
|
/// PARAMS:
|
|
/// sbi -
|
|
/// vMin -
|
|
/// vMax -
|
|
PROC ALLOW_PEDS_TO_BE_IN_AREA(SCENARIO_BLOCKING_INDEX sbi, VECTOR vMin, VECTOR vMax)
|
|
REMOVE_SCENARIO_BLOCKING_AREA(sbi)
|
|
CLEAR_PED_NON_CREATION_AREA()
|
|
DISABLE_NAVMESH_IN_AREA(vMin, vMax, FALSE)
|
|
ENDPROC
|
|
|
|
STRUCT SCRIPT_SCALEFORM_MEDAL_TOAST
|
|
SCALEFORM_INDEX siMovie
|
|
INT iDuration
|
|
structTimer movieTimer
|
|
ENDSTRUCT
|
|
|
|
FUNC SCALEFORM_INDEX REQUEST_MG_MEDAL_TOAST()
|
|
RETURN REQUEST_SCALEFORM_MOVIE("MP_MEDAL_FREEMODE")
|
|
ENDFUNC
|
|
|
|
PROC CLEAR_MG_MEDAL_TOAST(SCRIPT_SCALEFORM_MEDAL_TOAST& medalToast)
|
|
IF HAS_SCALEFORM_MOVIE_LOADED(medalToast.siMovie)
|
|
BEGIN_SCALEFORM_MOVIE_METHOD(medalToast.siMovie, "RESET_AWARDS_MOVIE")
|
|
END_SCALEFORM_MOVIE_METHOD()
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC CLEANUP_MG_MEDAL_TOAST(SCRIPT_SCALEFORM_MEDAL_TOAST& medalToast)
|
|
SET_SCALEFORM_MOVIE_AS_NO_LONGER_NEEDED(medalToast.siMovie)
|
|
medalToast.siMovie = NULL
|
|
ENDPROC
|
|
|
|
|
|
PROC SET_MG_MEDAL_TOAST(SCRIPT_SCALEFORM_MEDAL_TOAST &medalToast, STRING TexDict, STRING TexName, STRING sAward, STRING sTitle, STRING sSubTitle, INT iDuration)
|
|
medalToast.iDuration = iDuration
|
|
BEGIN_SCALEFORM_MOVIE_METHOD(medalToast.siMovie, "SHOW_AWARD_AND_MESSAGE")
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_STRING(sAward)
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_STRING(sTitle)
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_PLAYER_NAME(TexDict)//DisplayStruct.TextureDictionary
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_PLAYER_NAME(TexName)//DisplayStruct.TextureName)
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_STRING(sSubTitle)
|
|
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(0) // 107 = Bronze, 108 = Silver, 109 = gold, 110 = Plat
|
|
|
|
// SCALEFORM_MOVIE_METHOD_ADD_PARAM_STRING("FAKESTRING")
|
|
END_SCALEFORM_MOVIE_METHOD()
|
|
ENDPROC
|
|
|
|
FUNC BOOL UPDATE_MG_MEDAL_TOAST(SCRIPT_SCALEFORM_MEDAL_TOAST &medalToast)
|
|
IF NOT IS_TIMER_STARTED(medalToast.movieTimer)
|
|
RESTART_TIMER_NOW(medalToast.movieTimer)
|
|
ENDIF
|
|
|
|
// Hide the reticle.
|
|
HIDE_HUD_COMPONENT_THIS_FRAME(NEW_HUD_RETICLE)
|
|
|
|
DRAW_SCALEFORM_MOVIE_FULLSCREEN(medalToast.siMovie, 255, 255, 255, 255)
|
|
|
|
//always return true if the duration is -1
|
|
IF (medalToast.iDuration = -1)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
// Is it time to leave?
|
|
IF (GET_TIMER_IN_SECONDS(medalToast.movieTimer) * 1000.0 > TO_FLOAT(medalToast.iDuration))
|
|
CANCEL_TIMER(medalToast.movieTimer)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// prepares a music event
|
|
/// PARAMS: eBitMask is for a flag to make sure that we dont prepare/trigger more than once.
|
|
|
|
/// RETURNS:
|
|
/// Whether we were successful
|
|
///
|
|
|
|
FUNC BOOL MG_PREPARE_MUSIC_EVENT(STRING sMusicEvent, INT &iBitField, ENUM_TO_INT eBitMask)
|
|
IF NOT IS_BIT_SET(iBitField, ENUM_TO_INT(eBitmask))
|
|
IF PREPARE_MUSIC_EVENT(sMusicEvent)
|
|
PRINTLN("PREPARED MUSIC EVENT: ", sMusicEvent)
|
|
SET_BIT(iBitField, ENUM_TO_INT(eBitmask))
|
|
RETURN TRUE
|
|
ENDIF
|
|
ELSE
|
|
RETURN TRUE
|
|
ENDIF
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL MG_TRIGGER_MUSIC_EVENT(STRING sMusicEvent, INT &iBitField, ENUM_TO_INT eBitMask)
|
|
|
|
IF NOT IS_BIT_SET(iBitField, ENUM_TO_INT(eBitmask))
|
|
IF PREPARE_MUSIC_EVENT(sMusicEvent)
|
|
IF TRIGGER_MUSIC_EVENT(sMusicEvent)
|
|
PRINTLN("TRIGGERED MUSIC EVENT: ", sMusicEvent)
|
|
SET_BIT(iBitField, ENUM_TO_INT(eBitmask))
|
|
RETURN TRUE
|
|
ELSE
|
|
PRINTLN("Couldn't trigger music event this frame: ", sMusicEvent)
|
|
ENDIF
|
|
ELSE
|
|
PRINTLN("music event not prepared")
|
|
ENDIF
|
|
ELSE
|
|
RETURN TRUE
|
|
ENDIF
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// starts audio scene
|
|
/// PARAMS: eBitMask is for a flag to make sure that we dont prepare/trigger more than once.
|
|
|
|
/// RETURNS:
|
|
/// Whether we were successful
|
|
///
|
|
|
|
FUNC BOOL MG_START_AUDIO_SCENE(STRING sAudioSceneToStart, STRING sAudioSceneToStop, INT &iBitField, ENUM_TO_INT eBitMask)
|
|
IF NOT IS_STRING_NULL_OR_EMPTY(sAudioSceneToStop)
|
|
IF IS_AUDIO_SCENE_ACTIVE(sAudioSceneToStop)
|
|
STOP_AUDIO_SCENE(sAudioSceneToStop)
|
|
PRINTLN("STOPPED AUDIO SCENE: ", sAudioSceneToStop)
|
|
ELSE
|
|
PRINTLN("CANT STOP AN INACTIVE AUDIO SCENE: ", sAudioSceneToStop)
|
|
ENDIF
|
|
ELSE
|
|
PRINTLN("NULL STRING. NO AUDIO SCENE TO STOP ")
|
|
ENDIF
|
|
|
|
IF NOT IS_BIT_SET(iBitField, ENUM_TO_INT(eBitmask))
|
|
IF START_AUDIO_SCENE(sAudioSceneToStart)
|
|
PRINTLN("STARTED AUDIO SCENE: ", sAudioSceneToStart)
|
|
SET_BIT(iBitField, ENUM_TO_INT(eBitmask))
|
|
RETURN TRUE
|
|
ENDIF
|
|
PRINTLN("ATTEMPTING TO START AUDIO SCENE: ", sAudioSceneToStart)
|
|
ELSE
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
PROC MG_STOP_AUDIO_SCENE(STRING sAudioScene, INT &iBitField, ENUM_TO_INT eBitMask)
|
|
IF NOT IS_BIT_SET(iBitField, ENUM_TO_INT(eBitmask))
|
|
STOP_AUDIO_SCENE(sAudioScene)
|
|
PRINTLN("STOPPED AUDIO SCENE: ", sAudioScene)
|
|
SET_BIT(iBitField, ENUM_TO_INT(eBitmask))
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
CONST_INT MG_FAIL_BLUR_EFFECT_TIME 3000
|
|
CONST_FLOAT MG_FAIL_BLUR_FAIL_EFFECT_SLO_MO 0.02
|
|
CONST_FLOAT MG_FAIL_BLUR_FAIL_OUT_EFFECT_SLO_MO 0.05
|
|
INT iFailScreenBits = 0
|
|
INT iDelayTimer = 0
|
|
ENUM MG_FAIL_BLUR_EFFECT_FLAGS
|
|
MG_FAIL_BLUR_HAS_BEEN_TRIGGERED,
|
|
MG_FAIL_BLUR_FAIL_OUT_HAS_BEEN_TRIGGERED,
|
|
MG_FAIL_BLUR_SLOW_MO_HAS_BEEN_TRIGGERED,
|
|
MG_FAIL_BLUR_PAUSED_GAME,
|
|
MG_FAIL_BLUR_DELAY_TIMER_SET
|
|
|
|
ENDENUM
|
|
|
|
PROC MG_RESET_FAIL_EFFECT_VARS()
|
|
iFailScreenBits = 0
|
|
iDelayTimer = 0
|
|
SET_SCRIPTS_SAFE_FOR_CUTSCENE(FALSE)
|
|
DISABLE_CELLPHONE(TRUE)
|
|
ENDPROC
|
|
|
|
PROC MG_DO_PAUSE_EFFECT(BOOL bPause)
|
|
BOOL bIgnore = FALSE
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
bIgnore = g_bFlowAutoplayInProgress
|
|
#ENDIF
|
|
|
|
IF bIgnore = FALSE
|
|
// don't pause the game if we are doing an auto playthrough
|
|
|
|
IF bPause = TRUE
|
|
// pause the game
|
|
IF NOT IS_BIT_SET(iFailScreenBits, ENUM_TO_INT(MG_FAIL_BLUR_PAUSED_GAME))
|
|
PRINTLN("MG_DO_PAUSE_EFFECT() is pausing the game.")
|
|
SET_GAME_PAUSED(TRUE)
|
|
SET_BIT(iFailScreenBits, ENUM_TO_INT(MG_FAIL_BLUR_PAUSED_GAME))
|
|
ENDIF
|
|
ELSE
|
|
// unpause the game
|
|
IF IS_BIT_SET(iFailScreenBits, ENUM_TO_INT(MG_FAIL_BLUR_PAUSED_GAME))
|
|
PRINTLN( "MG_DO_PAUSE_EFFECT() is unpausing the game.")
|
|
SET_GAME_PAUSED(FALSE)
|
|
CLEAR_BIT(iFailScreenBits, ENUM_TO_INT(MG_FAIL_BLUR_PAUSED_GAME))
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
|
|
ENDPROC
|
|
|
|
PROC MG_DO_SLOW_MO_EFFECT(BOOL bStart, INT iFailEffect = 1, BOOL bIgnoreTriggeredFlags = FALSE)
|
|
IF bStart = TRUE
|
|
PRINTLN("MG_DO_SLOW_MO_EFFECT() is starting slo-mo now")
|
|
SET_BIT(iFailScreenBits, ENUM_TO_INT(MG_FAIL_BLUR_SLOW_MO_HAS_BEEN_TRIGGERED))
|
|
// start slow motion
|
|
|
|
#IF USE_TU_CHANGES
|
|
IF NOT NETWORK_IS_GAME_IN_PROGRESS()
|
|
IF iFailEffect = 1
|
|
SET_TIME_SCALE(FAIL_EFFECT_SLO_MO)
|
|
ELSE
|
|
SET_TIME_SCALE(FAIL_OUT_EFFECT_SLO_MO)
|
|
ENDIF
|
|
ENDIF
|
|
#ENDIF // USE_TU_CHANGES
|
|
|
|
#IF NOT USE_TU_CHANGES
|
|
IF iFailEffect = 1
|
|
SET_TIME_SCALE(FAIL_EFFECT_SLO_MO)
|
|
ELSE
|
|
SET_TIME_SCALE(FAIL_OUT_EFFECT_SLO_MO)
|
|
ENDIF
|
|
#ENDIF // NOT USE_TU_CHANGES
|
|
|
|
|
|
ELSE
|
|
IF IS_BIT_SET(iFailScreenBits, ENUM_TO_INT(MG_FAIL_BLUR_SLOW_MO_HAS_BEEN_TRIGGERED)) OR bIgnoreTriggeredFlags
|
|
PRINTLN( "MG_DO_SLOW_MO_EFFECT() is disabling slo-mo now")
|
|
#IF USE_TU_CHANGES
|
|
IF NOT NETWORK_IS_GAME_IN_PROGRESS()
|
|
SET_TIME_SCALE(1.0)
|
|
ENDIF
|
|
#ENDIF // USE_TU_CHANGES
|
|
|
|
#IF NOT USE_TU_CHANGES
|
|
SET_TIME_SCALE(1.0)
|
|
#ENDIF // NOT USE_TU_CHANGES
|
|
ENDIF
|
|
CLEAR_BIT(iFailScreenBits, ENUM_TO_INT(MG_FAIL_BLUR_SLOW_MO_HAS_BEEN_TRIGGERED))
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC MG_DO_FAIL_EFFECT(BOOL bStart, BOOL bIgnoreTriggeredFlags = FALSE)
|
|
STRING sEffect
|
|
|
|
SWITCH GET_CURRENT_PLAYER_PED_ENUM()
|
|
CASE CHAR_MICHAEL
|
|
sEffect = "DeathFailMichaelIn"
|
|
BREAK
|
|
|
|
CASE CHAR_FRANKLIN
|
|
sEffect = "DeathFailFranklinIn"
|
|
BREAK
|
|
|
|
CASE CHAR_TREVOR
|
|
sEffect = "DeathFailTrevorIn"
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
IF bStart = TRUE
|
|
IF NOT IS_BIT_SET(iFailScreenBits, ENUM_TO_INT(MG_FAIL_BLUR_HAS_BEEN_TRIGGERED)) OR bIgnoreTriggeredFlags
|
|
PRINTLN("MG_DO_FAIL_OUT_EFFECT() is starting effect now: ", sEffect)
|
|
ANIMPOSTFX_PLAY(sEffect, 0, FALSE)
|
|
SET_BIT(iFailScreenBits, ENUM_TO_INT(MG_FAIL_BLUR_HAS_BEEN_TRIGGERED))
|
|
MG_DO_SLOW_MO_EFFECT(TRUE, 1)
|
|
// trigger slow motion camera effect
|
|
SET_CAM_DEATH_FAIL_EFFECT_STATE(CAM_DEATH_FAIL_EFFECT_INTRO)
|
|
ENDIF
|
|
ELSE
|
|
IF IS_BIT_SET(iFailScreenBits, ENUM_TO_INT(MG_FAIL_BLUR_HAS_BEEN_TRIGGERED)) OR bIgnoreTriggeredFlags
|
|
PRINTLN("MG_DO_FAIL_OUT_EFFECT() is disabling fail effect now: ", sEffect)
|
|
ANIMPOSTFX_STOP(sEffect)
|
|
MG_DO_SLOW_MO_EFFECT(FALSE, 1, TRUE)
|
|
SET_CAM_DEATH_FAIL_EFFECT_STATE(CAM_DEATH_FAIL_EFFECT_INACTIVE)
|
|
ENDIF
|
|
CLEAR_BIT(iFailScreenBits, ENUM_TO_INT(MG_FAIL_BLUR_HAS_BEEN_TRIGGERED))
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
PROC MG_DO_FAIL_OUT_EFFECT(BOOL bStart, BOOL bIgnoreTriggeredFlags = FALSE)
|
|
IF bStart = TRUE
|
|
MG_DO_FAIL_EFFECT(FALSE)
|
|
PRINTLN("MG_DO_FAIL_OUT_EFFECT() is starting fail out effect now")
|
|
ANIMPOSTFX_PLAY("DeathFailOut", 0, FALSE)
|
|
SET_BIT(iFailScreenBits, ENUM_TO_INT(MG_FAIL_BLUR_FAIL_OUT_HAS_BEEN_TRIGGERED))
|
|
|
|
// super slow motion
|
|
MG_DO_SLOW_MO_EFFECT(TRUE, 2)
|
|
|
|
// trigger camera effect
|
|
SET_CAM_DEATH_FAIL_EFFECT_STATE(CAM_DEATH_FAIL_EFFECT_OUTRO)
|
|
ELSE
|
|
IF IS_BIT_SET(iFailScreenBits, ENUM_TO_INT(MG_FAIL_BLUR_FAIL_OUT_HAS_BEEN_TRIGGERED)) OR bIgnoreTriggeredFlags
|
|
PRINTLN("MG_DO_FAIL_OUT_EFFECT() is disabling fail out effect now")
|
|
ANIMPOSTFX_STOP("DeathFailOut")
|
|
MG_DO_SLOW_MO_EFFECT(FALSE, 2, TRUE)
|
|
SET_CAM_DEATH_FAIL_EFFECT_STATE(CAM_DEATH_FAIL_EFFECT_INACTIVE)
|
|
ENDIF
|
|
CLEAR_BIT(iFailScreenBits, ENUM_TO_INT(MG_FAIL_BLUR_FAIL_OUT_HAS_BEEN_TRIGGERED))
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
|
|
//PROC MG_START_FAIL_BLUR_EFFECT(BOOL bStart)
|
|
//
|
|
//
|
|
//ENDPROC
|
|
|
|
|
|
FUNC BOOL MG_DO_FAIL_BLUR_EFFECT()
|
|
|
|
//trigger blur effect and reset timer
|
|
IF NOT IS_BIT_SET(iFailScreenBits, ENUM_TO_INT(MG_FAIL_BLUR_HAS_BEEN_TRIGGERED))
|
|
AND NOT IS_BIT_SET(iFailScreenBits, ENUM_TO_INT(MG_FAIL_BLUR_FAIL_OUT_HAS_BEEN_TRIGGERED))
|
|
SETTIMERA(0)
|
|
MG_DO_FAIL_EFFECT(TRUE)
|
|
ENDIF
|
|
|
|
// things we need to block every frame
|
|
// remove any god text / subtitles
|
|
IF NOT IS_CUTSCENE_PLAYING()
|
|
CLEAR_PRINTS()
|
|
ENDIF
|
|
|
|
// disable the pause menu during fail screen
|
|
DISABLE_CONTROL_ACTION(FRONTEND_CONTROL, INPUT_FRONTEND_PAUSE)
|
|
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_MOVE_LR)
|
|
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_MOVE_UD)
|
|
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_SELECT_WEAPON)
|
|
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_AIM)
|
|
|
|
SUPPRESS_AMBIENT_PED_AGGRESSIVE_CLEANUP_THIS_FRAME()
|
|
|
|
IF TIMERA() > 1500 * FAIL_EFFECT_SLO_MO
|
|
IF NOT IS_BIT_SET(iFailScreenBits, ENUM_TO_INT(MG_FAIL_BLUR_FAIL_OUT_HAS_BEEN_TRIGGERED))
|
|
// not started fail out effect, do it now + pause the game
|
|
MG_DO_FAIL_OUT_EFFECT(TRUE)
|
|
SETTIMERB(0)
|
|
ELSE
|
|
IF TIMERB() > 1500 * FAIL_OUT_EFFECT_SLO_MO
|
|
OR IS_SCREEN_FADED_OUT() // used for skipping fail cut-scenes
|
|
// --------finished fail out effect ------------------------------
|
|
// start fading out
|
|
IF NOT IS_SCREEN_FADED_OUT()
|
|
IF NOT IS_SCREEN_FADING_OUT()
|
|
DO_SCREEN_FADE_OUT(1500)
|
|
ENDIF
|
|
ELSE
|
|
IF iDelayTimer = 0
|
|
iDelayTimer = GET_GAME_TIMER() + 1000
|
|
|
|
// -------------screen has faded out--------------------------
|
|
// Do necessary setup, and then move on to showing the replay screen
|
|
PRINTLN("Fail effect for script [", GET_THIS_SCRIPT_NAME(), "] completed.")
|
|
|
|
// disable player control
|
|
IF IS_PLAYER_PLAYING(PLAYER_ID())
|
|
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE)
|
|
ENDIF
|
|
MG_DO_SLOW_MO_EFFECT(FALSE, 2, TRUE)
|
|
SET_SCRIPTS_SAFE_FOR_CUTSCENE(TRUE)
|
|
DISABLE_CELLPHONE(TRUE)
|
|
SET_FRONTEND_ACTIVE(FALSE)
|
|
SET_PAUSE_MENU_ACTIVE(FALSE)
|
|
CLEAR_HELP()
|
|
CLEAR_PRINTS()
|
|
|
|
// disable player control
|
|
IF IS_PLAYER_PLAYING(PLAYER_ID())
|
|
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE)
|
|
ENDIF
|
|
|
|
MG_DO_FAIL_EFFECT(FALSE)
|
|
MG_DO_PAUSE_EFFECT(FALSE)
|
|
ELSE
|
|
IF GET_GAME_TIMER() < iDelayTimer
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Gets appropriate checkpoint alpha based on the player's distance from the checkpoint
|
|
FUNC INT MG_GET_CHECKPOINT_ALPHA(VECTOR vCheckpointPos, INT iAMin = 25, INT iAMax = 200)
|
|
FLOAT fDistMaxAlpha = 100.0
|
|
INT iA = 50
|
|
|
|
//add special min/max alpha distances depending on type of MG?
|
|
|
|
FLOAT fDist
|
|
|
|
IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID())
|
|
fDist = GET_DISTANCE_BETWEEN_COORDS(vCheckpointPos, GET_ENTITY_COORDS(PLAYER_PED_ID()))
|
|
IF fDist > fDistMaxAlpha
|
|
iA = iAMax
|
|
ELSE
|
|
FLOAT fMod = ( (fDistMaxAlpha-fDist) / (fDistMaxAlpha) )
|
|
iA = iAMax - CEIL((iAMax-iAMin) * fMod)
|
|
//PRINTLN("MG_GET_CHECKPOINT_ALPHA: ", iA, " and fDis: ", fDist, "and fMod: ", fMod)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF iA < iAMin
|
|
iA = iAMin
|
|
ENDIF
|
|
|
|
RETURN iA
|
|
ENDFUNC
|
|
|
|
/// PURPOSE: Gets appropriate checkpoint colour based on chevron type
|
|
FUNC HUD_COLOURS MG_GET_RACE_CHECKPOINT_DEFAULT_COLOUR()
|
|
RETURN HUD_COLOUR_YELLOW
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Checks if the vehicle is very large and needs its own respawn space
|
|
/// Checks for blimps and helicopters. And some Planes.
|
|
/// Please add vehicles as needed.
|
|
/// PARAMS:
|
|
/// vehPlayer - player's saved vehicle index
|
|
/// RETURNS:
|
|
/// TRUE if the vehicle should be moved to more open space for respawn.
|
|
FUNC BOOL MINIGAME_DOES_VEHICLE_NEED_LARGE_RESPAWN_SPACE( VEHICLE_INDEX vehPlayer )
|
|
|
|
MODEL_NAMES eModel = GET_ENTITY_MODEL( vehPlayer )
|
|
|
|
SWITCH eModel
|
|
CASE BLIMP RETURN TRUE
|
|
CASE BLIMP2 RETURN TRUE
|
|
CASE CARGOBOB RETURN TRUE
|
|
CASE CARGOBOB2 RETURN TRUE
|
|
CASE CARGOBOB3 RETURN TRUE
|
|
CASE BUZZARD RETURN TRUE
|
|
CASE BUZZARD2 RETURN TRUE
|
|
CASE MAVERICK RETURN TRUE
|
|
CASE POLMAV RETURN TRUE
|
|
CASE SWIFT RETURN TRUE
|
|
CASE VALKYRIE RETURN TRUE
|
|
CASE ANNIHILATOR RETURN TRUE
|
|
CASE FROGGER RETURN TRUE
|
|
CASE FROGGER2 RETURN TRUE
|
|
CASE DODO RETURN TRUE
|
|
ENDSWITCH
|
|
|
|
RETURN FALSE
|
|
|
|
ENDFUNC
|
|
|
|
// END OF FILE! DO NOT ADD ANYTHING BELOW THIS LINE!
|