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

473 lines
18 KiB
Scheme
Executable File

// Functions only used when setting up an RC mission
USING "rage_builtins.sch"
USING "globals.sch"
USING "RC_Helper_Functions.sch"
USING "taxi_functions.sch"
/// PURPOSE:
/// Ends the cutscene request for this RC mission
PROC END_RC_CUTSCENE_REQUEST(INT &iCutsceneRequestID)
STOP_CUTSCENE()
REMOVE_CUTSCENE()
END_OFFMISSION_CUTSCENE_REQUEST(iCutsceneRequestID)
ENDPROC
/// PURPOSE:
/// Used by the launcher to register a request to preload a cutscene and
/// load/unload it when told to do so by the off-mission cutscene controller.
/// PARAMS:
/// iCutsceneRequestID - And INT to be used to store the cutscene request ID assigned by the cutscene controller.
/// sCutsceneName - Name of RC intro cutscene.
PROC MANAGE_PRELOADING_RC_CUTSCENE(INT &iCutsceneRequestID, STRING sCutsceneName, VECTOR vMissionCoords)
IF IS_PLAYER_PLAYING(PLAYER_ID())
IF NOT IS_STRING_NULL_OR_EMPTY(sCutsceneName)
// Clear cutscenes for switches
IF g_OnMissionState = MISSION_TYPE_SWITCH
// Clear any cutscene requests with controller.
IF iCutsceneRequestID != NULL_OFFMISSION_CUTSCENE_REQUEST
END_RC_CUTSCENE_REQUEST(iCutsceneRequestID)
CPRINTLN(DEBUG_RANDOM_CHAR, GET_THIS_SCRIPT_NAME(), ": Cleaned up cutscene for character switch :", sCutsceneName)
ENDIF
// If the player has changed his component variations we have to request the cutscene again
ELIF IS_PLAYER_CHANGING_CLOTHES()
// Clear any cutscene requests with controller.
IF iCutsceneRequestID != NULL_OFFMISSION_CUTSCENE_REQUEST
END_RC_CUTSCENE_REQUEST(iCutsceneRequestID)
CPRINTLN(DEBUG_RANDOM_CHAR, GET_THIS_SCRIPT_NAME(), ": Cleaned up cutscene early for player changing clothes :", sCutsceneName)
ENDIF
ELSE
// No cutscenes have yet been requested
IF iCutsceneRequestID = NULL_OFFMISSION_CUTSCENE_REQUEST
// Player has entered cutscene streaming range for this RC mission
IF GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(PLAYER_PED_ID(), vMissionCoords) <= DEFAULT_CUTSCENE_LOAD_DIST
CPRINTLN(DEBUG_RANDOM_CHAR, GET_THIS_SCRIPT_NAME(), ": Requesting permission to preload intro cutscene :", sCutsceneName)
REGISTER_OFFMISSION_CUTSCENE_REQUEST(iCutsceneRequestID, OCT_RC_MISSION)
ENDIF
ELSE
// Handle cutscene actions
SWITCH GET_OFFMISSION_CUTSCENE_REQURIED_ACTION(iCutsceneRequestID)
CASE OCA_LOAD
CPRINTLN(DEBUG_RANDOM_CHAR, GET_THIS_SCRIPT_NAME(), ": Started loading intro cutscene : ", sCutsceneName)
IF ARE_STRINGS_EQUAL(sCutsceneName,"JOSH_1_INT_CONCAT")
REQUEST_CUTSCENE_WITH_PLAYBACK_LIST(sCutsceneName, CS_SECTION_2|CS_SECTION_3|CS_SECTION_4)
ELSE
REQUEST_CUTSCENE(sCutsceneName)
ENDIF
// Disable SRL map pre-streaming for off-mission prestreamed cutscenes. Stops the world streaming
// from being choked and allows us to run switch cams with the cutscenes in memory.
CPRINTLN(DEBUG_RANDOM_CHAR, GET_THIS_SCRIPT_NAME(), ": Disabling SRL map pre-streaming for cutscene.")
SET_SRL_FORCE_PRESTREAM(SRL_PRESTREAM_FORCE_OFF)
SET_OFFMISSION_CUTSCENE_ACTIVE(iCutsceneRequestID, TRUE)
BREAK
CASE OCA_UNLOAD
CPRINTLN(DEBUG_RANDOM_CHAR, GET_THIS_SCRIPT_NAME(), ": Asked to unload intro cutscene : ", sCutsceneName)
STOP_CUTSCENE()
REMOVE_CUTSCENE()
CPRINTLN(DEBUG_RANDOM_CHAR, GET_THIS_SCRIPT_NAME(), ": Re-enabling SRL map pre-streaming for cutscenes as cutscene unloads.")
SET_SRL_FORCE_PRESTREAM(SRL_PRESTREAM_DEFAULT)
SET_OFFMISSION_CUTSCENE_ACTIVE(iCutsceneRequestID, FALSE)
BREAK
ENDSWITCH
// Player has gone out of cutscene streaming range
IF GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(PLAYER_PED_ID(), vMissionCoords) > DEFAULT_CUTSCENE_UNLOAD_DIST
END_RC_CUTSCENE_REQUEST(iCutsceneRequestID)
CPRINTLN(DEBUG_RANDOM_CHAR, GET_THIS_SCRIPT_NAME(), ": Cleaned up cutscene as out of range : ", sCutsceneName)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
ENUM eCUTSCENE_SECTION_LOADING
CSL_NULL,
CSL_SECTION_ONE,
CSL_SECTION_TWO
ENDENUM
/// PURPOSE:
/// Used by the launcher to register a request to preload a multi scene cutscene and
/// load/unload it when told to do so by the off-mission cutscene controller.
/// This is designed for cutscenes with alternate starts, it loads the start for the side the player is closest to
/// PARAMS:
/// iCutsceneRequestID - An INT to be used to store the cutscene request ID assigned by the cutscene controller.
/// eCutscenePartLoading - An enum that tracks what stages are currently loaded
/// sCutsceneName - Name of RC intro cutscene.
/// vSectionOne - A locate that is pretty much where the player starts for section one
/// vSectionTwo - A locate that is pretty much where the player starts for section two
PROC MANAGE_PRELOADING_RC_CONCAT_CUTSCENE(INT &iCutsceneRequestID, eCUTSCENE_SECTION_LOADING &eCutscenePartLoading, STRING sCutsceneName, VECTOR vMissionCoords, VECTOR vSectionOne, VECTOR vSectionTwo)
IF IS_PLAYER_PLAYING(PLAYER_ID())
IF NOT IS_STRING_NULL_OR_EMPTY(sCutsceneName)
// If the player has changed his component variations we have to request the cutscene again
IF IS_PLAYER_CHANGING_CLOTHES()
// Clear any cutscene requests with controller.
IF iCutsceneRequestID != NULL_OFFMISSION_CUTSCENE_REQUEST
END_RC_CUTSCENE_REQUEST(iCutsceneRequestID)
CPRINTLN(DEBUG_RANDOM_CHAR, GET_THIS_SCRIPT_NAME(), ": Cleaned up cutscene early for player changing clothes :", sCutsceneName)
ENDIF
ELSE
// No cutscenes have yet been requested
IF iCutsceneRequestID = NULL_OFFMISSION_CUTSCENE_REQUEST
// Player has entered cutscene streaming range for this RC mission
IF GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(PLAYER_PED_ID(), vMissionCoords) <= DEFAULT_CUTSCENE_LOAD_DIST
CPRINTLN(DEBUG_RANDOM_CHAR, GET_THIS_SCRIPT_NAME(), ": Requesting permission to preload intro cutscene :", sCutsceneName)
REGISTER_OFFMISSION_CUTSCENE_REQUEST(iCutsceneRequestID, OCT_RC_MISSION)
ENDIF
ELSE
IF GET_OFFMISSION_CUTSCENE_REQURIED_ACTION(iCutsceneRequestID) = OCA_UNLOAD
CPRINTLN(DEBUG_RANDOM_CHAR, GET_THIS_SCRIPT_NAME(), ": Asked to unload intro cutscene ", sCutsceneName)
STOP_CUTSCENE()
REMOVE_CUTSCENE()
SET_OFFMISSION_CUTSCENE_ACTIVE(iCutsceneRequestID, FALSE)
ELSE
FLOAT fDistPlayerSectionOne = GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(PLAYER_PED_ID(), vSectionOne)
FLOAT fDistPlayerSectionTwo = GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(PLAYER_PED_ID(), vSectionTwo)
FLOAT fDifference = fDistPlayerSectionOne - fDistPlayerSectionTwo
IF fDifference < 0
fDifference *= -1
ENDIF
// Don't load new cutscenes if the player is in the middle of the two locates
IF fDifference > 0.5
IF fDistPlayerSectionOne < fDistPlayerSectionTwo
IF eCutscenePartLoading <> CSL_SECTION_ONE
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), ": Requesting permission to preload intro cutscene ", sCutsceneName, " parts one and three")
REMOVE_CUTSCENE()
REQUEST_CUTSCENE_WITH_PLAYBACK_LIST(sCutsceneName, CS_SECTION_1 | CS_SECTION_3)
SET_OFFMISSION_CUTSCENE_ACTIVE(iCutsceneRequestID, TRUE)
eCutscenePartLoading = CSL_SECTION_ONE
ENDIF
ELSE
IF eCutscenePartLoading <> CSL_SECTION_TWO
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), ": Requesting permission to preload intro cutscene ", sCutsceneName, " parts two and three")
REMOVE_CUTSCENE()
REQUEST_CUTSCENE_WITH_PLAYBACK_LIST(sCutsceneName, CS_SECTION_2 | CS_SECTION_3)
SET_OFFMISSION_CUTSCENE_ACTIVE(iCutsceneRequestID, TRUE)
eCutscenePartLoading = CSL_SECTION_TWO
ENDIF
ENDIF
ENDIF
ENDIF
// Player has gone out of cutscene streaming range
IF GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(PLAYER_PED_ID(), vMissionCoords) > DEFAULT_CUTSCENE_UNLOAD_DIST
END_RC_CUTSCENE_REQUEST(iCutsceneRequestID)
CPRINTLN(DEBUG_RANDOM_CHAR, GET_THIS_SCRIPT_NAME(), ": Cleaned up cutscene as out of range : ", sCutsceneName)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Puts the player into an outift that they can use the trigger the mission specified
/// PARAMS:
/// RcMission - which mission the player is trying to launch
PROC RC_UPDATE_PLAYER_OUTFIT(g_eRC_MissionIDs RcMission)
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
SWITCH RcMission
CASE RC_EPSILON_7
SET_PED_COMP_ITEM_CURRENT_SP(PLAYER_PED_ID(), COMP_TYPE_OUTFIT, OUTFIT_P0_EPSILON, FALSE)
BREAK
CASE RC_EPSILON_8
SET_PED_COMP_ITEM_CURRENT_SP(PLAYER_PED_ID(), COMP_TYPE_OUTFIT, OUTFIT_P0_EPSILON_WITH_MEDAL, FALSE)
BREAK
DEFAULT // other RCs don't need specific outfit
BREAK
ENDSWITCH
ENDIF
ENDPROC
/// PURPOSE:
/// Checks if the player is wearing the outfit required for this mission
/// PARAMS:
/// RcMission - which RC mission is the player doing?
/// RETURNS:
/// TRUE if the player is in the correct outfit, FALSE otherwise
FUNC BOOL IS_PLAYER_IN_CORRECT_OUTFIT(g_eRC_MissionIDs RcMission)
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
SWITCH RcMission
CASE RC_EPSILON_7
IF IS_PED_COMP_ITEM_CURRENT_SP(PLAYER_PED_ID(), COMP_TYPE_OUTFIT, OUTFIT_P0_EPSILON) // Michael
RETURN TRUE
ENDIF
BREAK
CASE RC_EPSILON_8
IF IS_PED_COMP_ITEM_CURRENT_SP(PLAYER_PED_ID(), COMP_TYPE_OUTFIT, OUTFIT_P0_EPSILON) // Michael
OR IS_PED_COMP_ITEM_CURRENT_SP(PLAYER_PED_ID(), COMP_TYPE_OUTFIT, OUTFIT_P0_EPSILON_WITH_MEDAL) // Michael
RETURN TRUE
ENDIF
BREAK
DEFAULT
RETURN TRUE // no outfit required
BREAK
ENDSWITCH
ENDIF
RETURN FALSE // not wearing the correct outfit
ENDFUNC
/// PURPOSE:
/// Checks individual component types to see if they are suitable for the activities in the specified
/// Fanatic mission.
/// NOTE: These component types are ignored
/// COMP_TYPE_HAND, COMP_TYPE_HEAD, COMP_TYPE_DECL, COMP_TYPE_BERD, COMP_TYPE_TEETH
/// COMP_TYPE_JBIB, COMP_TYPE_HAIR, COMP_TYPE_PROPGROUP (we do check individual props though)
/// PARAMS:
/// iFanaticMission - 1, or 2 (3 only uses the triathlon outfit currently)
/// eComponent - the component type we are checking (COMP_TYPE_TORSO, COMP_TYPE_LEGS etc)
/// RETURNS:
/// TRUE if this component is suitable for the activity in this mission
FUNC BOOL IS_COMPONENT_SUITABLE_FOR_FANATIC_MISSION(INT iFanaticMission, PED_COMP_TYPE_ENUM eComponentType)
PED_COMP_NAME_ENUM eItem
if eComponentType != COMP_TYPE_PROPS
eItem = GET_PED_COMP_ITEM_CURRENT_SP(PLAYER_PED_ID(), eComponentType)
endif
SWITCH iFanaticMission
CASE 1 // Fanatic 1 = Michael running
SWITCH eComponentType
CASE COMP_TYPE_TORSO
IF eItem = TORSO_P0_TRIATHLON
OR (eItem >= TORSO_P0_V_NECK_0 AND eItem <= TORSO_P0_V_NECK_15)
OR eItem = TORSO_P0_TRIATHLON
OR (eItem >= TORSO_P0_GOLF AND eItem <= TORSO_P0_POLO_SHIRT_7)
OR (eItem >= TORSO_P0_YOGA_0 AND eItem <= TORSO_P0_YOGA_5)
OR (eItem >= TORSO_P0_HOODIE_0 AND eItem <= TORSO_P0_HOODIE_15)
OR (eItem >= TORSO_P0_TENNIS AND eItem <= TORSO_P0_TENNIS_2)
RETURN TRUE
ENDIF
BREAK
CASE COMP_TYPE_LEGS
IF eItem = LEGS_P0_TRIATHLON
OR (eItem >= LEGS_P0_CARGO_SHORTS_0 AND eItem <= LEGS_P0_CARGO_SHORTS_4)
OR (eItem >= LEGS_P0_TENNIS AND eItem <= LEGS_P0_TENNIS_2)
OR (eItem >= LEGS_P0_LONG_SHORTS_0 AND eItem <= LEGS_P0_LONG_SHORTS_15)
RETURN TRUE
ENDIF
BREAK
CASE COMP_TYPE_FEET
IF eItem = FEET_P0_1
OR eItem = FEET_P0_TRIATHLON
OR eItem = FEET_P0_BED
OR (eItem >= FEET_P0_SKATE_SHOES AND eItem <= FEET_P0_SKATE_SHOES_9)
RETURN TRUE
ENDIF
BREAK
CASE COMP_TYPE_SPECIAL
IF eItem = SPECIAL_P0_NONE
OR eItem = SPECIAL_P0_WATCH_AND_BRACELET
OR eItem = SPECIAL_P0_STAR_TATTOOS
OR eItem = SPECIAL_P0_WATCH_LEATHER_STRAP
RETURN TRUE
ENDIF
BREAK
CASE COMP_TYPE_SPECIAL2
IF eItem = SPECIAL2_P0_NONE
RETURN TRUE
ENDIF
BREAK
CASE COMP_TYPE_OUTFIT
IF eItem = OUTFIT_P0_TRIATHLON
OR eItem = OUTFIT_P0_TENNIS
RETURN TRUE
ENDIF
BREAK
CASE COMP_TYPE_PROPS
eItem = GET_PED_COMP_ITEM_CURRENT_SP(PLAYER_PED_ID(), eComponentType, ENUM_TO_INT(ANCHOR_EYES))
IF eItem = PROPS_P0_GLASSES
OR (eItem >= PROPS_P0_GLASSES_DARK AND eItem <= PROPS_P0_GLASSES_DARK_9)
OR eItem = PROPS_P0_SHADES_REFLECTIVE
OR (eItem >= PROPS_P0_PROGRAMMER_GLASSES AND eItem <= PROPS_P0_PROGRAMMER_GLASSES_7)
OR (eItem >= PROPS_P0_SHADES AND eItem <= PROPS_P0_SHADES_9)
OR (eItem >= PROPS_P0_AVIATORS_0 AND eItem <= PROPS_P0_AVIATORS_11)
OR (eItem >= PROPS_P0_GLASSES_THICK_RIM_0 AND eItem <= PROPS_P0_GLASSES_THICK_RIM_7)
RETURN TRUE
ENDIF
// also return true if the player has no props equipped
IF NOT DOES_PED_HAVE_ANY_PROPS_EQUIPPED(PLAYER_PED_ID())
RETURN TRUE
ENDIF
BREAK
DEFAULT // other types are ignored, so return true
RETURN TRUE
BREAK
ENDSWITCH
BREAK
CASE 2 // Fanatic 2 = Trevor cycling
SWITCH eComponentType
CASE COMP_TYPE_TORSO
IF (eItem >= TORSO_P2_WHITE_TSHIRT AND eItem <= TORSO_P2_VNECK_15)
OR (eItem >= TORSO_P2_TANK_TOP_0 AND eItem <= TORSO_P2_TANK_TOP_8)
OR eItem = TORSO_P2_TRIATHLON
OR (eItem >= TORSO_P2_GOLF AND eItem <= TORSO_P2_TSHIRT_15)
OR (eItem >= TORSO_P2_STEALTH AND eItem <= TORSO_P2_HOODIE_15)
OR eItem = TORSO_P2_TENNIS
OR (eItem >= TORSO_P2_BOWLING_SHIRT AND eItem <= TORSO_P2_BOWLING_SHIRT_15)
OR (eItem >= TORSO_P2_YELLOW_VEST AND eItem <= TORSO_P2_YELLOW_VEST_15)
RETURN TRUE
ENDIF
BREAK
CASE COMP_TYPE_LEGS
IF eItem = LEGS_P2_TRIATHLON
OR eItem = LEGS_P2_TENNIS
OR (eItem >= LEGS_P2_BEACH AND eItem <= LEGS_P2_BEACH_7)
OR eItem = LEGS_P2_SWEAT_PANTS
RETURN TRUE
ENDIF
BREAK
CASE COMP_TYPE_FEET
IF eItem = FEET_P2_DUMMY
OR eItem = FEET_P2_TRIATHLON
OR eItem = FEET_P2_DUMMY_2
RETURN TRUE
ENDIF
BREAK
CASE COMP_TYPE_SPECIAL
IF eItem = SPECIAL_P2_WATCH
OR eItem = SPECIAL_P2_WATCH_1
OR eItem = SPECIAL_P2_STAR_TATTOOS
OR eItem = SPECIAL_P2_DUMMY
RETURN TRUE
ENDIF
BREAK
CASE COMP_TYPE_SPECIAL2
IF eItem = SPECIAL2_P2_NONE
OR eItem = SPECIAL2_P2_DUMMY
RETURN TRUE
ENDIF
BREAK
CASE COMP_TYPE_OUTFIT
IF eItem = OUTFIT_P2_TENNIS
OR eItem = OUTFIT_P2_TRIATHLON
RETURN TRUE
ENDIF
BREAK
CASE COMP_TYPE_PROPS
eItem = GET_PED_COMP_ITEM_CURRENT_SP(PLAYER_PED_ID(), eComponentType, ENUM_TO_INT(ANCHOR_EYES))
IF eItem = PROPS_P2_SUNGLASSES
OR (eItem >= PROPS_P2_SHADES_A_0 AND eItem <= PROPS_P2_SHADES_A_9)
OR eItem = PROPS_P2_BIKE_GOGGLES
OR (eItem >= PROPS_P2_SHADES_B_0 AND eItem <= PROPS_P2_SHADES_B_9)
OR (eItem >= PROPS_P2_SUNGLASSES_B_0 AND eItem <= PROPS_P2_SUNGLASSES_B_9)
OR (eItem >= PROPS_P2_SUNGLASSES_C_0 AND eItem <= PROPS_P2_SUNGLASSES_C_9)
OR (eItem >= PROPS_P2_GLASSES AND eItem <= PROPS_P2_GLASSES_9)
OR (eItem >= PROPS_P2_SQUARE_GLASSES_0 AND eItem <= PROPS_P2_SQUARE_GLASSES_9)
RETURN TRUE
ENDIF
// also return true if the player has no props equipped
IF NOT DOES_PED_HAVE_ANY_PROPS_EQUIPPED(PLAYER_PED_ID())
RETURN TRUE
ENDIF
BREAK
DEFAULT // other types are ignored, so return true
RETURN TRUE
BREAK
ENDSWITCH
BREAK
DEFAULT //shouldn't get here
BREAK
ENDSWITCH
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Checks if the player is wearing clothes suitable for the events in the Fanatic missions
/// (Running, cycling + swimming)
/// (assumes you have checked the ped is alive)
/// PARAMS:
/// iFanaticMission - 1, 2 or 3
/// RETURNS:
/// TRUE if the player's outfit is suitable for the activities used in this mission
FUNC BOOL IS_OUTFIT_SUITABLE_FOR_FANATIC_MISSION(INT iFanaticMission)
INT iCompType
SWITCH iFanaticMission
CASE 1 // Fanatic 1 = Michael running
CASE 2 // Fanatic 2 = Trevor cycling
// check outfit 1st, if the outfit passes we don't need to check individual components
IF IS_COMPONENT_SUITABLE_FOR_FANATIC_MISSION(iFanaticMission, COMP_TYPE_OUTFIT)
RETURN TRUE
ENDIF
FOR iCompType = 0 TO NUMBER_OF_PED_COMP_TYPES
IF iCompType <> ENUM_TO_INT(COMP_TYPE_OUTFIT) // outfits checked 1st (above)
// check other items
IF NOT IS_COMPONENT_SUITABLE_FOR_FANATIC_MISSION(iFanaticMission, INT_TO_ENUM(PED_COMP_TYPE_ENUM, iCompType))
CPRINTLN(DEBUG_MISSION, "IS_OUTFIT_SUITABLE_FOR_FANATIC_MISSION: Failed for compType: ", iCompType)
RETURN FALSE
ENDIF
ENDIF
ENDFOR
// If we reach here, the player isn't wearing a suitable "outfit"
// but all of the component items they are wearing are suitable
RETURN TRUE
BREAK
CASE 3 // Fanatic 3 = Franklin doing a triathlon
IF IS_PED_COMP_ITEM_CURRENT_SP(PLAYER_PED_ID(), COMP_TYPE_OUTFIT, OUTFIT_P1_TRIATHLON)
RETURN TRUE // only the triathlon outfit is suitable for swimming, cycling and running combined
ENDIF
BREAK
DEFAULT // shouldn't reach here
BREAK
ENDSWITCH
RETURN FALSE
ENDFUNC