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

940 lines
34 KiB
Scheme
Executable File

USING "random_event_private.sch"
// *****************************************************************************************
// *****************************************************************************************
// *****************************************************************************************
//
// MISSION NAME : random_events_Public.sch
// CREATED : Paul Davies
// DESCRIPTION : Contains all Random Events public functions.
//
// *****************************************************************************************
// *****************************************************************************************
// *****************************************************************************************
//INT i_REVariation
//BOOL b_REpassed
CONST_INT RANDOM_EVENT_NUMBER_OF_FLASHING_BLIPS 5
CONST_INT REBLIP_NUMBER_OF_FLASHES 5
CONST_INT REBLIP_FLASH_PHASE 1000
CONST_INT REBLIP_DARK_TIME 400
CONST_INT REBLIP_LIGHT_TIME (REBLIP_FLASH_PHASE - REBLIP_DARK_TIME)
CONST_INT REBLIP_FLASH_TIME (REBLIP_FLASH_PHASE * REBLIP_NUMBER_OF_FLASHES)
STRUCT structRandomEventBlipFlasher
BLIP_INDEX blipsToFlash[RANDOM_EVENT_NUMBER_OF_FLASHING_BLIPS]
FLOAT fBlipSize[RANDOM_EVENT_NUMBER_OF_FLASHING_BLIPS]
INT iFlashStage
INT iStartFlash
INT iStartPhase
ENDSTRUCT
PROC SET_BLIP_CAN_FLASH(structRandomEventBlipFlasher &sBlipStruct, BLIP_INDEX blipToAdd, FLOAT defaultSize = BLIP_SIZE_COORD)
IF DOES_BLIP_EXIST(blipToAdd)
INT iTemp
REPEAT COUNT_OF(sBlipStruct.blipsToFlash) iTemp
IF NOT DOES_BLIP_EXIST(sBlipStruct.blipsToFlash[iTemp])
OR sBlipStruct.blipsToFlash[iTemp] = blipToAdd
sBlipStruct.blipsToFlash[iTemp] = blipToAdd
sBlipStruct.fBlipSize[iTemp] = defaultSize
IF sBlipStruct.iFlashStage < 2
SET_BLIP_ALPHA(sBlipStruct.blipsToFlash[iTemp], 0)
ENDIF
ENDIF
ENDREPEAT
ENDIF
ENDPROC
PROC UPDATE_FLASHING_BLIPS(structRandomEventBlipFlasher &sBlipStruct)
INT iTemp
SWITCH sBlipStruct.iFlashStage
CASE 0
sBlipStruct.iStartFlash = GET_GAME_TIMER()
sBlipStruct.iStartPhase = GET_GAME_TIMER()
sBlipStruct.iFlashStage++
CPRINTLN(DEBUG_RANDOM_EVENTS, "Setting flash timer start")
REPEAT COUNT_OF(sBlipStruct.blipsToFlash) iTemp
IF DOES_BLIP_EXIST(sBlipStruct.blipsToFlash[iTemp])
sBlipStruct.iFlashStage++
EXIT
ENDIF
ENDREPEAT
BREAK
CASE 1
IF GET_GAME_TIMER() - sBlipStruct.iStartFlash < REBLIP_FLASH_TIME
SET_BLIP_SCALE(sBlipStruct.blipsToFlash[iTemp], BLIP_SIZE_COORD)
IF GET_GAME_TIMER() - sBlipStruct.iStartPhase < REBLIP_LIGHT_TIME
CPRINTLN(DEBUG_RANDOM_EVENTS, "ON")
REPEAT COUNT_OF(sBlipStruct.blipsToFlash) iTemp
IF DOES_BLIP_EXIST(sBlipStruct.blipsToFlash[iTemp])
IF GET_BLIP_ALPHA(sBlipStruct.blipsToFlash[iTemp]) <> 0
SET_BLIP_ALPHA(sBlipStruct.blipsToFlash[iTemp], 0)
ENDIF
ENDIF
ENDREPEAT
ELSE
CPRINTLN(DEBUG_RANDOM_EVENTS, "OFF")
REPEAT COUNT_OF(sBlipStruct.blipsToFlash) iTemp
IF DOES_BLIP_EXIST(sBlipStruct.blipsToFlash[iTemp])
IF GET_BLIP_ALPHA(sBlipStruct.blipsToFlash[iTemp]) <> 255
SET_BLIP_ALPHA(sBlipStruct.blipsToFlash[iTemp], 255)
ENDIF
ENDIF
ENDREPEAT
ENDIF
IF GET_GAME_TIMER() - sBlipStruct.iStartPhase >= REBLIP_FLASH_PHASE
sBlipStruct.iStartPhase = GET_GAME_TIMER()
ENDIF
ELSE
CPRINTLN(DEBUG_RANDOM_EVENTS, "Flashing done")
sBlipStruct.iFlashStage++
ENDIF
BREAK
CASE 2
REPEAT COUNT_OF(sBlipStruct.blipsToFlash) iTemp
IF DOES_BLIP_EXIST(sBlipStruct.blipsToFlash[iTemp])
SET_BLIP_SCALE(sBlipStruct.blipsToFlash[iTemp], sBlipStruct.fBlipSize[iTemp])
SET_BLIP_ALPHA(sBlipStruct.blipsToFlash[iTemp], 255)
ENDIF
ENDREPEAT
CPRINTLN(DEBUG_RANDOM_EVENTS, "Resetting blip sizes and alpha")
sBlipStruct.iFlashStage++
BREAK
ENDSWITCH
ENDPROC
PROC SET_PASS_TYPE_FOR_THIS_RANDOM_EVENT(RANDOM_EVENT_PASS_TYPE eParamPassType)
g_iREPassType = ENUM_TO_INT(eParamPassType)
ENDPROC
FUNC STRING GET_STRING_FOR_RANDOM_EVENT_HELP(RANDOM_EVENT_HELP_ENUM eHelp)
STRING sReturn = ""
SWITCH eHelp
CASE REHLP_EVENT_ACTIVE sReturn = "AM_H_REFS" BREAK
CASE REHLP_BLIP_FLASH sReturn = "RE_FLASHBLIP" BREAK
CASE REHLP_RETURN_ITEM sReturn = "RE_HANDOVER" BREAK
ENDSWITCH
RETURN sReturn
ENDFUNC
PROC PRINT_LIMITED_RANDOM_EVENT_HELP(RANDOM_EVENT_HELP_ENUM eHelp)
SWITCH eHelp
CASE REHLP_EVENT_ACTIVE
IF g_savedGlobals.sRandomEventData.iHelpCount < 3
IF NOT IS_HELP_MESSAGE_ON_SCREEN()
PRINT_HELP(GET_STRING_FOR_RANDOM_EVENT_HELP(eHelp))
g_savedGlobals.sRandomEventData.iHelpCount++
SET_BIT(g_iREHelpShown, ENUM_TO_INT(REHLP_EVENT_ACTIVE))
ENDIF
ENDIF
BREAK
CASE REHLP_BLIP_FLASH
IF NOT IS_BIT_SET(g_iREHelpShown, ENUM_TO_INT(REHLP_BLIP_FLASH))
IF NOT IS_HELP_MESSAGE_ON_SCREEN()
PRINT_HELP(GET_STRING_FOR_RANDOM_EVENT_HELP(eHelp))
g_savedGlobals.sRandomEventData.iBlipFlashHelpCount++
SET_BIT(g_iREHelpShown, ENUM_TO_INT(REHLP_BLIP_FLASH))
ENDIF
ENDIF
BREAK
CASE REHLP_RETURN_ITEM
IF NOT IS_BIT_SET(g_iREHelpShown, ENUM_TO_INT(REHLP_RETURN_ITEM))
IF NOT IS_HELP_MESSAGE_ON_SCREEN()
PRINT_HELP(GET_STRING_FOR_RANDOM_EVENT_HELP(eHelp))
g_savedGlobals.sRandomEventData.iItemReturnHelpCount++
SET_BIT(g_iREHelpShown, ENUM_TO_INT(REHLP_RETURN_ITEM))
ENDIF
ENDIF
BREAK
ENDSWITCH
ENDPROC
FUNC BOOL IS_THIS_RANDOM_EVENT_HELP_BEING_DISPLAYED(RANDOM_EVENT_HELP_ENUM eHelp)
RETURN IS_THIS_HELP_MESSAGE_BEING_DISPLAYED(GET_STRING_FOR_RANDOM_EVENT_HELP(eHelp))
ENDFUNC
FUNC BOOL HAS_LIMITED_RANDOM_EVENT_HELP_BEEN_DISPLAYED(RANDOM_EVENT_HELP_ENUM eHelp)
RETURN IS_BIT_SET(g_iREHelpShown, ENUM_TO_INT(eHelp))
ENDFUNC
/// PURPOSE:
/// Sets the lock state of a random event
/// PARAMS:
/// eRandomEvent - enum of random event
/// bLockState - Set to true to lock the event, false to unlock 1 is open, 0 is locked
///
PROC SET_RANDOM_EVENT_AVAILABLE(SP_RANDOM_EVENTS eRandomEvent, BOOL bAvailable = TRUE)
INT iBit = ENUM_TO_INT(eRandomEvent)
IF iBit < 31
IF bAvailable
SET_BIT(g_savedGlobals.sRandomEventData.iBitsetReUnlockA, iBit)
ELSE
CLEAR_BIT(g_savedGlobals.sRandomEventData.iBitsetReUnlockA, iBit)
ENDIF
ELSE
iBit -= 31
IF bAvailable
SET_BIT(g_savedGlobals.sRandomEventData.iBitsetReUnlockB, iBit)
ELSE
CLEAR_BIT(g_savedGlobals.sRandomEventData.iBitsetReUnlockB, iBit)
ENDIF
ENDIF
#IF IS_DEBUG_BUILD
IF bAvailable
CPRINTLN(DEBUG_RANDOM_EVENTS, "Setting ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent), " available")
ELSE
CPRINTLN(DEBUG_RANDOM_EVENTS, "Setting ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent), " unavailable")
ENDIF
#ENDIF
ENDPROC
/// PURPOSE:
/// Gets the lock state of a random event
/// PARAMS:
/// eRandomEvent - enum of random event
///
FUNC BOOL IS_RANDOM_EVENT_AVAILABLE(SP_RANDOM_EVENTS eRandomEvent)
// Two new CGtoNG only REs.
IF eRandomEvent = RE_DUEL OR eRandomEvent = RE_SEAPLANE
IF NOT IS_LAST_GEN_PLAYER()
RETURN FALSE
ENDIF
ENDIF
INT iBit = ENUM_TO_INT(eRandomEvent)
BOOL bRet
IF iBit < 31
bRet = IS_BIT_SET(g_savedGlobals.sRandomEventData.iBitsetReUnlockA, iBit)
ELSE
iBit -= 31
bRet = IS_BIT_SET(g_savedGlobals.sRandomEventData.iBitsetReUnlockB, iBit)
ENDIF
#IF IS_DEBUG_BUILD
IF bRet
//CPRINTLN(DEBUG_RANDOM_EVENTS, "Querying locked state of ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent), " - event is LOCKED")
ELSE
//CPRINTLN(DEBUG_RANDOM_EVENTS, "Querying locked state of ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent), " - event is UNLOCKED")
ENDIF
#ENDIF
RETURN bRet
ENDFUNC
FUNC BOOL IS_RANDOM_EVENT_COMPLETE(SP_RANDOM_EVENTS eRandomEvent, INT iVariation = 0)
IF IS_BIT_SET(g_savedGlobals.sRandomEventData.iREVariationComplete[eRandomEvent], iVariation)
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
FUNC BOOL ARE_LEADINS_BLOCKING_RE()
IF (IS_MISSION_LEADIN_WITH_HIGH_MEMORY_ACTIVE() AND NOT IS_HIGH_MEMORY_PC())
RETURN TRUE
ENDIF
//Block REs if both a mission lead-in and an RC lead-in is active at the same time.
IF IS_MISSION_TRIGGER_ACTIVE()
#IF NOT USE_SP_DLC
AND IS_RC_LEADIN_ACTIVE()
#ENDIF
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
FUNC BOOL CAN_RANDOM_EVENT_LAUNCH(VECTOR paramWorldPointCoords, SP_RANDOM_EVENTS eRandomEvent = RE_NONE, INT iVariation = 0, BOOL bIgnoreCompletion = FALSE, BOOL bDisableHeightCheck = FALSE)
//Don't launch REs before initial has finished - could lead to REs starting before loading is complete.
IF NOT g_isSPMainInitialised
CPRINTLN(DEBUG_RANDOM_EVENTS,"Random Event Debug: RE tried to launch before main.sc had started, Terminating")
RETURN FALSE
ENDIF
//If the random event enum has not been supplied with the function call then get it from the script name
IF eRandomEvent = RE_NONE
eRandomEvent = GET_RANDOM_EVENT_ENUM_FROM_CURRENT_SCRIPT()
ENDIF
//If the random event enum is still invalid then break out, the error message will have already printed
IF eRandomEvent = RE_NONE
RETURN FALSE
ENDIF
// Two new CGtoNG only REs.
IF eRandomEvent = RE_DUEL OR eRandomEvent = RE_SEAPLANE
IF NOT IS_LAST_GEN_PLAYER()
RETURN FALSE
ENDIF
ENDIF
vThisWorldPointLocation = paramWorldPointCoords
BOOL bSkipChecksForDebug = FALSE
// the following funtion is purely for launching the script from the debug menu
#IF IS_DEBUG_BUILD
IF NOT IS_STRING_NULL_OR_EMPTY(g_sRandomEventDebugScriptRequested)
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: current requested script is ", g_sRandomEventDebugScriptRequested)
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: Current script is ", GET_THIS_SCRIPT_NAME())
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: current requested variation is ", g_iRandomEventDebugVarRequested, " compared to passed variation of ", iVariation)
ENDIF
// This section allows any event selected from XML to start without altering the datestamp
IF ARE_STRINGS_EQUAL(GET_THIS_SCRIPT_NAME(), g_sRandomEventDebugScriptRequested)
AND (g_iRandomEventDebugVarRequested = iVariation OR g_iRandomEventDebugVarRequested = 0)
IF g_bDontResetCompletionOnDebugLaunch
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: g_bDontResetCompletionOnDebugLaunch has been set, ", GET_THIS_SCRIPT_NAME(), " variation may already be complete.")
ELSE
RESET_COMPLETION_FOR_THIS_RANDOM_EVENT(eRandomEvent)
ENDIF
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_THIS_SCRIPT_NAME(), " launched through debug menu.")
bSkipChecksForDebug = TRUE
ELIF NOT IS_STRING_NULL_OR_EMPTY(g_sRandomEventDebugScriptRequested)
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_THIS_SCRIPT_NAME(), " is not the selected event, or the random event flag is already set. Expecting ", g_sRandomEventDebugScriptRequested)
RETURN FALSE
ENDIF
#ENDIF
IF NOT bSkipChecksForDebug
VECTOR vPlayerCoords
IF IS_PLAYER_PLAYING(PLAYER_ID())
AND NOT IS_PED_INJURED(PLAYER_PED_ID())
vPlayerCoords = GET_ENTITY_COORDS(PLAYER_PED_ID())
//Don't allow REs to launch if the player is moving very fast.
//The streaming engine will be under too much stress.
IF VMAG2(GET_ENTITY_VELOCITY(PLAYER_PED_ID())) > AMBIENT_LOAD_PLAYER_SPEED_CUTOFF
AND NOT IS_HIGH_MEMORY_PC()
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent), ". New random event can't run as the player is moving too fast.")
RETURN FALSE
ENDIF
ENDIF
IF NOT g_savedGlobals.sFlow.isGameflowActive
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent), ". New random event can't run as flow is not active.")
RETURN FALSE
ENDIF
IF IS_REPEAT_PLAY_ACTIVE()
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent), ". New random event can't run as repeat play is active.")
RETURN FALSE
ENDIF
IF ARE_LEADINS_BLOCKING_RE()
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent), ". New random event can't run as mission lead-ins are blocking REs.")
RETURN FALSE
ENDIF
IF IS_PLAYER_WITH_A_PROSTITUTE()
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent), ". Can't launch random event as player is with a hooker.")
RETURN FALSE
ENDIF
//If is any ambient mission active
IF g_eCurrentRandomEvent != RE_NONE
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent), ". Random event terminating as ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(g_eCurrentRandomEvent), " is currently active.")
RETURN FALSE
ENDIF
#IF NOT USE_SP_DLC
//check to see if a random character is awaiting launch
IF IS_PLAYER_PED_PLAYABLE(GET_CURRENT_PLAYER_PED_ENUM())
IF GET_NEAREST_VALID_RC_MISSION(100) != NO_RC_MISSION
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent), " - Random character is awaiting activation within 100m." )
RETURN FALSE
ENDIF
ENDIF
#ENDIF
//if the player is too high above the worldpoint then don't run as the event will probably be spotted streaming in.
IF IS_PLAYER_PLAYING(PLAYER_ID())
AND NOT bDisableHeightCheck // Override added for RE_SeaPlane - url:bugstar:2035010
IF vPlayerCoords.z - vThisWorldPointLocation.z > 50
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent), " - Random event is too far below player." )
RETURN FALSE
ENDIF
ENDIF
//check if the event has been unlocked in the flow
IF NOT IS_RANDOM_EVENT_AVAILABLE(eRandomEvent)
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent), " - Random event is currently locked.")
RETURN FALSE
ENDIF
//check if the player is waiting on a high priority phone call
IF IS_PLAYER_PED_PLAYABLE(GET_CURRENT_PLAYER_PED_ENUM())
IF GET_PLAYER_CHAR_COMMUNICATION_PRIORITY_LEVEL(GET_CURRENT_PLAYER_PED_ENUM()) = CPR_HIGH
OR GET_PLAYER_CHAR_COMMUNICATION_PRIORITY_LEVEL(GET_CURRENT_PLAYER_PED_ENUM()) = CPR_VERY_HIGH
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent), " - Current player is awaiting a high priority phone call")
RETURN FALSE
ENDIF
ENDIF
//check that the event is available for the current player ped
IF IS_PLAYER_PED_PLAYABLE(GET_CURRENT_PLAYER_PED_ENUM())
IF NOT SHOULD_RANDOM_EVENT_START_FOR_PLAYER_PED(eRandomEvent, iVariation)
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent), " cannot launch for ", GET_CURRENT_PLAYER_PED_STRING())
RETURN FALSE
ENDIF
ENDIF
//Has enough time passed since this type of event launched
IF NOT IS_NOW_AFTER_TIMEOFDAY(g_savedGlobals.sRandomEventData.eTimeBlockUntil[eRandomEvent])
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent), ". New random event can't run, Not enough time has passed since last launch of this event.")
RETURN FALSE
ENDIF
// //Has enough time passed since last random event was seen on the map (RE_SIMEONYETARIAN ignores this)
// IF eRandomEvent != RE_SIMEONYETARIAN
// AND (GET_GAME_TIMER() - g_iLastSuccessfulAmbientLaunchTime) < iMinTimeBetweenLaunches
//
// CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent), ". New random event can't run, Not enough time has passed since last ambient event.")
// RETURN FALSE
//
// ENDIF
//Has enough time passed since last random event was seen on the map
IF (GET_GAME_TIMER() - g_iLastRandomEventLaunch) < iMinTimeBetweenLaunches
IF eRandomEvent != RE_SIMEONYETARIAN
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent), ". New random event can't run, Not enough time has passed since last random event.")
RETURN FALSE
ENDIF
ENDIF
//Checks the game isn't in sleep mode
IF IS_CURRENT_PLAYER_IN_SLEEP_MODE()
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent), ". New random event can't run if the player is in sleep.")
RETURN FALSE
ENDIF
//is any mission active
IF GET_MISSION_FLAG()
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent), ". New random event can't run if there's a mission running.")
RETURN FALSE
ENDIF
//is the random event flag set
IF GET_RANDOM_EVENT_FLAG()
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent), ". New random event can't run if there's already one running.")
RETURN FALSE
ENDIF
//a set of checks for other situations that may block random events such as lead ins etc.
IF NOT IS_IT_SAFE_TO_TRIGGER_SCRIPT_TYPE(ST_RANDOM_EVENT)
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent), ". New random event can't run as IS_IT_SAFE_TO_TRIGGER_SCRIPT_TYPE(ST_RANDOM_EVENT) returned false.")
RETURN FALSE
ENDIF
//Checks if a random event can launch against current mission type
IF NOT CAN_MISSION_TYPE_START_AGAINST_CURRENT_TYPE(MISSION_TYPE_RANDOM_EVENT)
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent), ". New random event can't run if there's a mission running. Checked against CAN_MISSION_TYPE_START_AGAINST_CURRENT_TYPE")
RETURN FALSE
ENDIF
//Is this event and variation complete
IF IS_RANDOM_EVENT_COMPLETE(eRandomEvent, iVariation) AND NOT bIgnoreCompletion
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent), ". This variation has been completed, exiting.")
RETURN FALSE
ENDIF
//If the magdemo is running, only the pap event should launch
IF g_bMagDemoActive AND eRandomEvent != RE_PAPARAZZI
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent), ". Mag demo is active, cannot launch events other than RE - Escape Paparazzi.")
RETURN FALSE
ENDIF
// Random events can't happen in a cinema.
IF IS_VALID_INTERIOR(GET_INTERIOR_FROM_ENTITY(PLAYER_PED_ID()))
IF GET_INTERIOR_FROM_ENTITY(PLAYER_PED_ID()) = GET_INTERIOR_AT_COORDS(<< 377.1530, -717.5670, 10.0536 >>) // Downtown cinema
OR GET_INTERIOR_FROM_ENTITY(PLAYER_PED_ID()) = GET_INTERIOR_AT_COORDS(<<320.9934, 265.2515, 82.1221>>) // Vinewood cinema
OR GET_INTERIOR_FROM_ENTITY(PLAYER_PED_ID()) = GET_INTERIOR_AT_COORDS(<< -1425.5645, -244.3000, 15.8053 >>) // Morningwood cinema
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent), ". New random event can't run if the player is in a cinema.")
RETURN FALSE
ENDIF
ENDIF
IF eRandomEvent = RE_SECURITYVAN
AND (iVariation = 2 OR iVariation = 5)
AND NOT IS_RANDOM_EVENT_COMPLETE(RE_ACCIDENT)
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: Security van ", iVariation, " cannot start until RE_ACCIDENT has been completed.")
RETURN FALSE
ENDIF
IF g_bPlayerInteractingWithChop
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: Cannot launch random events when the player is with Chop")
RETURN FALSE
ENDIF
IF IS_RANDOM_EVENT_AVAILABLE(RE_SIMEONYETARIAN)
AND NOT IS_RANDOM_EVENT_COMPLETE(RE_SIMEONYETARIAN)
IF eRandomEvent != RE_SIMEONYETARIAN
//Added this for bug 1585566 to ensure simeon will run when available.
IF VDIST2(vPlayerCoords, <<-61.2745, -1100.4675, 25.3752>>) < 176400 //210^2
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: Blocking launch of ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent), " as the player is near to re_yetarian and it's availablilty is limited.")
RETURN FALSE
ENDIF
ENDIF
ENDIF
IF IS_PLAYER_PED_PLAYABLE(GET_CURRENT_PLAYER_PED_ENUM())
enumCharacterList currentCharID
REPEAT NUM_OF_PLAYABLE_PEDS currentCharID
VECTOR vLastKnownCoords = g_savedGlobals.sPlayerData.sInfo.vLastKnownCoords[currentCharID]
TIMEOFDAY sLastTimeActive = g_savedGlobals.sPlayerData.sInfo.sLastTimeActive[currentCharID]
IF Is_TIMEOFDAY_Valid(sLastTimeActive)
IF HasHourPassedSinceCharLastTimeActive(currentCharID)
IF NOT ARE_VECTORS_EQUAL(vLastKnownCoords, <<0,0,0>>)
IF (VDIST2(GET_ENTITY_COORDS(PLAYER_PED_ID(), FALSE), vLastKnownCoords) < (210.0*210.0))
IF GET_CURRENT_PLAYER_PED_ENUM() <> currentCharID
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_THIS_SCRIPT_NAME(), ". Player is near last known coords of another playable ped, random event should not run.")
RETURN FALSE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDREPEAT
ENDIF
ENDIF
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent), " has passed all launch checks.")
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent), " world point coords are ", vThisWorldPointLocation)
RETURN TRUE
ENDFUNC
FUNC BOOL SHOULD_SHOW_HELP_FOR_THIS_RANDOM_EVENT(SP_RANDOM_EVENTS eRandomEvent)
//List of REs to hide help for.
SWITCH eRandomEvent
CASE RE_BORDERPATROL
CASE RE_SIMEONYETARIAN
CASE RE_BUSTOUR
CASE RE_CULTSHOOTOUT
RETURN FALSE
BREAK
ENDSWITCH
RETURN TRUE
ENDFUNC
FUNC BOOL SET_RANDOM_EVENT_ACTIVE(BOOL bFlashDisplay = TRUE)
IF PRIVATE_CAN_RE_RUN_THROUGH_CANDIDATE_SYSTEM()
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(g_eCurrentRandomEvent), ". Candidate system has allowed event to go active.")
g_bRandomEventActive = TRUE
g_iREStartTime = GET_GAME_TIMER()
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: g_savedGlobals.sRandomEventData.iHelpCount = ", g_savedGlobals.sRandomEventData.iHelpCount)
IF SHOULD_SHOW_HELP_FOR_THIS_RANDOM_EVENT(g_eCurrentRandomEvent)
PRINT_LIMITED_RANDOM_EVENT_HELP(REHLP_EVENT_ACTIVE)
ENDIF
SET_MISSION_NAME(TRUE, "RE_TITLE")
IF bFlashDisplay
AND SHOULD_SHOW_HELP_FOR_THIS_RANDOM_EVENT(g_eCurrentRandomEvent)
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: flashing minimap display in SET_RANDOM_EVENT_ACTIVE")
FLASH_MINIMAP_DISPLAY()
ENDIF
RETURN TRUE
ELSE
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(g_eCurrentRandomEvent), ". Candidate system did not allow event to go active.")
ENDIF
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(g_eCurrentRandomEvent), ", cannot set random event active, random event flag is already set.")
RETURN FALSE
ENDFUNC
PROC APPLY_DELAY_FOR_RANDOM_EVENT(SP_RANDOM_EVENTS eRandomEvent)
APPLY_SPECIFIC_DELAY_TO_RANDOM_EVENT(eRandomEvent, 0, GET_RANDOM_EVENT_BLOCKING_TIME(eRandomEvent))
ENDPROC
FUNC BOOL SHOULD_THIS_RANDOM_EVENT_EXIT_BEFORE_LOADING_ASSETS()
IF IS_PLAYER_PLAYING(PLAYER_ID())
AND NOT IS_PED_INJURED(PLAYER_PED_ID())
IF VDIST2(GET_ENTITY_COORDS(PLAYER_PED_ID()), vThisWorldPointLocation) < fREMinDistanceRequiredForSpawn*fREMinDistanceRequiredForSpawn
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: Too close to world point whilst awaiting assets.")
RETURN TRUE
ENDIF
//Don't allow REs to launch if the player is moving very fast.
//The streaming engine will be under too much stress.
IF VMAG2(GET_ENTITY_VELOCITY(PLAYER_PED_ID())) > AMBIENT_LOAD_PLAYER_SPEED_CUTOFF
AND NOT IS_HIGH_MEMORY_PC()
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: Player is moving too fast whilst awaiting assets.")
RETURN FALSE
ENDIF
ENDIF
IF ARE_LEADINS_BLOCKING_RE()
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ARE_LEADINS_BLOCKING_RE() returned false.")
RETURN TRUE
ENDIF
#IF NOT USE_SP_DLC
//check to see if a random character is awaiting launch
IF GET_NEAREST_VALID_RC_MISSION(100) != NO_RC_MISSION
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(g_eCurrentRandomEvent), " - Random character is awaiting activation within 100m." )
RETURN TRUE
ENDIF
#ENDIF
RETURN FALSE
ENDFUNC
FUNC BOOL SHOULD_THIS_RANDOM_EVENT_EXIT_BEFORE_ACTIVATION()
IF NOT CAN_MISSION_TYPE_START_AGAINST_CURRENT_TYPE(MISSION_TYPE_RANDOM_EVENT)
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: CAN_MISSION_TYPE_START_AGAINST_CURRENT_TYPE(MISSION_TYPE_RANDOM_EVENT) returned false.")
RETURN TRUE
ENDIF
IF ARE_LEADINS_BLOCKING_RE()
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ARE_LEADINS_BLOCKING_RE() returned false.")
RETURN TRUE
ENDIF
//Don't allow REs to launch if the player is moving very fast.
//The streaming engine will be under too much stress.
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
IF VMAG2(GET_ENTITY_VELOCITY(PLAYER_PED_ID())) > AMBIENT_LOAD_PLAYER_SPEED_CUTOFF
AND NOT IS_HIGH_MEMORY_PC()
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: Player is moving too fast whilst awaiting activation.")
RETURN FALSE
ENDIF
ENDIF
#IF NOT USE_SP_DLC
//check to see if a random character is awaiting launch
IF GET_NEAREST_VALID_RC_MISSION(100) != NO_RC_MISSION
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(g_eCurrentRandomEvent), " - Random character is awaiting activation within 100m." )
RETURN TRUE
ENDIF
#ENDIF
RETURN FALSE
ENDFUNC
FUNC BOOL IS_THIS_RANDOM_EVENT_SCRIPT_ACTIVE()
IF g_eCurrentRandomEvent = GET_RANDOM_EVENT_ENUM_FROM_CURRENT_SCRIPT()
AND GET_RANDOM_EVENT_FLAG()
AND g_bRandomEventActive
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
PROC LAUNCH_RANDOM_EVENT(SP_RANDOM_EVENTS eRandomEvent = RE_NONE)
//If the random event enum has not been supplied with the function call then get it from the script name
IF eRandomEvent = RE_NONE
eRandomEvent = GET_RANDOM_EVENT_ENUM_FROM_CURRENT_SCRIPT()
ENDIF
//If the random event enum is still invalid then ignor the rest of the funciton
IF eRandomEvent = RE_NONE
EXIT
ENDIF
SET_CURRENT_RANDOM_EVENT(eRandomEvent)
SET_SCRIPT_HIGH_PRIO(FALSE)
SET_RANDOM_EVENT_FLAG(TRUE)
//SET_RANDOM_EVENT_ACTIVE() // this is being added unitl all scripts are using the new system.
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random event launched ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent))
g_sRandomEventDebugScriptRequested = ""
g_iRandomEventDebugVarRequested = 0
#ENDIF
g_iREPassType = 0
// b_REpassed = FALSE
// SCRIPT_PLAYSTATS_MISSION_STARTED(GET_THIS_SCRIPT_NAME(), i_REVariation)
SUPPRESS_PLAYERS_CAR_FOR_RANDOM_EVENT()
ENDPROC
PROC RANDOM_EVENT_PASSED(SP_RANDOM_EVENTS eRandomEvent = RE_NONE, INT iVariation = 0)
//If the random event enum has not been supplied with the function call then get it from the script name
IF eRandomEvent = RE_NONE
eRandomEvent = GET_RANDOM_EVENT_ENUM_FROM_CURRENT_SCRIPT()
ENDIF
//If the random event enum is still invalid then ignore the rest of the funciton
IF eRandomEvent = RE_NONE
CPRINTLN(DEBUG_RANDOM_EVENTS, "Invalid random event enum passed to RANDOM_EVENT_PASSED by ", GET_THIS_SCRIPT_NAME())
EXIT
ENDIF
IF iVariation <= GET_RANDOM_EVENT_NUMBER_OF_VARIATIONS(eRandomEvent)
SET_RANDOM_EVENT_VARIATION_COMPLETE(eRandomEvent, iVariation)
#IF NOT USE_SP_DLC
IF NOT HAS_ONE_TIME_HELP_DISPLAYED(FHM_RE_STAT_BOOSTS)
ADD_HELP_TO_FLOW_QUEUE("RE_REWARD", FHP_MEDIUM, 0, 4000, DEFAULT_HELP_TEXT_TIME, GET_CURRENT_PLAYER_PED_BIT(), CID_BLANK, CID_RE_STAT_BOOST_HELP_DISPLAYED)
SET_ONE_TIME_HELP_MESSAGE_DISPLAYED(FHM_RE_STAT_BOOSTS)
ENDIF
#ENDIF
IF SHOULD_SHOW_HELP_FOR_THIS_RANDOM_EVENT(eRandomEvent)
g_savedGlobals.sRandomEventData.iHelpCount = 3
ENDIF
IF GET_RANDOM_EVENT_COMPLETION_ID(eRandomEvent, iVariation) <> UNUSED_DEFAULT
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent), ", completed.")
REGISTER_SCRIPT_IN_COMPLETION_PERCENTAGE_TOTAL(GET_RANDOM_EVENT_COMPLETION_ID(eRandomEvent, iVariation), vThisWorldPointLocation.x, vThisWorldPointLocation.y)
ELSE
CPRINTLN(DEBUG_RANDOM_EVENTS, "No percentage pass ID found for random event ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent))
ENDIF
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random event passed ", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent))
#ENDIF
g_iREVariation = iVariation
IF g_iREPassType = 0
IF g_eCurrentRandomEvent = RE_ATMROBBERY
OR g_eCurrentRandomEvent = RE_SHOPROBBERY
OR g_eCurrentRandomEvent = RE_CHASETHIEVES
OR g_eCurrentRandomEvent = RE_MUGGING
SET_PASS_TYPE_FOR_THIS_RANDOM_EVENT(RE_PASS_KEEP_ITEM)
ELIF g_eCurrentRandomEvent = RE_BIKETHIEF
OR g_eCurrentRandomEvent = RE_BIKETHIEFSTAMP
OR g_eCurrentRandomEvent = RE_CARTHEFT
SET_PASS_TYPE_FOR_THIS_RANDOM_EVENT(RE_PASS_KEEP_VEHICLE)
ELSE
SET_PASS_TYPE_FOR_THIS_RANDOM_EVENT(RE_PASS_NORMAL)
ENDIF
ENDIF
ENDIF
ENDPROC
PROC RANDOM_EVENT_OVER(SP_RANDOM_EVENTS eRandomEvent = RE_NONE)
//If the random event enum has not been supplied with the function call then get it from the script name
IF eRandomEvent = RE_NONE
eRandomEvent = GET_RANDOM_EVENT_ENUM_FROM_CURRENT_SCRIPT()
ENDIF
//If the random event enum is still invalid then ignore the rest of the funciton
IF eRandomEvent = RE_NONE
EXIT
ENDIF
IF IS_THIS_RANDOM_EVENT_SCRIPT_ACTIVE()
APPLY_DELAY_FOR_RANDOM_EVENT(eRandomEvent)
#IF IS_DEBUG_BUILD
g_sLastRandomEventScript = "NULL"
#ENDIF
SET_MISSION_NAME(FALSE)
g_iLastRandomEventLaunch = GET_GAME_TIMER()
ADD_GLOBAL_COMMUNICATION_DELAY(CC_GLOBAL_DELAY_POST_MISSION)
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random Event Debug: ", GET_THIS_SCRIPT_NAME(), " RESET_RANDOM_EVENT_LAUNCH_TIMER()")
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random event over, initial interaction completed.", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent))
TEXT_LABEL_63 sTemp
sTemp = GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(g_eCurrentRandomEvent, TRUE)
IF GET_RANDOM_EVENT_NUMBER_OF_VARIATIONS(g_eCurrentRandomEvent) > 0
sTemp += " Variation "
sTemp += g_iREVariation
ENDIF
PLAYSTATS_RANDOM_MISSION_DONE(sTemp, g_iREPassType, GET_GAME_TIMER() - g_iREStartTime)
ELSE
IF IS_BIT_SET(g_iREHelpShown, ENUM_TO_INT(REHLP_EVENT_ACTIVE))
AND g_savedGlobals.sRandomEventData.iHelpCount < 3
CLEAR_BIT(g_iREHelpShown, ENUM_TO_INT(REHLP_EVENT_ACTIVE))
ENDIF
CPRINTLN(DEBUG_RANDOM_EVENTS, "Random event over, no interaction with the player.", GET_RANDOM_EVENT_DISPLAY_STRING_FROM_ID(eRandomEvent))
ENDIF
Mission_Over(g_iRECandidateID)
g_bRandomEventActive = FALSE
#IF IS_DEBUG_BUILD
g_sRandomEventDebugScriptRequested = ""
g_iRandomEventDebugVarRequested = 0
#ENDIF
SET_CURRENT_RANDOM_EVENT(RE_NONE)
ENDPROC
PROC SET_LAST_ATM_LAUNCH_LOCATION(VECTOR paramLocation)
g_vLastCompletedATMRobbery = paramLocation
ENDPROC
FUNC VECTOR GET_LAST_ATM_LAUNCH_LOCATION()
RETURN g_vLastCompletedATMRobbery
ENDFUNC
FUNC BOOL HAS_SECURITY_VAN_HELP_DISPLAYED(INT iParamBit)
RETURN IS_BIT_SET(g_savedGlobals.sRandomEventData.iSecurityVanHelps, iParamBit)
ENDFUNC
PROC SET_SECURITY_VAN_HELP_DISPLAYED(INT iParamBit)
SET_BIT(g_savedGlobals.sRandomEventData.iSecurityVanHelps, iParamBit)
ENDPROC
PROC FLASH_RANDOM_EVENT_DECISION_BLIP(BLIP_INDEX flashBlip, INT &timeOfLastFlash)
IF DOES_BLIP_EXIST(flashBlip)
IF GET_GAME_TIMER() > (timeOfLastFlash+500)
IF GET_BLIP_COLOUR(flashBlip) = BLIP_COLOUR_RED
SET_BLIP_AS_FRIENDLY(flashBlip, TRUE)
ELSE
SET_BLIP_AS_FRIENDLY(flashBlip, FALSE)
SET_BLIP_COLOUR(flashBlip, BLIP_COLOUR_RED)
ENDIF
timeOfLastFlash = GET_GAME_TIMER()
PRINTLN(GET_THIS_SCRIPT_NAME(), " - FLASH_RANDOM_EVENT_DECISION_BLIP")
ENDIF
IF NOT IS_HELP_MESSAGE_BEING_DISPLAYED()
AND HAS_LIMITED_RANDOM_EVENT_HELP_BEEN_DISPLAYED(REHLP_EVENT_ACTIVE)
PRINT_LIMITED_RANDOM_EVENT_HELP(REHLP_BLIP_FLASH)
ENDIF
ENDIF
ENDPROC
PROC FLASH_RANDOM_EVENT_RETURN_ITEM_BLIP(BLIP_INDEX flashBlip, INT &iBlipTimer)
IF iBlipTimer = -99
iBlipTimer = GET_GAME_TIMER()
ENDIF
IF DOES_BLIP_EXIST(flashBlip)
INT iTimer = GET_GAME_TIMER() - iBlipTimer
IF iTimer < REBLIP_NUMBER_OF_FLASHES*1000
INT iFlashNo = CEIL(TO_FLOAT(iTimer)/1000)
IF (iFlashNo * 1000) - iTimer < 500
IF GET_BLIP_ALPHA(flashBlip) != 255
SET_BLIP_ALPHA(flashBlip, 255)
ENDIF
ELSE
IF GET_BLIP_ALPHA(flashBlip) != 0
SET_BLIP_ALPHA(flashBlip, 0)
ENDIF
ENDIF
ELSE
IF iBlipTimer != -100
iBlipTimer = -100
IF GET_BLIP_ALPHA(flashBlip) != 255
SET_BLIP_ALPHA(flashBlip, 255)
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
PROC START_RETURN_ITEM_BLIP_FLASHING(INT &iBlipTimer)
iBlipTimer = -99
ENDPROC
PROC STOP_RETURN_ITEM_BLIP_FLASHING(INT &iBlipTimer)
iBlipTimer = GET_GAME_TIMER() - REBLIP_NUMBER_OF_FLASHES*1000
ENDPROC
FUNC BOOL HAS_PLAYER_BEEN_TO_DRUG_FARM()
RETURN g_savedGlobals.sRandomEventData.bHasPlayerAttackedDrugFarm
ENDFUNC
PROC SET_PLAYER_HAS_ATTACKED_DRUG_FARM(BOOL bAttacked = TRUE)
g_savedGlobals.sRandomEventData.bHasPlayerAttackedDrugFarm = bAttacked
ENDPROC