Files
2025-09-29 00:52:08 +02:00

1952 lines
58 KiB
Python
Executable File

//Compile out Title Update changes to header functions.
//Must be before includes.
//CONST_INT USE_TU_CHANGES 0 // Removed by Kenneth R.
USING "rage_builtins.sch"
USING "globals.sch"
USING "clearmissionarea.sch"
USING "commands_audio.sch"
USING "commands_camera.sch"
USING "commands_pad.sch"
USING "commands_vehicle.sch"
USING "commands_path.sch"
USING "commands_ped.sch"
USING "commands_physics.sch"
USING "commands_script.sch"
USING "commands_task.sch"
USING "CompletionPercentage_public.sch"
using "dialogue_public.sch"
USING "flow_public_core_override.sch"
USING "flow_public_GAME.sch"
using "ped_component_public.sch"
USING "player_ped_public.sch"
USING "replay_public.sch"
USING "script_blips.sch"
USING "script_heist.sch"
USING "script_ped.sch"
USING "selector_public.sch"
USING "flow_special_event_checks.sch"
BOOL bJumpSkip = FALSE //flag for if current MISSION state should clean up and move to the next state
USING "prep_mission_common.sch"
USING "shop_public.sch"
USING "commands_recording.sch"
#IF IS_DEBUG_BUILD
USING "select_mission_stage.sch"
USING "shared_debug.sch"
CONST_INT MAX_SKIP_MENU_LENGTH 2
INT i_debug_jump_stage
MissionStageMenuTextStruct s_skip_menu[MAX_SKIP_MENU_LENGTH]
#ENDIF
// *****************************************************************************************
// *****************************************************************************************
// *****************************************************************************************
//
// MISSION NAME : Template.sc
// AUTHOR : Ste Kerrigan
// DESCRIPTION :
//
// *****************************************************************************************
// *****************************************************************************************
// *****************************************************************************************
//----------------------
// CHECKPOINTS
//----------------------
CONST_INT CP_AFTER_MOCAP 0 //following beverly down the road
//-----------------------
// CONSTANTS
//-----------------------
//POLY TEST CONST
CONST_INT MAX_POLY_TEST_VERTS 8 //poly test
//Ambient encounter speech
CONST_INT MAX_AMBIENT_CONV_LINES 8
/// --------------------------------------------------
/// ENUMS
/// -------------------------------------------
/// PURPOSE: Mission states
ENUM MISSION_STATE
MS_SET_UP = 0, //0
MS_GET_TO_CLOTHES, //1
MS_BUY, //2
MS_FAILED //4
ENDENUM
/// PURPOSE:
/// Internal state machine states for mission state
ENUM STAGE_STATES
SS_INIT,
SS_ACTIVE,
SS_CLEANUP,
SS_SKIPPED
ENDENUM
/// PURPOSE: Mission requirements used for loading
/// and creating mission assets
ENUM MISSION_REQ
RQ_NONE,
RQ_TEXT
ENDENUM
/// PURPOSE: Fail reason enums for picking correct fail reason
ENUM FAILED_REASONS
FR_NONE,
FR_KICKOFFSHOP,
FR_LEFT,
FR_NO_CASH,
FR_COPS
ENDENUM
ENUM ABM_CONV_STATES
ACS_START_LINE,
ACS_WAIT_LINE_FIN,
ACS_PICK_NEXT_LINE,
ACS_FIN
ENDENUM
///MISSION PED STATES
MISSION_STATE eMissionState = MS_SET_UP //track what MISSION stage we are at
STAGE_STATES eState = SS_INIT //Internal state tracking for mission stages
//*****************************************************************************
// :STRUCTS:
//*****************************************************************************
TEST_POLY mAreaCheck1 //Poly area 1
TEST_POLY mAreaCheck2 //Poly area 2
//****************************************************************************************************
// : MISSION FLOW VARIABLES :
//****************************************************************************************************
//mission flow
INT iMissionState = 0 //Used in skips and checkpoints
//Fail vars
STRING sFailReason = NULL //String to display when mission is failed
//GOD TEXT
STRING sGodText = "FBIPRD"
BOOL bObjectiveShown = FALSE //Has an objective been shown
BOOL bMaskBought = FALSE
INT iNumberBought = 0
//BLIPs
BLIP_INDEX biBlip //Mission blip - mainly used for go to objectives
//ScriptCamera
CAMERA_INDEX camMain //Script camera used in place holder cutscenes
VECTOR vSafeVec = <<0,0,0>> //safe vector used when a proper position isnt needed
VECTOR vShop = <<-1335.3142, -1277.9427, 3.8649>>
VECTOR vMasks = <<-1336.3777, -1279.0555, 3.8550>>
BOOL bArrivedShopLoc = FALSE
INT iMissionPassDelayTimer
INT iWantedFailTimer = -1
///==============| GOD TEXT BOOLS |============
BOOL bWarnLeft = FALSE
BOOL bDeletedBlip = FALSE
STRING mObj[NUM_OF_PLAYABLE_PEDS]
///===============| models |===================
/// ===============| START VECTORS |==============
/// ==============| START HEADINGS |===============
/// ==============| PED INDICES |================
/// ==============| VEHICLE INDICES |===========
/// ===============| GROUPS |========================
/// ===============| DIALOGUE |======================
STRING sTextBlock = "FBIPRAU" //The Dialogue block for the mission
structPedsForConversation s_conversation_peds //conversation struct
TEXT_LABEL_15 sPhoneUpdateString
DYNAMIC_PHONE_STATE ePhoneCallState = DPS_CHOOSE_PHONE_CALL
//Used for tracking an interupted conversation
//TEXT_LABEL_23 sResumeRoot = "NONE"
//TEXT_LABEL_23 sResumeLine = "NONE"
/// PURPOSE:
/// Resets all variables used in flow
PROC RESET_ALL()
ENDPROC
// ------------MASKS FUNCTIONS -------------------------------------------
/// PURPOSE:
/// Returns the number of masks that the player has bought
/// RETURNS:
///
FUNC INT GET_NUM_OF_MASKS_BOUGHT()
INT iMasks = 0
INT iPlayerToCheck
FOR iPlayerToCheck = ENUM_TO_INT(CHAR_MICHAEL) TO (NUM_OF_PLAYABLE_PEDS-1)
IF g_savedGlobals.sPlayerData.sInfo.eFBI4MaskName[INT_TO_ENUM( enumCharacterList, iPlayerToCheck)] != DUMMY_PED_COMP
iMasks++
ENDIF
ENDFOR
CPRINTLN(DEBUG_MISSION, "The player has bought ",iMasks, " masks. And has ", GET_ACCOUNT_BALANCE(BANK_ACCOUNT_MICHAEL), " Cash in account")
RETURN iMasks
ENDFUNC
///
///
/// DEBUG ONLY MISSION STUFF ------------------------------------------------------------
///
///
#IF IS_DEBUG_BUILD
BOOL bShowDebugText = TRUE
WIDGET_GROUP_ID widgetGroup
BOOL bForceFail = FALSE
/// PURPOSE:
/// Prints a string to a TTY Channel
/// PARAMS:
/// s - The string to print
/// ddc - The debug channel to print to
PROC SK_PRINT(String s, DEBUG_CHANNELS ddc = DEBUG_MISSION)
IF bShowDebugText
CPRINTLN(ddc, s)
PRINTNL()
PRINTNL()
ENDIF
ENDPROC
/// PURPOSE:
/// Prints a string and an int to a TTY Channel
/// PARAMS:
/// s - The string to print
/// i - the int to print
/// ddc - the debug channel to print to
PROC SK_PRINT_INT(String s, INT i, DEBUG_CHANNELS ddc = DEBUG_MISSION)
IF bShowDebugText
CPRINTLN(ddc, s,i)
PRINTNL()
PRINTNL()
ENDIF
ENDPROC
/// PURPOSE:
/// Prints a string and a Float to a TTY Channel
/// PARAMS:
/// s - the string to print
/// f - the float to print
/// ddc - the debug channel
PROC SK_PRINT_FLOAT(String s, FLOAT f, DEBUG_CHANNELS ddc = DEBUG_MISSION)
IF bShowDebugText
CPRINTLN(ddc, s,f)
PRINTNL()
PRINTNL()
ENDIF
ENDPROC
/// PURPOSE:
/// Sets up a widget for this mission
PROC SETUP_FOR_RAGE_WIDGETS()
widgetGroup = START_WIDGET_GROUP("CURRENT Mission Widgets")
START_WIDGET_GROUP("Debug")
ADD_WIDGET_BOOL("Toggle Debug spew", bShowDebugText)
STOP_WIDGET_GROUP()
START_WIDGET_GROUP("Force Mission Fail")
ADD_WIDGET_BOOL("Force Fail", bForceFail)
STOP_WIDGET_GROUP()
STOP_WIDGET_GROUP()
ENDPROC
/// PURPOSE:
/// Deletes the mission widget
PROC CLEANUP_OBJECT_WIDGETS()
IF DOES_WIDGET_GROUP_EXIST(widgetGroup)
DELETE_WIDGET_GROUP(widgetGroup)
ENDIF
ENDPROC
/// PURPOSE:
/// Checks for any updates needed for the widgets
PROC UPDATE_RAG_WIDGETS()
IF bForceFail
eMissionState = MS_FAILED
eState = SS_INIT
bForceFail = FALSE
ENDIF
ENDPROC
/// PURPOSE:
/// Draws an angled area
/// PARAMS:
/// vec1 - first point of the area
/// vec2 - second point of the area
/// width - the width of the area
// PROC DRAW_DEBUG_LOCATE_SPECIAL(VECTOR vec1, VECTOR vec2, FLOAT width)
//
// VECTOR vBottom[2]
// VECTOR vTop[2]
//
// vBottom[0] = vec1
// vBottom[1] = vec2
//
// vTop[0] = vec1
// vTop[1] = vec2
//
// IF vec1.z > vec2.z
// vBottom[0].z = vec2.z
// vBottom[1].z = vec2.z
// vTop[0].z = vec1.z
// vTop[1].z = vec1.z
// ELSE
// vBottom[0].z = vec1.z
// vBottom[1].z = vec1.z
// vTop[0].z = vec2.z
// vTop[1].z = vec2.z
// ENDIF
//
// VECTOR fwd = NORMALISE_VECTOR(vBottom[1] - vBottom[0]) // normalize to get distance
// VECTOR side = <<-fwd.y, fwd.x, fwd.z>>
// VECTOR w = side * (width / 2.0)
//
// // Bottom points
// VECTOR c1 = vBottom[0] - w // base left
// VECTOR c2 = vBottom[0] + w // base right
// VECTOR c3 = vBottom[1] + w // top rt
// VECTOR c4 = vBottom[1] - w // top lt
//
// // Top points
// VECTOR d1 = vTop[0] - w // base left
// VECTOR d2 = vTop[0] + w // base right
// VECTOR d3 = vTop[1] + w // top rt
// VECTOR d4 = vTop[1] - w // top lt
//
// // Draw bottom lines
// DRAW_DEBUG_LINE(c1, c2, 128, 0, 128)
// DRAW_DEBUG_LINE(c2, c3, 128, 0, 128)
// DRAW_DEBUG_LINE(c3, c4, 128, 0, 128)
// DRAW_DEBUG_LINE(c4, c1, 128, 0, 128)
// // Draw top lines
// DRAW_DEBUG_LINE(d1, d2, 128, 0, 128)
// DRAW_DEBUG_LINE(d2, d3, 128, 0, 128)
// DRAW_DEBUG_LINE(d3, d4, 128, 0, 128)
// DRAW_DEBUG_LINE(d4, d1, 128, 0, 128)
// // Draw uprights
// DRAW_DEBUG_LINE(c1, d1, 128, 0, 128)
// DRAW_DEBUG_LINE(c2, d2, 128, 0, 128)
// DRAW_DEBUG_LINE(c3, d3, 128, 0, 128)
// DRAW_DEBUG_LINE(c4, d4, 128, 0, 128)
//
// ENDPROC
#ENDIF
///
///
/// GENERAL HELP FUNCTIONS
///
///
/// PURPOSE:
/// Set a peds position and heading safely ie check its ok then move it and set its heading
/// PARAMS:
/// index - The ped to move
/// pos - The position to move it to
/// dir - The Heading to set
PROC SET_PED_POS(PED_INDEX index, VECTOR pos, FLOAT dir)
IF IS_PED_UNINJURED(index)
CLEAR_PED_TASKS(index)
ENDIF
SAFE_TELEPORT_ENTITY(index, pos, dir)
ENDPROC
/// PURPOSE:
/// Requests a model and waits for it to load
/// PARAMS:
/// _modname - The name of the model to load
/// _debugstring - used to debug
/// i - used to debug
/// RETURNS:
/// TRUE when the model is loaded
FUNC BOOL REQUEST_AND_CHECK_MODEL(MODEL_NAMES _modname, STRING _debugstring, INT i = 0)
REQUEST_MODEL(_modname)
IF NOT Is_String_Null_Or_Empty(_debugstring)
AND i <> -1
#IF IS_DEBUG_BUILD
SK_PRINT_INT(_debugstring, i)
#ENDIF
ENDIF
IF HAS_MODEL_LOADED(_modname)
#IF IS_DEBUG_BUILD
SK_PRINT("MODEL LOADED")
#ENDIF
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Unloads a model - Sets it as no longer needed
/// PARAMS:
/// _modname - The model to unload
PROC UNLOAD_MODEL(MODEL_NAMES _modname, BOOL bCheckLoaded = TRUE)
IF bCheckLoaded
IF HAS_MODEL_LOADED(_modname)
SET_MODEL_AS_NO_LONGER_NEEDED(_modname)
ENDIF
ELSE
SET_MODEL_AS_NO_LONGER_NEEDED(_modname)
ENDIF
ENDPROC
/// PURPOSE:
/// Spawns a ped and returns true if it was succesful. Requests the model and unloads it
/// PARAMS:
/// pedindex - The PED_INDEX to write the newly create ped to
/// model - The model to load and use to create the ped
/// pos - The position the ped should be created
/// dir - The heading the ped should have when created
/// bUnloadAfterSpawn - If true we unload the model after spawning the ped
/// bFreeze - if true we freeze the ped after spawning
/// bTempEvents - if true we block temp events
/// bTargetable - if false we set the ped to not be targetted
/// RETURNS:
/// TRUE if the ped was created
FUNC BOOL SPAWN_PED(PED_INDEX &pedindex, MODEL_NAMES model, VECTOR pos, FLOAT dir, BOOL bUnloadAfterSpawn = TRUE, BOOL bFreeze = FALSE, BOOL bTempEvents = TRUE, BOOL bTargetable = TRUE)
IF NOT DOES_ENTITY_EXIST(pedindex)
IF REQUEST_AND_CHECK_MODEL(model,"Loading")
pedindex = CREATE_PED(PEDTYPE_MISSION, model, pos, dir)
//SET_PED_DEFAULT_COMPONENT_VARIATION(pedindex)
IF IS_PED_UNINJURED(pedindex)
#IF IS_DEBUG_BUILD SK_PRINT("PED CREATED !") #ENDIF
IF bFreeze
FREEZE_ENTITY_POSITION(pedindex, TRUE)
ENDIF
IF bTempEvents
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(pedindex, bTempEvents)
ENDIF
IF NOT bTargetable
SET_PED_CAN_BE_TARGETTED(pedindex, bTargetable)
ENDIF
IF bUnloadAfterSpawn
UNLOAD_MODEL(model)
ENDIF
RETURN TRUE
ENDIF
ENDIF
ELSE
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Spawns a vehicle and returns true if it was succesful - why does the is mission entity check return true
/// no matter what the out come of said check?
/// PARAMS:
/// vehicleindex - The VEHICLE_INDEX to write the newly create vehicle to
/// model - The model to load and use to create the vehicle
/// pos - The position the vehicle should be created
/// dir - The heading the vehicle should have when created
/// RETURNS:
/// TRUE if the vehicle was created
FUNC BOOL SPAWN_VEHICLE(VEHICLE_INDEX &vehicleindex, MODEL_NAMES model, VECTOR pos, FLOAT dir, BOOL bUnloadAfterSpawn = TRUE)
IF NOT DOES_ENTITY_EXIST(vehicleindex)
IF REQUEST_AND_CHECK_MODEL(model,"Loading")
vehicleindex = CREATE_VEHICLE(model, pos, dir)
IF DOES_ENTITY_EXIST(vehicleindex)
IF NOT IS_ENTITY_A_MISSION_ENTITY(vehicleindex)
SET_ENTITY_AS_MISSION_ENTITY(vehicleindex)
ENDIF
SET_VEHICLE_ON_GROUND_PROPERLY(vehicleindex)
IF bUnloadAfterSpawn
UNLOAD_MODEL(model)
ENDIF
RETURN TRUE
ENDIF
ENDIF
ELSE
IF IS_VEHICLE_OK(vehicleindex)
SET_ENTITY_COORDS(vehicleindex, pos)
SET_ENTITY_HEADING(vehicleindex, dir)
ENDIF
IF NOT IS_ENTITY_A_MISSION_ENTITY(vehicleindex)
SET_ENTITY_AS_MISSION_ENTITY(vehicleindex)
RETURN TRUE
ELSE
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Spawns a ped inside a vehicle
/// PARAMS:
/// pedindex - The index to write the newly created ped back to (ref)
/// Car - The vehicle to create the ped in
/// modelName - The model of the ped to create
/// seat - the seat to create the ped in
/// bUnloadAfterSpawn - should we unload the ped model after creation
/// RETURNS:
/// TRUE if the ped was spawned correctly
FUNC BOOL SPAWN_PED_IN_VEHICLE(PED_INDEX &pedindex, VEHICLE_INDEX Car, MODEL_NAMES modelName, VEHICLE_SEAT seat = VS_DRIVER, BOOL bUnloadAfterSpawn = TRUE)
IF IS_VEHICLE_OK(Car)
IF NOT DOES_ENTITY_EXIST(pedindex)
IF REQUEST_AND_CHECK_MODEL(modelName,"Loading")
pedindex = CREATE_PED_INSIDE_VEHICLE(Car, PEDTYPE_MISSION, modelName, seat)
IF DOES_ENTITY_EXIST(pedindex)
IF bUnloadAfterSpawn
UNLOAD_MODEL(modelName)
ENDIF
RETURN TRUE
ENDIF
ENDIF
ELSE
RETURN TRUE
ENDIF
ELSE
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Spawns an object. And activates its physics
/// PARAMS:
/// objectindex - The OBJECT_INDEX to write the newly create object to
/// model - The model to load and use to create the object
/// pos - The position the object should be created
/// dir - The heading the object should have when created
/// RETURNS:
/// TRUE if the object was created
FUNC BOOL SPAWN_OBJECT(OBJECT_INDEX &objectindex, MODEL_NAMES model, VECTOR pos, FLOAT dir = 0.0, BOOL bUnloadAfterSpawn = TRUE)
IF NOT DOES_ENTITY_EXIST(objectindex)
IF REQUEST_AND_CHECK_MODEL(model,"Loading")
objectindex = CREATE_OBJECT(model, pos)
IF DOES_ENTITY_EXIST(objectindex)
SET_ENTITY_HEADING(objectindex, dir)
ACTIVATE_PHYSICS(objectindex)
IF bUnloadAfterSpawn
UNLOAD_MODEL(model)
ENDIF
RETURN TRUE
ENDIF
ENDIF
ELSE
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
//PURPOSE:
/// PURPOSE:
/// Checkes to see if a ped is in a given vehicle, also does alive checks.
/// Returns TRUE if the given ped is in the given vehicle and they are all alive and well
/// PARAMS:
/// ped - Ped to check
/// veh - The vehicle to check they are in
/// RETURNS:
/// TRUE if the ped is in the vehicle and they are both alive and well
FUNC BOOL IS_SAFE_PED_IN_VEHICLE(PED_INDEX ped, VEHICLE_INDEX veh)
IF veh != NULL
IF IS_VEHICLE_OK(veh)
IF IS_PED_UNINJURED(ped)
IF IS_PED_IN_VEHICLE(ped,veh)
RETURN TRUE
ENDIF
ENDIF
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Adds a blip to a location safly checking to see that its not in existance before creatinging it
/// PARAMS:
/// blipIn - The blip index to write the newly created blip to
/// pos - the position to set the blip at
/// route - should the blip have a GPS route
PROC ADD_BLIP_LOCATION_WITH_NAME(BLIP_INDEX &blipIn, VECTOR pos, BOOL route = TRUE, BOOL bAddNameToBlip = FALSE, STRING sBlipName = NULL)
IF NOT DOES_BLIP_EXIST(blipIn)
blipIn = CREATE_COORD_BLIP(pos, BLIPPRIORITY_MED, route)
IF bAddNameToBlip
SET_BLIP_NAME_FROM_TEXT_FILE(blipIn, sBlipName) //Tooth
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Print a warning God text string and expires a bool when the warning has been shown
/// PARAMS:
/// WarnObj - the text key of the wanrning
/// expire - the bool to change
PROC PRINT_WARNING_OBJ(STRING WarnObj, BOOL &expire)
IF NOT expire
PRINT_NOW(WarnObj, DEFAULT_GOD_TEXT_TIME,0)
expire = TRUE
ENDIF
ENDPROC
/// PURPOSE:
/// Spawns and sets up the ped with a debug name
/// PARAMS:
/// index - The PED_INDEX to write the newly created ped to
/// pos - The postion to create the ped at
/// fDir - The heading to give the new ped
/// modelName - The model to create the ped with
/// i - Debug number for Debug name
/// _name - The Debug name
/// RETURNS:
/// TRUE if the ped was created
FUNC BOOL SETUP_PED(PED_INDEX &index, VECTOR pos, FLOAT fDir, MODEL_NAMES modelName, INT i, STRING _name)
IF SPAWN_PED(index, modelName, pos, fDir)
#IF IS_DEBUG_BUILD
SK_PRINT("SPAWNED")
#ENDIF
IF IS_PED_UNINJURED(index)
TEXT_LABEL tDebugName = _name
tDebugName += i
#IF IS_DEBUG_BUILD
SK_PRINT(tDebugName)
#ENDIF
SET_PED_NAME_DEBUG(index, tDebugName)
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Gets the heading between to vectors
/// PARAMS:
/// V1 - First vector
/// V2 - Second vector
/// RETURNS:
/// FLOAT - the heading between the two
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
///-----------------------------------------------------------------------------------
/// MISSION FUNCTIONS
///-----------------------------------------------------------------------------------
/// PURPOSE:
/// Tells a ped to leave a specified vehicle
/// performs dead checks on the ped and vehicle
/// PARAMS:
/// ped - The ped to leave the vechicle
/// veh - The vehicle said ped is leaving
PROC GIVE_LEAVE_VEHICLE_ORDER(PED_INDEX ped, VEHICLE_INDEX veh)
IF IS_VEHICLE_OK(veh)
IF IS_PED_UNINJURED(ped)
TASK_LEAVE_VEHICLE(ped, veh)
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Tells a ped to enter a specified vehicle
/// performs dead checks on the ped and vehicle
/// PARAMS:
/// ped - The ped to leave the vechicle
/// veh - The vehicle said ped is leaving
/// seat - Seate the ped should enter the car from
PROC GIVE_ENTER_VEHICLE_ORDER(PED_INDEX ped, VEHICLE_INDEX veh, VEHICLE_SEAT seat = VS_DRIVER)
IF IS_VEHICLE_OK(veh)
IF IS_PED_UNINJURED(ped)
TASK_ENTER_VEHICLE(ped, veh, DEFAULT_TIME_BEFORE_WARP, seat)
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Gives a ped a waypoint task
/// PARAMS:
/// ped - The ped to give the task to
/// waypoint - The name of the waypoint rec to give the ped
PROC GIVE_WAYPOINT_TASK(PED_INDEX ped, STRING waypoint, INT iStartPoint = 0 , EWAYPOINT_FOLLOW_FLAGS eFollow = EWAYPOINT_DEFAULT)
IF IS_PED_UNINJURED(ped)
FREEZE_ENTITY_POSITION(ped, FALSE)
CLEAR_PED_TASKS(ped)
TASK_FOLLOW_WAYPOINT_RECORDING(ped, waypoint, iStartPoint, eFollow)
ENDIF
ENDPROC
PROC GIVE_NAVMESH_TASK(PED_INDEX ped, VECTOR vGoto, FLOAT moveBlend = PEDMOVEBLENDRATIO_WALK, INT warpTime = DEFAULT_TIME_BEFORE_WARP)
IF IS_PED_UNINJURED(ped)
FREEZE_ENTITY_POSITION(ped, FALSE)
CLEAR_PED_TASKS(ped)
TASK_FOLLOW_NAV_MESH_TO_COORD(ped, vGoto, moveBlend, warpTime)
ENDIF
ENDPROC
/// PURPOSE:
/// Gives a ped an attack order after the player has been spotted
/// Only called when the player fails the mission for getting spotted or attacking a ped
/// and possibly when the player has completed the sex scene section
/// PARAMS:
/// ped - The ped to give the order to
PROC GIVE_PED_ATTACK_ORDER(PED_INDEX ped)
IF IS_PED_UNINJURED(ped)
IF NOT IsPedPerformingTask(ped, SCRIPT_TASK_COMBAT)
FREEZE_ENTITY_POSITION(ped, FALSE)
CLEAR_PED_TASKS(ped)
TASK_COMBAT_PED(ped, PLAYER_PED_ID())
SET_PED_KEEP_TASK(ped, TRUE)
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Tells a ped to smart flee 200m from the player
/// Checks to see if the task is already being performed
/// Checks the ped is alive
/// PARAMS:
/// ped - the ped to flee
PROC GIVE_PED_FLEE_ORDER(PED_INDEX ped, BOOL bClearTasks = TRUE)
IF IS_PED_UNINJURED(ped)
IF NOT IsPedPerformingTask(ped, SCRIPT_TASK_SMART_FLEE_PED)
FREEZE_ENTITY_POSITION(ped, FALSE)
IF bClearTasks
CLEAR_PED_TASKS(ped)
ENDIF
TASK_SMART_FLEE_PED(ped, PLAYER_PED_ID(), 200, -1)
SET_PED_KEEP_TASK(ped, TRUE)
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Checks that 2 entities are at the same height - within
/// 1.5m
/// PARAMS:
/// e1 - first entity
/// e2 - second entity
/// RETURNS:
/// TRUE if the entities are at the same height
FUNC BOOL ARE_ENTITYS_AT_SAME_HEIGHT(ENTITY_INDEX e1, ENTITY_INDEX e2)
VECTOR vE1 = GET_ENTITY_COORDS(e1)
VECTOR vE2 = GET_ENTITY_COORDS(e2)
FLOAT fDiff = ABSF(vE1.z - vE2.z) //want the absolute difference so it doesnt matter which entitys height was taken away first
IF fDiff <= 1.5
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Checks that the player is with in range of the hunter used when playing dialogue
/// PARAMS:
/// distance - The distance the player must be with in - defaults to 10.0
/// RETURNS:
/// TRUE if the player is with in the distance
FUNC BOOL IS_IN_CONV_DISTANCE(PED_INDEX ped, FLOAT distance = 10.0)
IF ped = NULL
RETURN TRUE
ENDIF
IF IS_PED_UNINJURED(PLAYER_PED_ID())
AND IS_PED_UNINJURED(ped)
// #IF IS_DEBUG_BUILD SK_PRINT_FLOAT(" DISTANCE BETWEEN CONVO === ", GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), ped, FALSE))#ENDIF
IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), ped, FALSE) <= distance
AND ARE_ENTITYS_AT_SAME_HEIGHT(ped, PLAYER_PED_ID())
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Creates a conversation and then displays an objective
/// Expires a bool when the conversation has been created
/// assume the player is talking to another ped
/// kills the conversation if its started and the peds are too far away
/// PARAMS:
/// ped - the ped the conversation is with - pass in NULL if i doesnt matter where the other ped is in relation to the player
/// bExpire - The bool to expire when the conversation has been created (ref)
/// sConvo - the string of the conversation to play
/// sObj - the text key for the obj
/// distance - the distance the player and ped need to be in before the convostation happens
PROC DO_CONVO_WITH_OBJ(PED_INDEX ped, BOOL &bExpire, STRING sConvo, STRING sObj, FLOAT distance = 10.0)
IF NOT bObjectiveShown
// #IF IS_DEBUG_BUILD SK_PRINT(sConvo) #ENDIF
// #IF IS_DEBUG_BUILD SK_PRINT(" NOT bObjectiveShown") #ENDIF
//
IF NOT bExpire
// #IF IS_DEBUG_BUILD SK_PRINT("NOT bExpire") #ENDIF
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
AND IS_SCREEN_FADED_IN()
IF IS_IN_CONV_DISTANCE(ped, distance)
bExpire = CREATE_CONVERSATION(s_conversation_peds, sTextBlock, sConvo, CONV_PRIORITY_MEDIUM)
ENDIF
ENDIF
ELSE
IF NOT IS_IN_CONV_DISTANCE(ped, distance)
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ENDIF
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
OR GET_PROFILE_SETTING(PROFILE_DISPLAY_SUBTITLES) = 0
PRINT_OBJ(sObj, bObjectiveShown)
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Creates a conversation and then displays an objective
/// And then creates another conversation
/// Expires a bool when each of the conversation have been created
/// assume the player is talking to another ped
/// kills the conversation if its started and the peds are too far away
/// PARAMS:
/// ped - the ped the conversation is with - pass in NULL if i doesnt matter where the other ped is in relation to the player
/// bExpire - The expiry bool for the first conversation (ref)
/// bExpireAfterConv - bool for the second conversation (ref)
/// sConvo - the string of the 1st conversation to play
/// sConvToPlayAfterObj - the string 2nd of the conversation to play
/// sObj - the text key for the obj
/// distance - the distance the player and ped need to be in before the convostation happens
PROC DO_TWO_CONVO_WITH_OBJ(PED_INDEX ped, BOOL &bExpire, BOOL &bExpireAfterConv, STRING sConvo, STRING sConvToPlayAfterObj, STRING sObj, FLOAT distance = 10.0)
IF NOT bObjectiveShown
// #IF IS_DEBUG_BUILD SK_PRINT(" NOT bObjectiveShown") #ENDIF
IF NOT bExpire
// #IF IS_DEBUG_BUILD SK_PRINT(sConvo) #ENDIF
// #IF IS_DEBUG_BUILD SK_PRINT("NOT bExpire") #ENDIF
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
AND IS_SCREEN_FADED_IN()
IF IS_IN_CONV_DISTANCE(ped, distance)
bExpire = CREATE_CONVERSATION(s_conversation_peds, sTextBlock, sConvo, CONV_PRIORITY_MEDIUM)
ENDIF
ENDIF
ELSE
IF NOT IS_IN_CONV_DISTANCE(ped, distance)
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ENDIF
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
OR GET_PROFILE_SETTING(PROFILE_DISPLAY_SUBTITLES) = 0
PRINT_OBJ(sObj, bObjectiveShown)
ENDIF
ENDIF
ELSE
IF NOT IS_THIS_PRINT_BEING_DISPLAYED(sObj)
OR GET_PROFILE_SETTING(PROFILE_DISPLAY_SUBTITLES) = 0
IF NOT IS_STRING_NULL_OR_EMPTY(sConvToPlayAfterObj)
IF NOT bExpireAfterConv
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF IS_IN_CONV_DISTANCE(ped, distance)
bExpireAfterConv = CREATE_CONVERSATION(s_conversation_peds, sTextBlock, sConvToPlayAfterObj, CONV_PRIORITY_MEDIUM)
ENDIF
ENDIF
ELSE
IF NOT IS_IN_CONV_DISTANCE(ped, distance)
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ENDIF
ENDIF
ELSE
bExpireAfterConv = TRUE
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Creates a conversation then expires a bool when the conversation has been created
/// PARAMS:
/// ped - the ped the conversation is with - pass in NULL if i doesnt matter where the other ped is in relation to the player
/// bExpire - The expiry bool for the first conversation (ref)
/// sConvo - the string of the conversation to play
/// distance - the distance the player and ped need to be in before the convostation happens
/// RETURNS:
/// true when the bool is expired
FUNC BOOL DO_CONVO(PED_INDEX ped, BOOL &bExpire, STRING sConvo, FLOAT distance = 10.0, enumConversationPriority priority = CONV_PRIORITY_MEDIUM)
IF NOT bExpire
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
AND IS_SCREEN_FADED_IN()
IF IS_IN_CONV_DISTANCE(ped, distance)
bExpire = CREATE_CONVERSATION(s_conversation_peds, sTextBlock, sConvo, priority)
ENDIF
ENDIF
ELSE
IF NOT IS_IN_CONV_DISTANCE(ped, distance)
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ENDIF
ENDIF
RETURN bExpire
ENDFUNC
// -----------------------------------------------------------------------------------------------------------
// Script Fail
// -----------------------------------------------------------------------------------------------------------
/// PURPOSE:
/// Called when the player has failed
/// deletes blips and clears the screen of text and conversations are ended
/// PARAMS:
/// fail - An Enum of the fail reason used in a switch statment to pick the correct text to display
PROC MISSION_FAILED(FAILED_REASONS fail = FR_NONE)
CLEAR_PRINTS()
KILL_ANY_CONVERSATION()
SWITCH fail
CASE FR_NONE
BREAK
CASE FR_KICKOFFSHOP
sFailReason = "PRD_FKICKOFF"
BREAK
CASE FR_LEFT
sFailReason = "PRD_FLEFT"
BREAK
CASE FR_NO_CASH
sFailReason = "PRD_CASH"
BREAK
CASE FR_COPS
sFailReason = "PRD_COPS"
BREAK
ENDSWITCH
eMissionState = MS_FAILED
eState = SS_INIT
ENDPROC
///-----------------------------------------------------------------------------------
/// STATE MACHINES
///-----------------------------------------------------------------------------------
/// PURPOSE:
/// Sets the mission check point
PROC SET_CHECKPOINT()
ENDPROC
/// PURPOSE:
/// Turn off the ambient services
PROC SERVICES_TOGGLE(BOOL bOn)
//Wanted
ENABLE_DISPATCH_SERVICE(DT_POLICE_AUTOMOBILE, bOn)
ENABLE_DISPATCH_SERVICE(DT_POLICE_HELICOPTER, bOn)
ENABLE_DISPATCH_SERVICE(DT_FIRE_DEPARTMENT, bOn)
ENABLE_DISPATCH_SERVICE(DT_SWAT_AUTOMOBILE, bOn)
ENABLE_DISPATCH_SERVICE(DT_AMBULANCE_DEPARTMENT, bOn)
IF bOn
SET_WANTED_LEVEL_MULTIPLIER(1.0)
SET_MAX_WANTED_LEVEL(5)
ELSE
SET_MAX_WANTED_LEVEL(0)
SET_WANTED_LEVEL_MULTIPLIER(0)
ENDIF
ENDPROC
/// PURPOSE:
/// Loads a scene around a point used to the player
/// seeing the map stream in when starting a replay or debug skipping
/// PARAMS:
/// pos - the position to stream the scene around at
/// rad - the radius of the scene to load
PROC LOAD_SCENE_SKIP(VECTOR pos, FLOAT rad)
NEW_LOAD_SCENE_START_SPHERE(pos, rad)
INT i_load_scene_timer = GET_GAME_TIMER()
WHILE (NOT IS_NEW_LOAD_SCENE_LOADED()) AND (GET_GAME_TIMER() - i_load_scene_timer < 12000)
WAIT(0)
ENDWHILE
NEW_LOAD_SCENE_STOP()
ENDPROC
/// PURPOSE:
/// Adds peds for dialogue based off the Mission state
PROC ADD_PEDS_FOR_DIALOGUE()
ADD_CURRENT_PLAYER_FOR_DIALOGUE(s_conversation_peds)
ENDPROC
/// PURPOSE:
/// Sets up a stage requirment via a switch using an ENUM
/// Stage requirements include the hunter the saleform or the mission text etc.
/// PARAMS:
/// missionReq - The Enum of the required mission element e.g. RQ_TEXT
/// pos - The position the thing is spawned at - if no position is required the use vSafeVec
/// If spawning multiple things at once then have the postions already in the switch statement
/// as calling this func multiple times wont work as well with the other function that calls it
/// dir - This is the heading or direction you want the thing to face when spawned. Defaults to
/// 0.0
/// RETURNS:
/// TRUE when the thing required is created/loaded/setup or whatever.
///
FUNC BOOL SETUP_STAGE_REQUIREMENTS(MISSION_REQ missionReq,VECTOR pos, FLOAT dir=0.0)
SWITCH missionReq
CASE RQ_NONE
IF ARE_VECTORS_ALMOST_EQUAL(pos, vSafeVec)
AND dir = 0.0
RETURN TRUE
ENDIF
BREAK
CASE RQ_TEXT
REQUEST_ADDITIONAL_TEXT(sGodText, MISSION_TEXT_SLOT)
REQUEST_ADDITIONAL_TEXT(sTextBlock, MISSION_DIALOGUE_TEXT_SLOT)
IF HAS_ADDITIONAL_TEXT_LOADED(MISSION_TEXT_SLOT)
AND HAS_ADDITIONAL_TEXT_LOADED(MISSION_DIALOGUE_TEXT_SLOT)
#IF IS_DEBUG_BUILD
SK_PRINT("RQ_TEXT")
#ENDIF
RETURN TRUE
ENDIF
#IF IS_DEBUG_BUILD
SK_PRINT("TEXT FAILED")
#ENDIF
BREAK
ENDSWITCH
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Used to setup a mission stage(or state if you call it that) Uses a switch statement to pick which
/// set of SETUP_STAGE_REQUIREMENTS() to call. It checks to see if all the stage requirements are
/// setup and then does any other setup needed. such as setting the players position or switching a
/// bool to true or false etc.
/// Handles setting up stuff needed after a Z or p skip first then the normal setup takes place
/// PARAMS:
/// eStage - The mission state/stage that needs setting up
/// bJumped - Wether or not the state/stage has been jumped to using Z or P skips
/// RETURNS:
/// TRUE if everything required for a stage is loaded properly
FUNC BOOL SETUP_MISSION_STAGE(MISSION_STATE eStage, BOOL bJumped = FALSE)
ADD_PEDS_FOR_DIALOGUE()
SWITCH eStage
CASE MS_SET_UP
IF bJumped //If we have jumped to this stage set up everything that might of been cleared buy the jump to funtions
bJumpSkip = FALSE // everything has been setup that is not key to this stage but is required to carry the mission on from this stage so reset the jump flag
RC_END_Z_SKIP()
ELSE
IF SETUP_STAGE_REQUIREMENTS(RQ_TEXT, vSafeVec)
RETURN TRUE //all mission stage requirements set up return true and activate stage
ENDIF
ENDIF
#IF IS_DEBUG_BUILD
SK_PRINT("MS_SET_UP, FAILED")
#ENDIF
BREAK
CASE MS_GET_TO_CLOTHES
IF bJumped //If we have jumped to this stage set up everything that might of been cleared buy the jump to funtions
SET_PED_POS(PLAYER_PED_ID(), <<-1339.7863, -1277.5099, 3.8874>>, 261.2839)
bJumpSkip = FALSE // everything has been setup that is not key to this stage but is required to carry the mission on from this stage so reset the jump flag
RC_END_Z_SKIP()
ELSE
RETURN TRUE //all mission stage requirements set up return true and activate stage
ENDIF
#IF IS_DEBUG_BUILD
SK_PRINT("MS_STEAL, FAILED")
#ENDIF
BREAK
CASE MS_BUY
IF bJumped //If we have jumped to this stage set up everything that might of been cleared buy the jump to funtions
SET_PED_POS(PLAYER_PED_ID(), vMasks, 261.2839)
bJumpSkip = FALSE // everything has been setup that is not key to this stage but is required to carry the mission on from this stage so reset the jump flag
RC_END_Z_SKIP()
ELSE
RETURN TRUE //all mission stage requirements set up return true and activate stage
ENDIF
#IF IS_DEBUG_BUILD
SK_PRINT("MS_STEAL, FAILED")
#ENDIF
BREAK
ENDSWITCH
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Sits in the NEXT_STAGE() function and moniters for assest that
/// should be unloaded based on the mission state
/// PARAMS:
/// state - the current state we should evaluate
PROC MONITER_UNLOAD_ASSETS(MISSION_STATE state)
SWITCH state
CASE MS_SET_UP
BREAK
ENDSWITCH
ENDPROC
// ===========================================================================================================
// Termination
// ===========================================================================================================
// -----------------------------------------------------------------------------------------------------------
// Script Cleanup
// -----------------------------------------------------------------------------------------------------------
/// PURPOSE:
/// Unloads all models
PROC UNLOAD_ALL_MODELS()
ENDPROC
/// PURPOSE:
/// Unloads all waypoints
PROC UNLOAD_ALL_WAYPOINTS()
ENDPROC
/// PURPOSE:
/// Unloads all anims
PROC UNLOAD_ANIMS()
ENDPROC
/// PURPOSE:
/// Unload all vehicle recordings
PROC UNLOAD_ALL_CAR_RECS()
ENDPROC
/// PURPOSE:
/// Deletes any blips that are valid
PROC REMOVE_BLIPS()
SAFE_REMOVE_BLIP(biBlip)
ENDPROC
/// PURPOSE:
/// Standard delete all function used the wait for fail state
/// Safe deletes all peds, props and vehicles
PROC DELETE_ALL()
ENDPROC
PROC RELEASE_ALL()
ENDPROC
/// PURPOSE:
/// Deletes all mission entities and any other clean up
/// This is used to clear the mission when P or Z skipping
PROC CLEANUP(BOOL bDelAll = TRUE)
IF bDelAll
#IF IS_DEBUG_BUILD SK_PRINT("CLEANUP = DEL ALL") #ENDIF
ELSE
#IF IS_DEBUG_BUILD SK_PRINT("CLEANUP = RELEASE ") #ENDIF
ENDIF
WAIT_FOR_CUTSCENE_TO_STOP()
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
REMOVE_BLIPS()
UNLOAD_ALL_MODELS()
UNLOAD_ALL_WAYPOINTS()
UNLOAD_ANIMS()
UNLOAD_ALL_CAR_RECS()
IF bDelAll
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
CLEAR_PRINTS()
DELETE_ALL()
ELSE
RELEASE_ALL()
ENDIF
SET_GPS_MULTI_ROUTE_RENDER(FALSE)
IF DOES_CAM_EXIST(camMain)
RENDER_SCRIPT_CAMS(FALSE,FALSE)
DESTROY_CAM(camMain)
ENDIF
ENDPROC
/// PURPOSE:
/// Cleans up mission entities, releases the entity to be cleaned up by population
/// and will give a suitable task to the peds before clean up
PROC Script_Cleanup()
// CLEAR_ADDITIONAL_TEXT(MISSION_DIALOGUE_TEXT_SLOT,TRUE)
SERVICES_TOGGLE(TRUE)
RESET_ALL_BATTLEBUDDY_BEHAVIOUR_REQUESTS()
CLEANUP(FALSE)
TERMINATE_THIS_THREAD()
ENDPROC
//***************************************
// :MISSION FLOW FUNC:
//***************************************
//PURPOSE: Advances or reverses the mission stage
PROC NEXT_STAGE( BOOL bReverse = FALSE)
MONITER_UNLOAD_ASSETS(eMissionState)
iMissionState = ENUM_TO_INT(eMissionState)
IF NOT bReverse
eMissionState = INT_TO_ENUM(MISSION_STATE, (iMissionState + 1))
ELSE
IF iMissionState > 0
eMissionState = INT_TO_ENUM(MISSION_STATE, (iMissionState - 1))
ENDIF
ENDIF
bObjectiveShown = FALSE
eState = SS_INIT
ENDPROC
// -----------------------------------------------------------------------------------------------------------
// Script Pass
// -----------------------------------------------------------------------------------------------------------
/// PURPOSE:
/// Pass function calls cleanup and termination
/// if the player debug passes this function warps him to the end
/// of the chasem, it will then complete
PROC Script_Passed()
CLEAR_PRINTS()
// KILL_ANY_CONVERSATION()
Mission_Flow_Mission_Passed()
Script_Cleanup()
ENDPROC
// -----------------------------------------------------------------------------------------------------------
// Script Fail
// -----------------------------------------------------------------------------------------------------------
PROC RESET_OUTFITS_ON_FAIL()
CPRINTLN(DEBUG_MISSION, " Resetting masks ")
g_savedGlobals.sPlayerData.sInfo.eFBI4MaskName[CHAR_MICHAEL] = DUMMY_PED_COMP
g_savedGlobals.sPlayerData.sInfo.eFBI4MaskName[CHAR_FRANKLIN] = DUMMY_PED_COMP
g_savedGlobals.sPlayerData.sInfo.eFBI4MaskName[CHAR_TREVOR] = DUMMY_PED_COMP
// g_sShopSettings.bFBI4PrepComplete = FALSE
ENDPROC
/// PURPOSE:
/// Waits for the screen to fade out then updates failed reason
PROC FAILED_WAIT_FOR_FADE()
SWITCH eState
CASE SS_INIT
CLEAR_PRINTS()
CLEAR_HELP()
REMOVE_BLIPS()
/* (not supported for story missions atm)
// set if we want to delay the fade
BOOL bDelayFade
bDelayFade = FALSE
IF NOT IS_STRING_NULL_OR_EMPTY(sFailReason)
bDelayFade = TRUE // delay the fade if we failed for one of these reasons
ENDIF
*/
IF NOT IS_STRING_NULL_OR_EMPTY(sFailReason)
IF ARE_STRINGS_EQUAL(sFailReason, "PRE_FKICKOFF")
WHILE (GET_GAME_TIMER() - iWantedFailTimer) < 3000
WAIT(0)
ENDWHILE
ENDIF
ENDIF
IF NOT IS_STRING_NULL_OR_EMPTY(sFailReason)
MISSION_FLOW_MISSION_FAILED_WITH_REASON(sFailReason)
ELSE
MISSION_FLOW_MISSION_FAILED()
ENDIF
eState = SS_ACTIVE
BREAK
CASE SS_ACTIVE
IF GET_MISSION_FLOW_SAFE_TO_CLEANUP()
// Do a check here to see if we need to warp the player at all
// (only set the fail warp locations if we can't leave the player where he was)
//
RESET_OUTFITS_ON_FAIL()
DELETE_ALL()
Script_Cleanup()
ELSE
// not finished fading out
// you may want to handle dialogue etc here.
ENDIF
BREAK
ENDSWITCH
ENDPROC
//------------------------------------------------------------------------------------
// MISSION STATES
//------------------------------------------------------------------------------------
/// PURPOSE:
/// Jumps the mission to a specific stage
/// PARAMS:
/// stage - The state to jump to
PROC JUMP_TO_STAGE(MISSION_STATE stage)
RC_START_Z_SKIP()
bJumpSkip = TRUE //Tells the mission stage setup function that we have just jumped and special setup is required
eMissionState = stage
IF eMissionState = MS_SET_UP
#IF IS_DEBUG_BUILD SK_PRINT("eMission state = MSS_SETUP GOING TO INTRO ") #ENDIF
eMissionState = MS_SET_UP
ENDIF
// bLoadingFinCutscene = FALSE
bObjectiveShown = FALSE
eState = SS_INIT
CLEANUP() //delete everything
ENDPROC
/// PURPOSE:
/// Adds points to a poly
/// PARAMS:
/// polys - The points to be added to the poly
/// count - the number of points to be added to the poly
PROC POPULATE_POLY_CHECKS(VECTOR &polys[], INT count = MAX_POLY_TEST_VERTS)
OPEN_TEST_POLY(mAreaCheck1)
INT i
FOR i = 0 TO (count-1)
ADD_TEST_POLY_VERT(mAreaCheck1, polys[i])
ENDFOR
CLOSE_TEST_POLY(mAreaCheck1)
COPY_EXPANDED_POLY(mAreaCheck2, mAreaCheck1, 50)
ENDPROC
/// PURPOSE:
/// Creates a poly check area using a local array
PROC CREATE_POLY_CHECKS()
VECTOR polys[MAX_POLY_TEST_VERTS]
polys[0] = << 344.0985, -1605.1539, 28.2928 >>
polys[1] = << 365.6985, -1580.4351, 28.2928 >>
polys[2] = << 407.9943, -1616.2589, 28.2928 >>
polys[3] = << 387.3322, -1641.2583, 29.0912 >>
POPULATE_POLY_CHECKS(polys, 4)
ENDPROC
PROC POPULATE_VEHICLES()
ENDPROC
PROC POPULATE_OBJECTIVES()
mObj[CHAR_MICHAEL] = "PRD_BUYM"
mObj[CHAR_FRANKLIN] = "PRD_BUYF"
mObj[CHAR_TREVOR] = "PRD_BUYT"
ENDPROC
/// PURPOSE:
/// Initialises all variables and structs
PROC POPULATE_STUFF()
POPULATE_VEHICLES()
POPULATE_OBJECTIVES()
CREATE_POLY_CHECKS()
ENDPROC
/// PURPOSE:
/// Sets the Game world time after a replay/shit skip
PROC SET_TIME_FOR_REPLAY()
IF g_bShitskipAccepted
ELSE
ENDIF
ENDPROC
///PURPOSE:
/// Initiate the mission and load the things needed
/// for the immediate gameplay
/// The skip menu is initialsed here
/// And if a replay is being done then we init and load assests for the check point
PROC INITMISSION()
SWITCH eState
CASE SS_INIT
//DO_SCREEN_FADE_OUT(0)
// #IF IS_DEBUG_BUILD
// SET_DEBUG_LINES_AND_SPHERES_DRAWING_ACTIVE (TRUE)
// #ENDIF
#IF IS_DEBUG_BUILD SK_PRINT("INIT MISSION - THIS WILL LOOP") #ENDIF
IF SETUP_MISSION_STAGE(eMissionState)
IF IS_PLAYER_PLAYING(PLAYER_ID())
AND NOT IS_PLAYER_DEAD(PLAYER_ID())
#IF IS_DEBUG_BUILD SK_PRINT("Wanted level cleared ") #ENDIF
CLEAR_PLAYER_WANTED_LEVEL(PLAYER_ID())
ENDIF
#IF IS_DEBUG_BUILD
s_skip_menu[0].sTxtLabel = "MS_GET_TO_CLOTHES"
s_skip_menu[1].sTxtLabel = "MS_BUY"
#ENDIF
INT iTimeOut
// SERVICES_TOGGLE(FALSE)
INIT_BATTLEBUDDY_BEHAVIOUR_FOR_MISSION(SP_MISSION_FBI_4_PREP_4)
IF IS_REPLAY_IN_PROGRESS()
VEHICLE_INDEX mReplayVehicle
CREATE_VEHICLE_FOR_REPLAY(mReplayVehicle, <<-1327.1753, -1290.8113, 3.8472>>, 291.8355, FALSE, FALSE, FALSE, FALSE, FALSE)
END_REPLAY_SETUP()
iTimeOut = GET_GAME_TIMER()
WHILE NOT IS_SHOP_OPEN_FOR_BUSINESS(CLOTHES_SHOP_A_01_VB)
AND (GET_GAME_TIMER() - iTimeOut) < 2000
#IF IS_DEBUG_BUILD SK_PRINT_INT("WAITING - Mask shop not open", (GET_GAME_TIMER() - iTimeOut)) #ENDIF
WAIT(0)
ENDWHILE
SAFE_FADE_SCREEN_IN_FROM_BLACK()
SAFE_RELEASE_VEHICLE(mReplayVehicle)
eState = SS_CLEANUP
ELSE
IF IS_REPEAT_PLAY_ACTIVE()
SET_PED_POS(PLAYER_PED_ID(), <<-1339.7863, -1277.5099, 3.8874>>, 261.2839)
SET_GAMEPLAY_CAM_RELATIVE_HEADING()
iTimeOut = GET_GAME_TIMER()
WHILE NOT IS_SHOP_OPEN_FOR_BUSINESS(CLOTHES_SHOP_A_01_VB)
AND (GET_GAME_TIMER() - iTimeOut) < 2000
#IF IS_DEBUG_BUILD SK_PRINT_INT("WAITING - Mask shop not open", (GET_GAME_TIMER() - iTimeOut)) #ENDIF
WAIT(0)
ENDWHILE
SAFE_FADE_SCREEN_IN_FROM_BLACK()
ENDIF
eState = SS_CLEANUP
ENDIF
ENDIF
BREAK
CASE SS_CLEANUP
#IF IS_DEBUG_BUILD SK_PRINT("CLEANEDUP INIT MISSION") #ENDIF
NEXT_STAGE()
BREAK
ENDSWITCH
ENDPROC
PROC PRINT_BOILER_OBJ(STRING Toprint, STRING ToClear1, STRING ToClear2)
IF IS_THIS_PRINT_BEING_DISPLAYED(ToClear1)
OR IS_THIS_PRINT_BEING_DISPLAYED(ToClear2)
CLEAR_PRINTS()
ENDIF
IF NOT IS_THIS_PRINT_BEING_DISPLAYED(ToPrint)
PRINT_NOW(Toprint, 60000, 0)
ENDIF
ENDPROC
PROC PRINT_CURRENT_BOILER_OBJ() //enumCharacterList ePlayerChar) // , INT i)
// INT p
IF IS_CUSTOM_MENU_ON_SCREEN()
SWITCH GET_CURRENT_PLAYER_PED_ENUM()
CASE CHAR_MICHAEL
IF g_savedGlobals.sPlayerData.sInfo.eFBI4MaskName[CHAR_MICHAEL] = DUMMY_PED_COMP
PRINT_BOILER_OBJ(mObj[CHAR_MICHAEL], mObj[CHAR_FRANKLIN], mObj[CHAR_TREVOR])
ELIF g_savedGlobals.sPlayerData.sInfo.eFBI4MaskName[CHAR_FRANKLIN] = DUMMY_PED_COMP
PRINT_BOILER_OBJ(mObj[CHAR_FRANKLIN], mObj[CHAR_MICHAEL], mObj[CHAR_TREVOR])
ELIF g_savedGlobals.sPlayerData.sInfo.eFBI4MaskName[CHAR_TREVOR] = DUMMY_PED_COMP
PRINT_BOILER_OBJ(mObj[CHAR_TREVOR], mObj[CHAR_FRANKLIN], mObj[CHAR_MICHAEL])
ENDIF
BREAK
CASE CHAR_FRANKLIN
IF g_savedGlobals.sPlayerData.sInfo.eFBI4MaskName[CHAR_FRANKLIN] = DUMMY_PED_COMP
PRINT_BOILER_OBJ(mObj[CHAR_FRANKLIN], mObj[CHAR_MICHAEL], mObj[CHAR_TREVOR])
ELIF g_savedGlobals.sPlayerData.sInfo.eFBI4MaskName[CHAR_MICHAEL] = DUMMY_PED_COMP
PRINT_BOILER_OBJ(mObj[CHAR_MICHAEL], mObj[CHAR_FRANKLIN], mObj[CHAR_TREVOR])
ELIF g_savedGlobals.sPlayerData.sInfo.eFBI4MaskName[CHAR_TREVOR] = DUMMY_PED_COMP
PRINT_BOILER_OBJ(mObj[CHAR_TREVOR], mObj[CHAR_FRANKLIN], mObj[CHAR_MICHAEL])
ENDIF
BREAK
CASE CHAR_TREVOR
IF g_savedGlobals.sPlayerData.sInfo.eFBI4MaskName[CHAR_TREVOR] = DUMMY_PED_COMP
PRINT_BOILER_OBJ(mObj[CHAR_TREVOR], mObj[CHAR_FRANKLIN], mObj[CHAR_MICHAEL])
ELIF g_savedGlobals.sPlayerData.sInfo.eFBI4MaskName[CHAR_MICHAEL] = DUMMY_PED_COMP
PRINT_BOILER_OBJ(mObj[CHAR_MICHAEL], mObj[CHAR_FRANKLIN], mObj[CHAR_TREVOR])
ELIF g_savedGlobals.sPlayerData.sInfo.eFBI4MaskName[CHAR_FRANKLIN] = DUMMY_PED_COMP
PRINT_BOILER_OBJ(mObj[CHAR_FRANKLIN], mObj[CHAR_MICHAEL], mObj[CHAR_TREVOR])
ENDIF
BREAK
ENDSWITCH
ENDIF
ENDPROC
FUNC BOOL HAS_PLAYER_AQUIRED_OUTFIT()
PRINT_CURRENT_BOILER_OBJ()
IF iNumberBought >= 3
IF IS_THIS_PRINT_BEING_DISPLAYED("PRD_BUYM")
OR IS_THIS_PRINT_BEING_DISPLAYED("PRD_BUYT")
OR IS_THIS_PRINT_BEING_DISPLAYED("PRD_BUYF")
CLEAR_PRINTS()
ENDIF
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
PROC GET_TO_CLOTHES()
SWITCH eState
CASE SS_INIT
IF SETUP_MISSION_STAGE(eMissionState, bJumpSkip)
#IF IS_DEBUG_BUILD SK_PRINT("INIT GET_TO_STEAL_THING") #ENDIF
eState = SS_ACTIVE
ENDIF
BREAK
CASE SS_ACTIVE
IF NOT bArrivedShopLoc
IF IS_ENTITY_IN_RANGE_COORDS(PLAYER_PED_ID(), vShop, 60)
PRINT_OBJ("PRD_GCLOTH", bObjectiveShown) //Buy a ~g~mask.
SAFE_REMOVE_BLIP(biBlip)
ADD_BLIP_LOCATION_WITH_NAME(biBlip, vMasks, TRUE, TRUE, "PRD_BLIP")
IF DOES_BLIP_EXIST(biBlip)
SET_BLIP_COLOUR(biBlip, BLIP_COLOUR_GREEN)
SET_BLIP_ROUTE_COLOUR(biBlip, BLIP_COLOUR_GREEN)
ENDIF
bArrivedShopLoc = TRUE
ENDIF
ELSE
IF IS_PLAYER_IN_SHOP(CLOTHES_SHOP_A_01_VB)
#IF IS_DEBUG_BUILD SK_PRINT("IN SHOP ") #ENDIF
INFORM_MISSION_STATS_SYSTEM_OF_TIME_WINDOW_OPEN(FBI4P4_FACE_TIME)
// IF HAS_SHOP_RUN_ENTRY_INTRO(CLOTHES_SHOP_A_01_VB)
eState = SS_CLEANUP
// ENDIF
ELSE
IF NOT IS_ENTITY_IN_RANGE_COORDS(PLAYER_PED_ID(), vShop, 75)
IF NOT bDeletedBlip
SAFE_REMOVE_BLIP(biBlip)
bDeletedBlip = TRUE
ENDIF
ADD_BLIP_LOCATION_WITH_NAME(biBlip, vMasks, TRUE, TRUE, "PRD_SHOP")
ELIF IS_ENTITY_IN_RANGE_COORDS(PLAYER_PED_ID(), vMasks, 12)
IF bDeletedBlip
SAFE_REMOVE_BLIP(biBlip)
bDeletedBlip = FALSE
ENDIF
ADD_BLIP_LOCATION_WITH_NAME(biBlip, vMasks, TRUE, TRUE, "PRD_BLIP")
IF DOES_BLIP_EXIST(biBlip)
SET_BLIP_COLOUR(biBlip, BLIP_COLOUR_GREEN)
SET_BLIP_ROUTE_COLOUR(biBlip, BLIP_COLOUR_GREEN)
ENDIF
ENDIF
ENDIF
ENDIF
BREAK
CASE SS_CLEANUP
#IF IS_DEBUG_BUILD SK_PRINT("CLEANEDUP GET_TO_VAN") #ENDIF
NEXT_STAGE()
BREAK
CASE SS_SKIPPED
SET_PED_POS(PLAYER_PED_ID(), vMasks, 0)
RC_END_Z_SKIP()
eState = SS_ACTIVE
BREAK
ENDSWITCH
ENDPROC
PROC BUY()
SWITCH eState
CASE SS_INIT
IF SETUP_MISSION_STAGE(eMissionState, bJumpSkip)
#IF IS_DEBUG_BUILD SK_PRINT("INIT BUY()") #ENDIF
TASK_LOOK_AT_COORD(PLAYER_PED_ID(), <<-1335.90479, -1278.67139, 5.07569>>, -1)
eState = SS_ACTIVE
ENDIF
BREAK
CASE SS_ACTIVE
IF IS_ENTITY_IN_RANGE_COORDS(PLAYER_PED_ID(), vMasks, 2)
AND IS_PLAYER_BROWSING_ITEMS_IN_SHOP(CLOTHES_SHOP_A_01_VB)
TASK_CLEAR_LOOK_AT(PLAYER_PED_ID())
SAFE_REMOVE_BLIP(biBlip)
ELSE
IF IS_THIS_PRINT_BEING_DISPLAYED("PRD_BUYM")
OR IS_THIS_PRINT_BEING_DISPLAYED("PRD_BUYT")
OR IS_THIS_PRINT_BEING_DISPLAYED("PRD_BUYF")
CLEAR_PRINTS()
ENDIF
IF bMaskBought
iMissionPassDelayTimer = GET_GAME_TIMER()
eState = SS_CLEANUP
ELSE
IF NOT IS_ENTITY_IN_RANGE_COORDS(PLAYER_PED_ID(), vShop, 75)
IF NOT bDeletedBlip
SAFE_REMOVE_BLIP(biBlip)
bDeletedBlip = TRUE
ENDIF
ADD_BLIP_LOCATION_WITH_NAME(biBlip, vMasks, TRUE, TRUE, "PRD_SHOP")
ELIF IS_ENTITY_IN_RANGE_COORDS(PLAYER_PED_ID(), vMasks, 12)
IF bDeletedBlip
SAFE_REMOVE_BLIP(biBlip)
bDeletedBlip = FALSE
ENDIF
ADD_BLIP_LOCATION_WITH_NAME(biBlip, vMasks, TRUE, TRUE, "PRD_BLIP")
IF DOES_BLIP_EXIST(biBlip)
SET_BLIP_COLOUR(biBlip, BLIP_COLOUR_GREEN)
SET_BLIP_ROUTE_COLOUR(biBlip, BLIP_COLOUR_GREEN)
ENDIF
ENDIF
ENDIF
ENDIF
BREAK
CASE SS_CLEANUP
IF (GET_GAME_TIMER() - iMissionPassDelayTimer) > 2000
#IF IS_DEBUG_BUILD SK_PRINT("CLEANEDUP BUY()") #ENDIF
SAFE_REMOVE_BLIP(biBlip)
IF UPDATE_PHONE_STATES(ePhoneCallState, sPhoneUpdateString, s_conversation_peds)
INFORM_MISSION_STATS_SYSTEM_OF_TIME_WINDOW_CLOSED()
IF g_savedGlobals.sPlayerData.sInfo.eFBI4MaskName[CHAR_MICHAEL] = PROPS_P0_MASK_HOCKEY_WHITE
AND g_savedGlobals.sPlayerData.sInfo.eFBI4MaskName[CHAR_FRANKLIN] = PROPS_P1_MASK_HOCKEY_WHITE
AND g_savedGlobals.sPlayerData.sInfo.eFBI4MaskName[CHAR_TREVOR] = PROPS_P2_MASK_HOCKEY_WHITE
INFORM_STAT_SYSTEM_OF_BOOL_STAT_HAPPENED(FBI4P4_CLICHE)
ENDIF
//
Script_Passed()
ENDIF
ENDIF
BREAK
CASE SS_SKIPPED
g_savedGlobals.sPlayerData.sInfo.eFBI4MaskName[CHAR_MICHAEL] = PROPS_P0_MASK_HOCKEY_WHITE
g_savedGlobals.sPlayerData.sInfo.eFBI4MaskName[CHAR_FRANKLIN] = PROPS_P1_MASK_HOCKEY_WHITE
g_savedGlobals.sPlayerData.sInfo.eFBI4MaskName[CHAR_TREVOR] = PROPS_P2_MASK_HOCKEY_WHITE
RC_END_Z_SKIP()
eState = SS_CLEANUP
BREAK
ENDSWITCH
ENDPROC
///DEBUG KEYS
#IF IS_DEBUG_BUILD
/// PURPOSE: Check for Forced Pass or Fail
PROC DEBUG_Check_Debug_Keys()
// Check for Pass
IF eState = SS_ACTIVE
IF (IS_KEYBOARD_KEY_JUST_PRESSED(KEY_S))
KILL_ANY_CONVERSATION()
CLEAR_PRINTS()
WAIT_FOR_CUTSCENE_TO_STOP()
REGISTER_PASS_CALL()
g_savedGlobals.sPlayerData.sInfo.eFBI4MaskName[CHAR_MICHAEL] = PROPS_P0_MASK_HOCKEY_WHITE
g_savedGlobals.sPlayerData.sInfo.eFBI4MaskName[CHAR_FRANKLIN] = PROPS_P1_MASK_HOCKEY_WHITE
g_savedGlobals.sPlayerData.sInfo.eFBI4MaskName[CHAR_TREVOR] = PROPS_P2_MASK_HOCKEY_WHITE
Script_Passed()
ENDIF
// Check for Fail
IF (IS_KEYBOARD_KEY_JUST_PRESSED(KEY_F))
KILL_ANY_CONVERSATION()
CLEAR_PRINTS()
WAIT_FOR_CUTSCENE_TO_STOP()
MISSION_FAILED(FR_NONE)
ENDIF
IF (IS_KEYBOARD_KEY_JUST_PRESSED(KEY_J))
KILL_ANY_CONVERSATION()
CLEAR_PRINTS()
WAIT_FOR_CUTSCENE_TO_STOP()
RC_START_Z_SKIP()
eState = SS_SKIPPED
ENDIF
IF (IS_KEYBOARD_KEY_JUST_PRESSED(KEY_P))
AND eMissionState <> MS_SET_UP
//Work out which stage we want to reach based on the current stage
iMissionState = ENUM_TO_INT(eMissionState)
IF iMissionState > 0
MISSION_STATE e_stage = INT_TO_ENUM(MISSION_STATE, iMissionState - 1)
JUMP_TO_STAGE(e_stage)
ENDIF
ENDIF
IF LAUNCH_MISSION_STAGE_MENU(s_skip_menu, i_debug_jump_stage)
#IF IS_DEBUG_BUILD SK_PRINT_INT("Z DEBUG Initial pick = ", i_debug_jump_stage) #ENDIF
SWITCH i_debug_jump_stage
CASE 0 //MS_STEAL
i_debug_jump_stage++
BREAK
CASE 1 //MS_RETURN_WITH_THING
i_debug_jump_stage++
BREAK
ENDSWITCH
SK_PRINT_INT("Z DEBUG ACTUAL STATE = ", i_debug_jump_stage)
MISSION_STATE e_stage = INT_TO_ENUM(MISSION_STATE, i_debug_jump_stage)
JUMP_TO_STAGE(e_stage)
ENDIF
ENDIF
ENDPROC
#ENDIF
FUNC BOOL HAS_PLAYER_GOT_ENOUGH_CASH()
INT iCashNeeded = 150
IF iNumberBought = 1
iCashNeeded = 100
ELIF iNumberBought = 2
iCashNeeded = 50
ENDIF
IF NOT DOES_PLAYER_HAVE_THE_CASH(bMaskBought, iCashNeeded)
AND NOT bMaskBought
RETURN FALSE
ENDIF
RETURN TRUE
ENDFUNC
/// PURPOSE:
/// Holds functions that moniter for the player failing
PROC CHECK_FOR_FAIL()
IF NOT bJumpSkip
AND eMissionState <> MS_FAILED
IF eMissionState > MS_SET_UP
IF NOT bMaskBought
IF NOT IS_SHOP_OPEN_FOR_BUSINESS(CLOTHES_SHOP_A_01_VB)
#IF IS_DEBUG_BUILD SK_PRINT("SHOP CLOSED") #ENDIF
MISSION_FAILED(FR_KICKOFFSHOP)
ENDIF
IF IS_PLAYER_KICKING_OFF_IN_SHOP(CLOTHES_SHOP_A_01_VB)
#IF IS_DEBUG_BUILD SK_PRINT("PLAYER KICKED OFF IN SHOP") #ENDIF
MISSION_FAILED(FR_KICKOFFSHOP)
ENDIF
IF GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) > 0
#IF IS_DEBUG_BUILD SK_PRINT("PLAYER HAS WANTED LEVEL") #ENDIF
iWantedFailTimer = GET_GAME_TIMER()
MISSION_FAILED(FR_COPS)
EXIT
ENDIF
ENDIF
IF NOT HAS_PLAYER_GOT_ENOUGH_CASH()
#IF IS_DEBUG_BUILD SK_PRINT("PLAYER HAS NO CASH main check") #ENDIF
MISSION_FAILED(FR_NO_CASH)
EXIT
ENDIF
IF NOT bMaskBought
IF NOT IS_ENTITY_IN_RANGE_COORDS(PLAYER_PED_ID(), vShop, 150)
MISSION_FAILED(FR_LEFT)
ELIF NOT IS_ENTITY_IN_RANGE_COORDS(PLAYER_PED_ID(), vShop, 75)
IF NOT bWarnLeft
CLEAR_PRINTS()
PRINT_NOW("PRD_RETSHOP", DEFAULT_GOD_TEXT_TIME, 0)
bWarnLeft = TRUE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
PROC GIVE_PLAYER_MONEY_ON_REPEAT_PLAY()
enumBankAccountName ePlayerAccount
SWITCH GET_CURRENT_PLAYER_PED_ENUM()
CASE CHAR_MICHAEL
ePlayerAccount = BANK_ACCOUNT_MICHAEL
BREAK
CASE CHAR_FRANKLIN
ePlayerAccount = BANK_ACCOUNT_FRANKLIN
BREAK
CASE CHAR_TREVOR
ePlayerAccount = BANK_ACCOUNT_TREVOR
BREAK
ENDSWITCH
IF GET_ACCOUNT_BALANCE(ePlayerAccount) < 1500
CREDIT_BANK_ACCOUNT(GET_CURRENT_PLAYER_PED_ENUM(), BAAC_CASH_DEPOSIT, 1500, FALSE, FALSE)
ENDIF
ENDPROC
SCRIPT
SET_MISSION_FLAG(TRUE)
IF IS_PLAYER_PLAYING(PLAYER_ID())
AND NOT IS_PLAYER_DEAD(PLAYER_ID())
#IF IS_DEBUG_BUILD SK_PRINT("Wanted level cleared ") #ENDIF
CLEAR_PLAYER_WANTED_LEVEL(PLAYER_ID())
ENDIF
// Setup callback when player is killed, arrested or goes to multiplayer
IF (HAS_FORCE_CLEANUP_OCCURRED(DEFAULT_FORCE_CLEANUP_FLAGS|FORCE_CLEANUP_FLAG_DEBUG_MENU))
PRINTSTRING("FORCE CLEAN UP") PRINTNL()
sFailReason = NULL
RESET_OUTFITS_ON_FAIL()
Mission_Flow_Mission_Force_Cleanup()
Script_Cleanup()
ENDIF
#IF IS_DEBUG_BUILD
SETUP_FOR_RAGE_WIDGETS()
#ENDIF
POPULATE_STUFF()
MAKE_ALL_MASKS_AVAILABLE() // this adds them to the shop
IF IS_REPLAY_IN_PROGRESS()
START_REPLAY_SETUP(<<-1339.7863, -1277.5099, 3.8874>>, 261.2839)
ENDIF
IF IS_REPEAT_PLAY_ACTIVE()
g_savedGlobals.sPlayerData.sInfo.eFBI4MaskName[CHAR_MICHAEL] = DUMMY_PED_COMP
g_savedGlobals.sPlayerData.sInfo.eFBI4MaskName[CHAR_FRANKLIN] = DUMMY_PED_COMP
g_savedGlobals.sPlayerData.sInfo.eFBI4MaskName[CHAR_TREVOR] = DUMMY_PED_COMP
GIVE_PLAYER_MONEY_ON_REPEAT_PLAY()
ENDIF
// Loop within here until the mission passes or fails
WHILE(TRUE)
REPLAY_CHECK_FOR_EVENT_THIS_FRAME("M_MS")
IF IS_PED_UNINJURED(PLAYER_PED_ID())
IF eMissionState = MS_BUY
iNumberBought = GET_NUM_OF_MASKS_BOUGHT()
IF HAS_PLAYER_AQUIRED_OUTFIT()
bMaskBought = TRUE
ENDIF
ENDIF
CHECK_FOR_FAIL()
SWITCH eMissionState
CASE MS_SET_UP
INITMISSION()
BREAK
CASE MS_GET_TO_CLOTHES
GET_TO_CLOTHES()
BREAK
CASE MS_BUY
BUY()
BREAK
CASE MS_FAILED
FAILED_WAIT_FOR_FADE()
BREAK
ENDSWITCH
IF eMissionState <> MS_FAILED
IF eMissionState >= MS_SET_UP
AND NOT bJumpSkip
ENDIF
#IF IS_DEBUG_BUILD
// Check debug completion/failure
DEBUG_Check_Debug_Keys()
UPDATE_RAG_WIDGETS()
#ENDIF
ENDIF
ENDIF
WAIT(0)
ENDWHILE
// Script should never reach here. Always terminate with cleanup function.
ENDSCRIPT