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

6427 lines
217 KiB
Scheme
Executable File

USING "globals.sch"
USING "commands_path.sch"
USING "commands_vehicle.sch"
USING "commands_camera.sch"
USING "commands_ped.sch"
USING "commands_hud.sch"
USING "commands_graphics.sch"
USING "commands_streaming.sch"
USING "commands_interiors.sch"
USING "commands_pad.sch"
USING "script_player.sch"
USING "script_maths.sch"
USING "commands_audio.sch"
USING "shop_public.sch"
CONST_INT LAST_CAR_RECORDING_FILE_NUMBER 3000
CONST_INT TRAFFIC_FLAGS_VEH_IS_A_COP 0
CONST_INT TRAFFIC_FLAGS_DRIVER_HAS_BEEN_CREATED 1
CONST_INT TRAFFIC_FLAGS_VEH_IS_A_BIKE 2
CONST_INT TRAFFIC_FLAGS_FREEZE_CAR_FOR_COLLISION 3
CONST_INT TRAFFIC_FLAGS_DONT_SWITCH_TO_AI_EARLY 4
CONST_FLOAT LOAD_AHEAD_TIME 7000.0
CONST_FLOAT MIN_CAR_CRUISE_SPEED 8.0
CONST_FLOAT MAX_CAR_CRUISE_SPEED 62.9
CONST_FLOAT CAUGHT_UP_DIST_PERCENT 0.4
ENUM block_colour_ENUM
dont_block_colour = -1,
traffic_black = 0,
traffic_grey,
traffic_silver,
traffic_red,
traffic_white,
traffic_blue,
traffic_navy,
traffic_light_blue,
traffic_cream,
traffic_turquoise,
traffic_green,
traffic_orange,
traffic_gun_metal_grey,
traffic_burgundy,
traffic_gold
ENDENUM
ENUM UBER_PLAYBACK_PED_MODEL
UBER_PLAYBACK_PED_MODEL_DEFAULT,
UBER_PLAYBACK_PED_MODEL_AMBIENT,
UBER_PLAYBACK_PED_MODEL_COP
ENDENUM
BOOL bResetPlaybackToTime = FALSE
BOOL bPausePlayback = FALSE
BOOL bDeleteCarsWhenDone = FALSE
BOOL bShowParkedCars = TRUE
BOOL bSetPieceCarIsRecording = FALSE
BOOL bReRecordingIsEnabled = FALSE
BOOL bReRecordingControlHijacked = FALSE
BOOL bResetSetPiece = FALSE
BOOL bReGrabSetPiecePositionAndQuat = FALSE
BOOL bTrafficDontSwitchToAI = FALSE
BOOL bCarsAreOn = TRUE
BOOL bPlayerIsAheadOfChase = FALSE
BOOL bSetPieceRecordingsAreActive = FALSE
BOOL bSetPieceRecordingsHaveBeenActivated = FALSE
BOOL bCreateAllWaitingCars = FALSE
BOOL bRefreshAllCarsAfterSkippingCalled = FALSE
BOOL bCalculatePlaybackSpeedInitialised = FALSE
BOOL bIsCatchingUp = FALSE
BOOL bDontUpdateUberCars = FALSE
BOOL bPlayTrafficRecordingEvenIfPlayerIsAheadOfChase = FALSE
BOOL bSetPieceCarsDontSwitchToAI = FALSE
BOOL bDontProcessTrafficHornsAndLights = FALSE
BOOL switch_SetPieceCar_to_ai_on_collision = FALSE
BOOL block_vehicle_colour = FALSE
BOOL bTrafficOnlySwitchToAIOnCollision = FALSE
BOOL bTrafficDontCleanupRecordingFiles = FALSE
BOOL allow_trailer_touching_check = FALSE
BOOL bTrafficForceDefaultPedModel = FALSE
BOOL allow_veh_to_stop_on_any_veh_impact = FALSE
BOOL allow_veh_to_stop_on_PLAYER_impact = FALSE
BOOL bDontCleanUpUberCarsForTrailer = FALSE //Don't flag this without permission! Intended use is for trailer scenes.
BOOL bCreatedUberPlaybackEntityThisFrame = FALSE
BOOL bUberPlaybackRemoveDefaultPedModel = TRUE
BOOL bSetReleasedDriversToExitOnFlee = FALSE
FLOAT TrafficCarQuatX[TOTAL_NUMBER_OF_TRAFFIC_CARS]
FLOAT TrafficCarQuatY[TOTAL_NUMBER_OF_TRAFFIC_CARS]
FLOAT TrafficCarQuatZ[TOTAL_NUMBER_OF_TRAFFIC_CARS]
FLOAT TrafficCarQuatW[TOTAL_NUMBER_OF_TRAFFIC_CARS]
FLOAT TrafficCarStartime[TOTAL_NUMBER_OF_TRAFFIC_CARS]
FLOAT fSetPieceQuatX, fSetPieceQuatY, fSetPieceQuatZ, fSetPieceQuatW
FLOAT SetPieceCarQuatX[TOTAL_NUMBER_OF_SET_PIECE_CARS]
FLOAT SetPieceCarQuatY[TOTAL_NUMBER_OF_SET_PIECE_CARS]
FLOAT SetPieceCarQuatZ[TOTAL_NUMBER_OF_SET_PIECE_CARS]
FLOAT SetPieceCarQuatW[TOTAL_NUMBER_OF_SET_PIECE_CARS]
FLOAT SetPieceCarStartime[TOTAL_NUMBER_OF_SET_PIECE_CARS]
FLOAT SetPieceCarRecordingSpeed[TOTAL_NUMBER_OF_SET_PIECE_CARS]
FLOAT ParkedCarQuatX[TOTAL_NUMBER_OF_PARKED_CARS]
FLOAT ParkedCarQuatY[TOTAL_NUMBER_OF_PARKED_CARS]
FLOAT ParkedCarQuatZ[TOTAL_NUMBER_OF_PARKED_CARS]
FLOAT ParkedCarQuatW[TOTAL_NUMBER_OF_PARKED_CARS]
FLOAT fPlaybackCarStreamingDistance = 120.0
FLOAT fResetTime = 0.0
FLOAT fTriggerCarPlaybackTime
FLOAT fMasterPlaybackSpeed = 1.0
FLOAT fNewSetPieceTriggerTime = 0.0
FLOAT fPausePlaybackTime = 1.0
FLOAT fClearSurroundingCarsDistance = 30.0
FLOAT fClearCarTimer
FLOAT fAirRes = 1.0
FLOAT fMaxAirRes = 5.0
FLOAT fMinAirRes = 1.0
FLOAT fAirResMultiplier = 1.0
FLOAT fUberPlaybackDensitySwitchOffRange = 100.0
FLOAT fUberPlaybackMinCreationDistance = 100.0 //The minimum distance a car has to be from the player to be allowed to create.
FLOAT fUberPlaybackParkedCarCleanupDistance = 0.0
FLOAT fUberMinTimeBeforePlaybackStartToCreate = LOAD_AHEAD_TIME //The minimum time before the playback start time of particular car before that car can be created.
FLOAT fTimeRoadsWereLastSwitchedOff = 0.0
FLOAT fTimeRoadsWereLastSwitchedOn = 0.0
FLOAT fPlaybackSpeedMaxAcceleration = 0.3
FLOAT fPlaybackSpeedMaxDecceleration = 0.5
FLOAT fSwitchOffRoadDist = 50.0
INT TrafficCarRecording[TOTAL_NUMBER_OF_TRAFFIC_CARS]
INT TrafficCarProgress[TOTAL_NUMBER_OF_TRAFFIC_CARS]
INT TrafficCarFlags[TOTAL_NUMBER_OF_TRAFFIC_CARS]
INT SetPieceCarRecording[TOTAL_NUMBER_OF_SET_PIECE_CARS]
INT SetPieceCarProgress[TOTAL_NUMBER_OF_SET_PIECE_CARS]
INT SetPieceCarFlags[TOTAL_NUMBER_OF_SET_PIECE_CARS]
INT ParkedCarProgress[TOTAL_NUMBER_OF_PARKED_CARS]
INT iCurrentNumberOfTrafficPlaybacks = 0
INT iCurrentNumberOfSetPieceCarPlaybacks = 0
INT iCurrentNumberOfParkedCars = 0
INT iTriggerCarRecordingNumber = -1
INT iFirstCarToProcess = 0
INT iFirstParkedCarToProcess = 0
INT iFirstSetpieceCarToProcess = 0
INT iParkedCarsWaitingToCreate = 0
INT iSetPieceCarsWaitingToCreate = 0
INT iTrafficCarsWaitingToCreate = 0
INT iSwitchRoadsIndex = 0
INT iDontSwitchThisSetpieceRecordingToAI = -1 //Allows a special case vehicle IF uber set-pieces are set to switch to AI.
INT iDontSwitchThisSetpieceRecordingToAI2 = -1 //Allows a special case vehicle IF uber set-pieces are set to switch to AI.
INT iSwitchRoadsOnIndex = 0
INT iLastTrafficCarProcessedForCollisions = 0
INT iLastTrafficCarProcessedForCreation = 0
INT iUberClearCarsIndex = 0
VECTOR TrafficCarPos[TOTAL_NUMBER_OF_TRAFFIC_CARS]
VECTOR ParkedCarPos[TOTAL_NUMBER_OF_PARKED_CARS]
VECTOR SetPieceCarPos[TOTAL_NUMBER_OF_SET_PIECE_CARS]
VECTOR RecordedSetPieceCarPos
VECTOR vRoadsOffAtStartMin
VECTOR vRoadsOffAtStartMax
VECTOR vRoadSwitchedOffMin
VECTOR vRoadSwitchedOffMax
VECTOR vSwitchRoadsTempMin
VECTOR vSwitchRoadsTempMax
VECTOR vSwitchRoadsOnMin
VECTOR vSwitchRoadsOnMax
TEXT_LABEL_63 strUberName
REL_GROUP_HASH rgh_traffic
MODEL_NAMES TrafficCarModel[TOTAL_NUMBER_OF_TRAFFIC_CARS]
MODEL_NAMES ParkedCarModel[TOTAL_NUMBER_OF_PARKED_CARS]
MODEL_NAMES SetPieceCarModel[TOTAL_NUMBER_OF_SET_PIECE_CARS]
MODEL_NAMES modelDefaultPed = DUMMY_MODEL_FOR_SCRIPT
block_colour_ENUM colour_to_block_0
block_colour_ENUM colour_to_block_1
VEHICLE_INDEX TrafficCarID[TOTAL_NUMBER_OF_TRAFFIC_CARS]
VEHICLE_INDEX RecordedTrafficCarID[MAX_NUMBER_OF_TRAFFIC_CARS_PLAYING_BACK]
VEHICLE_INDEX ParkedCarID[TOTAL_NUMBER_OF_PARKED_CARS]
VEHICLE_INDEX SetPieceCarID[TOTAL_NUMBER_OF_SET_PIECE_CARS]
VEHICLE_INDEX RecordedParkedCarID[MAX_NUMBER_OF_PARKED_CARS_PLAYING_BACK]
VEHICLE_INDEX MainRecordingCar
VEHICLE_INDEX SetPieceRecordingCar
VEHICLE_INDEX DontRemoveThisCar
VEHICLE_INDEX ActiveTrafficCarID[MAX_NUMBER_OF_TRAFFIC_CARS_PLAYING_BACK]
#IF IS_DEBUG_BUILD
BOOL bEnableReRecording = FALSE
BOOL bStartRecordingSetPieceCar = FALSE
BOOL bAllowSetPieceRecOverwrite = TRUE
BOOL bWidgetCreated = FALSE
BOOL bDeleteTrafficWhenRecorded = TRUE
BOOL bDeleteRedundantTrafficCars = TRUE
BOOL bDeleteRedundantParkedCars = TRUE
BOOL bStopParkedCarsFromBeingSpawned = FALSE
BOOL bShowExtraTrafficWidgets = FALSE
BOOL bShowRecordingCone = FALSE
BOOL bResetToStartPosition = FALSE
BOOL bClearArea = FALSE
BOOL bAllRandomCarsAreSwitchedOn = FALSE
BOOL bLoadSetPieceDataForReRec = FALSE
BOOL bReRecSetPieceDataLoaded = FALSE
BOOL bStartSetPieceReRec = FALSE
BOOL bStartReRecOnButtonPress = TRUE
BOOL bShowSetPieceReRecPath = FALSE
BOOL bShowSetPieceReRecGhost = FALSE
BOOL bStopSetPieceReRecOnButtonPress = FALSE
BOOL bShowSetPieceIndices = FALSE
BOOL bShowTrafficIndices = FALSE
BOOL bDrawTrafficProgress = FALSE
BOOL bDrawSetpieceProgress = FALSE
BOOL bShowTriggerCarPath = FALSE
BOOL bShowTrafficCarPaths = FALSE
BOOL bShowSetPiecePaths = FALSE
BOOL bOutputParkedCarInfo = FALSE
BOOL bShowUberWidgets = FALSE
BOOL bPrevShowUberWidgets = FALSE
BOOL bStartRecordingPlayersCarWithTraffic = FALSE
BOOL bIncludeParkedCars = TRUE
BOOL bTrafficDebugOn = FALSE
BOOL bDrawSpeedVector = FALSE
BOOL bOutputCleanedData = FALSE
BOOL bSetPieceCarsToConvert[TOTAL_NUMBER_OF_SET_PIECE_CARS]
BOOL bSetPieceCarsConverted[TOTAL_NUMBER_OF_SET_PIECE_CARS]
INT iHighlightedTrafficCar = -1
INT iHighlightedParkedCar = -1
INT iCurrentNumberOfTrafficRecordings = 0
INT iSetPieceCarRecordingFile = 0
INT iCarsProcessedThisFrame = 0
INT iMainCarRecordingFile = 0
INT iTotalNumberOfParkedCarsRecorded = 0
INT iInitialRecordingFileNumber = 1
INT iTotalNumberOfTrafficCarsRecorded = 0
INT iSetPieceReRecNum = 0
INT iSetPieceReRecNewRecNum = 0
FLOAT fRecordingAngle = 25.0
FLOAT fRecordingHeightAngle = 15.0
FLOAT fRecordingMinHeight = 2.0
FLOAT fRecordingMinWidth = 4.0
FLOAT fRecordingTimer = 0.0
FLOAT fMinRecordingOffset = 5.0
FLOAT fCarDensityMultiplier = 1.0
FLOAT fRecordingDistance = 90.0
FLOAT fTrafficRecordingDistanceAroundCar = 10.0
FLOAT fRecordingClearAreaPercentageOfCone = 0.5
FLOAT fInputPlaybackSpeed
FLOAT fMainRecordingStartQuatX
FLOAT fMainRecordingStartQuatY
FLOAT fMainRecordingStartQuatZ
FLOAT fMainRecordingStartQuatW
VECTOR vMainRecordingStartPosition
BLIP_INDEX HighlightedTrafficCarBlipID
BLIP_INDEX HighlightedParkedCarBlipID
BLIP_INDEX ActiveParkedCarBlipID[MAX_NUMBER_OF_PARKED_CARS_PLAYING_BACK]
BLIP_INDEX ActiveTrafficCarBlipID[MAX_NUMBER_OF_TRAFFIC_CARS_PLAYING_BACK]
VEHICLE_INDEX HighlightedTrafficCarID
VEHICLE_INDEX HighlightedParkedCarID
VEHICLE_INDEX vehForSetPieceReRec
WIDGET_GROUP_ID uberParentWidgetGroup = NULL
WIDGET_GROUP_ID uberWidgetGroup = NULL
#ENDIF
FUNC MODEL_NAMES DEFAULT_PED_MODEL()
IF modelDefaultPed = DUMMY_MODEL_FOR_SCRIPT
RETURN(A_M_Y_BUSINESS_01)
ELSE
RETURN modelDefaultPed
ENDIF
ENDFUNC
FUNC MODEL_NAMES DEFAULT_CAR_MODEL()
RETURN(SULTAN)
ENDFUNC
FUNC MODEL_NAMES COP_CAR_MODEL()
RETURN(POLICE)
ENDFUNC
FUNC MODEL_NAMES COP_PED_MODEL()
RETURN(S_M_Y_COP_01)
ENDFUNC
FUNC BOOL IS_VEH_MODEL_A_COP_MODEL(MODEL_NAMES model)
IF model = POLICE
OR model = POLICE2
OR model = POLICE3
OR model = POLICEB
OR model = POLICET
OR model = POLMAV
OR model = PRANGER
OR model = SHERIFF
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
PROC MARK_CAR_AS_NO_LONGER_NEEDED_KEEP_ID(VEHICLE_INDEX inCar)
IF DOES_ENTITY_EXIST(inCar)
SET_VEHICLE_AS_NO_LONGER_NEEDED(inCar)
ENDIF
ENDPROC
PROC MARK_CHAR_AS_NO_LONGER_NEEDED_KEEP_ID(PED_INDEX inChar)
IF DOES_ENTITY_EXIST(inChar)
SET_PED_AS_NO_LONGER_NEEDED(inChar)
ENDIF
ENDPROC
PROC DONT_LET_UBER_PLAYBACK_CLEANUP_THIS_CAR(VEHICLE_INDEX &InCar)
DontRemoveThisCar = InCar
ENDPROC
/// PURPOSE:
/// If TRUE - forces the uber playback to use the default ped model rather than grabbing random ped models.
PROC SET_FORCE_UBER_PLAYBACK_TO_USE_DEFAULT_PED_MODEL(BOOL bUseDefaultModel)
bTrafficForceDefaultPedModel = bUseDefaultModel
ENDPROC
/// PURPOSE:
/// Traffic cars by default will switch to AI after the trigger car has passed them. Use this procedure to change this behaviour
/// for a given traffic car. This is useful if you find a particular traffic car causing issues when switching to AI early (e.g. swerving
/// into other cars, doing U-turns, etc).
/// PARAMS:
/// iTrafficArrayID - The the traffic car that you want to change.
/// bSwitchToAIEarly - TRUE is the default behaviour, FALSE will stop this car from switching to AI early.
PROC SET_TRAFFIC_CAR_SWITCH_TO_AI_EARLY(INT iTrafficArrayID, BOOL bSwitchToAIEarly)
IF iTrafficArrayID > -1
AND iTrafficArrayID < COUNT_OF(TrafficCarFlags)
IF bSwitchToAIEarly
CLEAR_BIT(TrafficCarFlags[iTrafficArrayID], TRAFFIC_FLAGS_DONT_SWITCH_TO_AI_EARLY)
ELSE
SET_BIT(TrafficCarFlags[iTrafficArrayID], TRAFFIC_FLAGS_DONT_SWITCH_TO_AI_EARLY)
ENDIF
ELSE
#IF IS_DEBUG_BUILD
SCRIPT_ASSERT("SET_TRAFFIC_CAR_SWITCH_TO_AI_EARLY - invalid array ID given.")
#ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// B*1490105 - Used to stop released uber veh drivers interferring with chase by reacting to player shooting
/// SET_PED_FLEE_ATTRIBUTES(pedDriver, FA_FORCE_EXIT_VEHICLE, TRUE)
/// SET_PED_FLEE_ATTRIBUTES(pedDriver, FA_USE_VEHICLE, FALSE)
/// PARAMS:
/// bSetActive - If TRUE flee flags will be set
PROC SET_RELEASED_DRIVERS_TO_EXIT_VEHICLES_ON_FLEE(BOOL bSetActive = FALSE)
bSetReleasedDriversToExitOnFlee = bSetActive
ENDPROC
/// PURPOSE:
/// Changes the default model used by the uber recorder when creating peds.
/// PARAMS:
/// modelPed - The new model, If set to DUMMY_MODEL_FOR_SCRIPT the uber recorder will revert to its own default.
PROC SET_UBER_PLAYBACK_DEFAULT_PED_MODEL(MODEL_NAMES modelPed = DUMMY_MODEL_FOR_SCRIPT)
modelDefaultPed = modelPed
ENDPROC
/// PURPOSE:
/// If TRUE the header will set the default ped model as no longer needed after use. If FALSE it's left up to the mission script to remove the model.
PROC SET_UBER_PLAYBACK_TO_CLEANUP_DEFAULT_PED_MODEL(BOOL bCleanup)
bUberPlaybackRemoveDefaultPedModel = bCleanup
ENDPROC
/// PURPOSE:
/// Replaces the driver of a vehicle in the uber chase with a ped using a given model. For use if there are vehicles in the chase that would require
/// a custom ped different to the default selection.
/// RETURNS:
/// TRUE once the ped has been successfully swapped.
FUNC BOOL OVERRIDE_VEHICLE_DRIVER_MODEL(VEHICLE_INDEX veh, MODEL_NAMES newModel, PED_TYPE pedType = PEDTYPE_MISSION)
IF IS_VEHICLE_DRIVEABLE(veh)
BOOL bOkToCreatePed = FALSE
PED_INDEX ped = GET_PED_IN_VEHICLE_SEAT(veh)
IF DOES_ENTITY_EXIST(ped)
IF ped != PLAYER_PED_ID()
IF GET_ENTITY_MODEL(ped) != newModel
bOkToCreatePed = TRUE
ELSE
RETURN TRUE //Ped already exists and is the correct model.
ENDIF
ENDIF
ELSE
bOkToCreatePed = TRUE
ENDIF
IF bOkToCreatePed
REQUEST_MODEL(newModel)
IF HAS_MODEL_LOADED(newModel)
IF DOES_ENTITY_EXIST(ped)
SET_ENTITY_AS_MISSION_ENTITY(ped)
DELETE_PED(ped)
ENDIF
/*IF IS_ENTITY_A_MISSION_ENTITY(ped)
DELETE_PED(ped)
ELSE
VECTOR v_clear_pos = GET_PED_BONE_COORDS(ped, BONETAG_HEAD, <<0.0, 0.0, 0.0>>)
SET_PED_AS_NO_LONGER_NEEDED(ped)
CLEAR_AREA_OF_PEDS(v_clear_pos, 2.0)
ENDIF*/
PED_INDEX pedNew = CREATE_PED_INSIDE_VEHICLE(veh, pedType, newModel, DEFAULT, FALSE, FALSE)
IF IS_VEH_MODEL_A_COP_MODEL(GET_ENTITY_MODEL(veh))
SET_PED_RELATIONSHIP_GROUP_HASH(pedNew, rgh_traffic)
ENDIF
SET_PED_RANDOM_COMPONENT_VARIATION(pedNew)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(pedNew, TRUE)
SET_ENTITY_ONLY_DAMAGED_BY_PLAYER(pedNew, TRUE)
SET_PED_SUFFERS_CRITICAL_HITS(pedNew, FALSE)
SET_PED_CONFIG_FLAG(pedNew, PCF_WillFlyThroughWindscreen, FALSE)
// B*1490105 - Used to stop released uber veh drivers interferring with chase by reacting to player shooting
IF bSetReleasedDriversToExitOnFlee
SET_PED_FLEE_ATTRIBUTES(pedNew, FA_DISABLE_ACCELERATE_IN_VEHICLE, TRUE)
SET_PED_FLEE_ATTRIBUTES(pedNew, FA_FORCE_EXIT_VEHICLE, TRUE)
SET_PED_FLEE_ATTRIBUTES(pedNew, FA_USE_VEHICLE, FALSE)
SET_DISABLE_PRETEND_OCCUPANTS(veh, TRUE) // see B*1490105 - could affect fps
ENDIF
SET_MODEL_AS_NO_LONGER_NEEDED(newModel)
MARK_CHAR_AS_NO_LONGER_NEEDED_KEEP_ID(pedNew)
RETURN TRUE
ENDIF
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
PROC SWITCH_ALL_RANDOM_CARS_OFF()
SET_ALL_VEHICLE_GENERATORS_ACTIVE_IN_AREA(<<-9000.0, -9000.0, -1000.0>>, <<9000.0, 9000.0, 1500.0>>, FALSE)
SET_NUMBER_OF_PARKED_VEHICLES(0)
SET_GARBAGE_TRUCKS(FALSE)
SET_ALL_LOW_PRIORITY_VEHICLE_GENERATORS_ACTIVE(FALSE)
SET_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME(0.0)
SET_VEHICLE_POPULATION_BUDGET(0)
SET_PED_POPULATION_BUDGET(3)
ENDPROC
PROC SWITCH_ALL_RANDOM_CARS_ON()
SET_ALL_VEHICLE_GENERATORS_ACTIVE()
//SWITCH_ON_ACTIVATED_SCRIPT_CAR_GENS()
SET_NUMBER_OF_PARKED_VEHICLES(-1)
SET_GARBAGE_TRUCKS(TRUE)
SET_ALL_LOW_PRIORITY_VEHICLE_GENERATORS_ACTIVE(TRUE)
SET_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME(1.0)
SET_VEHICLE_POPULATION_BUDGET(3)
SET_PED_POPULATION_BUDGET(3)
ENDPROC
/// PURPOSE:
/// Call every frame to set the vehicle density based on the player's distance from the trigger car.
PROC UPDATE_CAR_DENSITY_BASED_ON_PLAYERS_DISTANCE_FROM_CAR(VEHICLE_INDEX vehTrigger, FLOAT fRadius = 250.0)
IF NOT (bSetPieceRecordingsHaveBeenActivated)
IF NOT IS_ENTITY_DEAD(vehTrigger)
IF IS_PLAYER_PLAYING(PLAYER_ID())
IF (VDIST2(GET_ENTITY_COORDS(vehTrigger), GET_ENTITY_COORDS(PLAYER_PED_ID())) > (fRadius * fRadius))
SET_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME(1.0)
ELSE
SET_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME(0.0)
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
PROC UPDATE_CAR_POPULATION_BUDGET_BASED_ON_PLAYERS_DISTANCE_FROM_CAR(VEHICLE_INDEX vehTrigger, FLOAT fRadius = 250.0)
IF NOT (bSetPieceRecordingsHaveBeenActivated)
IF NOT IS_ENTITY_DEAD(vehTrigger)
IF IS_PLAYER_PLAYING(PLAYER_ID())
IF (VDIST2(GET_ENTITY_COORDS(vehTrigger), GET_ENTITY_COORDS(PLAYER_PED_ID())) > (fRadius * fRadius))
SET_VEHICLE_POPULATION_BUDGET(1)
ELSE
SET_VEHICLE_POPULATION_BUDGET(0)
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Call this every frame before UPDATE_UBER_PLAYBACK to force cars to create without performing any visibility/optimisation checks.
/// Intended use is for forcing cars to create in special cases and debug, calling this during normal playback may cause cars to pop into view.
PROC CREATE_ALL_WAITING_UBER_CARS()
bCreateAllWaitingCars = TRUE
ENDPROC
FUNC BOOL IS_POINT_VISIBLE_TO_PLAYER(VECTOR vPos, FLOAT fRadius, FLOAT fDistance = 100.0)
VECTOR vPlayerPos
VECTOR vDiff
IF NOT IS_SCREEN_FADED_OUT()
IF NOT (bSetPieceRecordingsHaveBeenActivated)
IF NOT (bResetPlaybackToTime)
IF IS_SPHERE_VISIBLE(vPos, fRadius)
IF IS_PLAYER_PLAYING(PLAYER_ID())
vPlayerPos = GET_ENTITY_COORDS(PLAYER_PED_ID())
// vec from player to point
vDiff = vPlayerPos - vPos
// dist from player to edge of sphere
IF ((VMAG(vDiff) - fRadius) < fDistance)
RETURN(TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
RETURN(FALSE)
ENDFUNC
/// PURPOSE:
/// Private function for the uber header: checks if a point is visible or within a given distance of the player's position.
/// Assumes the player's coord has already been passed, this is to cut down on uneccesary calls to fetch coords.
FUNC BOOL private_IS_POINT_VISIBLE_TO_PLAYER_POS(VECTOR vPointPos, VECTOR vPlayerPos, FLOAT fRadius, FLOAT fDistance = 100.0)
IF NOT IS_SCREEN_FADED_OUT()
IF NOT (bSetPieceRecordingsHaveBeenActivated)
IF NOT (bResetPlaybackToTime)
// dist from player to edge of sphere
IF ((VMAG2(vPlayerPos - vPointPos) - fRadius) < fDistance * fDistance)
IF IS_SPHERE_VISIBLE(vPointPos, fRadius)
RETURN TRUE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
/// Private function for the uber header: clears an area of vehicles if safe to do so.
PROC private_SAFE_CLEAR_AREA_OF_VEHICLES(VECTOR vPosToClear, VECTOR vPlayerPos, FLOAT fRadius)
BOOL bSafeToClear = TRUE
IF NOT (bSetPieceRecordingsHaveBeenActivated)
IF NOT private_IS_POINT_VISIBLE_TO_PLAYER_POS(vPosToClear, vPlayerPos, fRadius, 200.0)
// check player's last car is not in this area
IF IS_PLAYER_PLAYING(PLAYER_ID())
VEHICLE_INDEX vehPlayersLastCar
vehPlayersLastCar = GET_PLAYERS_LAST_VEHICLE()
IF NOT IS_ENTITY_DEAD(vehPlayersLastCar)
IF IS_ENTITY_AT_COORD(vehPlayersLastCar, vPosToClear, <<fRadius, fRadius, fRadius>>, FALSE, TRUE)
bSafeToClear = FALSE
ENDIF
ENDIF
ENDIF
IF bSafeToClear
CLEAR_AREA_OF_VEHICLES(vPosToClear, fRadius)
ENDIF
ENDIF
ENDIF
ENDPROC
FUNC BOOL SAFELY_SET_VEHICLE_ON_GROUND_PROPERLY(VEHICLE_INDEX CarID)
MODEL_NAMES CarModel
IF NOT IS_ENTITY_DEAD(CarID)
CarModel = GET_ENTITY_MODEL(CarID)
IF IS_THIS_MODEL_A_CAR(CarModel)
OR IS_THIS_MODEL_A_BIKE(CarModel)
RETURN(SET_VEHICLE_ON_GROUND_PROPERLY(CarID))
ENDIF
ENDIF
RETURN(FALSE)
ENDFUNC
/// PURPOSE:
/// Searches the array of active traffic recordings and finds a free index. Returns -1 if no index was found.
FUNC INT GET_FREE_ACTIVE_CAR_SLOT()
INT i
REPEAT MAX_NUMBER_OF_TRAFFIC_CARS_PLAYING_BACK i
IF NOT DOES_ENTITY_EXIST(ActiveTrafficCarID[i])
RETURN i
ENDIF
ENDREPEAT
RETURN -1
ENDFUNC
/// PURPOSE:
/// Searches the array of recorded traffic cars and finds a free index. Returns -1 if no index was found.
FUNC INT GET_FREE_RECORDED_TRAFFIC_CAR_SLOT()
INT i
REPEAT MAX_NUMBER_OF_TRAFFIC_CARS_PLAYING_BACK i
IF NOT DOES_ENTITY_EXIST(RecordedTrafficCarID[i])
RETURN i
ENDIF
ENDREPEAT
RETURN -1
ENDFUNC
/// PURPOSE:
/// Searches the array of recorded parked cars and finds a free index. Returns -1 if no index was found.
FUNC INT GET_FREE_RECORDED_PARKED_CAR_SLOT()
INT i
REPEAT MAX_NUMBER_OF_PARKED_CARS_PLAYING_BACK i
IF NOT DOES_ENTITY_EXIST(RecordedParkedCarID[i])
RETURN i
ENDIF
ENDREPEAT
RETURN -1
ENDFUNC
/// PURPOSE:
/// Loads a vehicle recording and gets the total duration of it.
FUNC FLOAT GET_RECORDING_LENGTH(INT iRecNo)
REQUEST_VEHICLE_RECORDING(iRecNo, strUberName)
WHILE NOT HAS_VEHICLE_RECORDING_BEEN_LOADED(iRecNo, strUberName)
WAIT(0)
ENDWHILE
FLOAT fRecordingLength = GET_TOTAL_DURATION_OF_VEHICLE_RECORDING(iRecNo, strUberName)
REMOVE_VEHICLE_RECORDING(iRecNo, strUberName)
RETURN fRecordingLength
ENDFUNC
#IF IS_DEBUG_BUILD
PROC SET_UBER_PARENT_WIDGET_GROUP(WIDGET_GROUP_ID parentWidgetGroupID)
uberParentWidgetGroup = parentWidgetGroupID
ENDPROC
PROC CREATE_TRAFFIC_WIDGET()
TEXT_LABEL str
TEXT_LABEL_63 strWidgetName
INT i
IF bShowUberWidgets != bPrevShowUberWidgets
AND bWidgetCreated
DELETE_WIDGET_GROUP(uberWidgetGroup)
bWidgetCreated = FALSE
ENDIF
bPrevShowUberWidgets = bShowUberWidgets
IF NOT (bWidgetCreated)
IF NOT IS_STRING_NULL(strUberName)
strWidgetName = "UBER - "
strWidgetName += strUberName
ELSE
strWidgetName = "Uber Playback / Recording"
ENDIF
IF (uberParentWidgetGroup != NULL)
SET_CURRENT_WIDGET_GROUP(uberParentWidgetGroup)
else
SCRIPT_ASSERT("You have not called SET_UBER_PARENT_WIDGET_GROUP in traffic.sch")
ENDIF
uberWidgetGroup = START_WIDGET_GROUP(strWidgetName)
ADD_WIDGET_BOOL("Show uber playback widgets", bShowUberWidgets)
IF bShowUberWidgets
START_WIDGET_GROUP("Playback")
ADD_WIDGET_FLOAT_SLIDER("fMasterPlaybackSpeed", fMasterPlaybackSpeed, -5.0, 5.0, 0.001)
ADD_WIDGET_FLOAT_SLIDER("Input playback speed", fInputPlaybackSpeed, -5.0, 100.0, 0.001)
ADD_WIDGET_FLOAT_SLIDER("Current Playback Time", fTriggerCarPlaybackTime, 0.0, 9999999.9, 1000.0)
ADD_WIDGET_BOOL("Pause Playback", bPausePlayback)
ADD_WIDGET_BOOL("Delete cars when done", bDeleteCarsWhenDone)
ADD_WIDGET_FLOAT_SLIDER("Reset Time", fResetTime, 0.0, 9999999.9, 1000.0)
ADD_WIDGET_BOOL("Jump To Reset Time", bResetPlaybackToTime)
ADD_WIDGET_INT_SLIDER("Trigger Car Recording", iTriggerCarRecordingNumber, -1, LAST_CAR_RECORDING_FILE_NUMBER, 1)
ADD_WIDGET_BOOL("Show Trigger Car Path", bShowTriggerCarPath)
ADD_WIDGET_BOOL("Output cleaned up data (may take a few seconds)", bOutputCleanedData)
#IF IS_DEBUG_BUILD
ADD_WIDGET_BOOL("Show debug output", bTrafficDebugOn)
#ENDIF
IF (bShowExtraTrafficWidgets)
ADD_WIDGET_BOOL("Enable Re-Recording", bEnableReRecording)
ENDIF
ADD_WIDGET_FLOAT_SLIDER("fPausePlaybackTime", fPausePlaybackTime, 0.0, 1.0, 0.01)
ADD_WIDGET_BOOL("bDontUpdateUberCars", bDontUpdateUberCars)
ADD_WIDGET_BOOL("bCreateAllWaitingCars", bCreateAllWaitingCars)
START_WIDGET_GROUP("Traffic")
ADD_WIDGET_FLOAT_SLIDER("Streaming Distance", fPlaybackCarStreamingDistance, 0.0, 999.9, 1.0)
#IF IS_DEBUG_BUILD
ADD_WIDGET_INT_SLIDER("Highlighted Traffic Car", iHighlightedTrafficCar, -1 , TOTAL_NUMBER_OF_TRAFFIC_CARS, 1)
#ENDIF
ADD_WIDGET_INT_SLIDER("Current No Of Playbacks", iCurrentNumberOfTrafficPlaybacks, 0 , 99, 1)
ADD_WIDGET_BOOL("Show Traffic Paths", bShowTrafficCarPaths)
ADD_WIDGET_BOOL("Show Traffic Indices", bShowTrafficIndices)
ADD_WIDGET_BOOL("Draw Traffic Progress", bDrawTrafficProgress)
ADD_WIDGET_BOOL("Dont switch to AI", bTrafficDontSwitchToAI)
ADD_WIDGET_INT_SLIDER("Cars Processed This Frame", iCarsProcessedThisFrame, -1, 1000, 1)
ADD_WIDGET_INT_SLIDER("First Car to Process", iFirstCarToProcess, -1, 1000, 1)
ADD_WIDGET_INT_SLIDER("iTrafficCarsWaitingToCreate", iTrafficCarsWaitingToCreate, -999, 999, 1)
START_WIDGET_GROUP("Traffic Progress")
REPEAT TOTAL_NUMBER_OF_TRAFFIC_CARS i
str = "Progress["
str += i
str += "]"
ADD_WIDGET_INT_SLIDER(str,TrafficCarProgress[i], -1, 99, 1)
str = "StartTime["
str += i
str += "]"
ADD_WIDGET_FLOAT_SLIDER(str, TrafficCarStartime[i], 0.0, 9999999.9, 1000.0)
str = "StartPos["
str += i
str += "].x"
ADD_WIDGET_FLOAT_SLIDER(str, TrafficCarPos[i].x, -999999.9, 999999.9, 0.00001)
str = "StartPos["
str += i
str += "].y"
ADD_WIDGET_FLOAT_SLIDER(str, TrafficCarPos[i].y, -999999.9, 999999.9, 0.00001)
str = "StartPos["
str += i
str += "].z"
ADD_WIDGET_FLOAT_SLIDER(str, TrafficCarPos[i].z, -999999.9, 999999.9, 0.00001)
ENDREPEAT
STOP_WIDGET_GROUP()
STOP_WIDGET_GROUP()
START_WIDGET_GROUP("Parked Cars")
#IF IS_DEBUG_BUILD
ADD_WIDGET_INT_SLIDER("Highlighted Parked Car", iHighlightedParkedCar, -1 , TOTAL_NUMBER_OF_PARKED_CARS, 1)
#ENDIF
ADD_WIDGET_BOOL("Show parked cars", bShowParkedCars)
ADD_WIDGET_INT_SLIDER("iCurrentNumberOfParkedCars", iCurrentNumberOfParkedCars, 0 , 99, 1)
//ADD_WIDGET_INT_SLIDER("Cars Processed This Frame", iParkedCarsProcessedThisFrame, -1, 1000, 1)
ADD_WIDGET_INT_SLIDER("First Car to Process", iFirstParkedCarToProcess, -1, 1000, 1)
ADD_WIDGET_INT_SLIDER("iParkedCarsWaitingToCreate", iParkedCarsWaitingToCreate, -999, 999, 1)
STOP_WIDGET_GROUP()
START_WIDGET_GROUP("Set Piece Cars")
ADD_WIDGET_INT_SLIDER("Current No Of Playbacks", iCurrentNumberOfSetPieceCarPlaybacks, 0 , 99, 1)
ADD_WIDGET_BOOL("Show Set Piece Paths", bShowSetPiecePaths)
ADD_WIDGET_BOOL("Show Set Piece Indices", bShowSetPieceIndices)
ADD_WIDGET_BOOL("Draw Set Piece Progress", bDrawSetpieceProgress)
ADD_WIDGET_INT_SLIDER("iSetPieceCarsWaitingToCreate", iSetPieceCarsWaitingToCreate, -999, 999, 1)
ADD_WIDGET_INT_SLIDER("First Car to Process", iFirstSetpieceCarToProcess, -1, 1000, 1)
ADD_WIDGET_BOOL("bDrawSpeedVector", bDrawSpeedVector)
START_WIDGET_GROUP("Set Piece Progress")
REPEAT TOTAL_NUMBER_OF_SET_PIECE_CARS i
str = "Progress["
str += i
str += "]"
ADD_WIDGET_INT_SLIDER(str,SetPieceCarProgress[i], -1, 99, 1)
str = "StartTime["
str += i
str += "]"
ADD_WIDGET_FLOAT_SLIDER(str, SetPieceCarStartime[i], 0.0, 9999999.9, 1000.0)
str = "StartPos["
str += i
str += "].x"
ADD_WIDGET_FLOAT_SLIDER(str, SetPieceCarPos[i].x, -999999.9, 999999.9, 0.00001)
str = "StartPos["
str += i
str += "].y"
ADD_WIDGET_FLOAT_SLIDER(str, SetPieceCarPos[i].y, -999999.9, 999999.9, 0.00001)
str = "StartPos["
str += i
str += "].z"
ADD_WIDGET_FLOAT_SLIDER(str, SetPieceCarPos[i].z, -999999.9, 999999.9, 0.00001)
ENDREPEAT
STOP_WIDGET_GROUP()
START_WIDGET_GROUP("Convert Set Piece cars To Traffic cars")
REPEAT TOTAL_NUMBER_OF_SET_PIECE_CARS i
IF (SetPieceCarRecordingSpeed[i] = 1.0)
str = "Car number "
str += i
ADD_WIDGET_BOOL(str, bSetPieceCarsToConvert[i])
ENDIF
ENDREPEAT
ADD_WIDGET_BOOL("Convert & output new data (will take a few seconds)", bOutputCleanedData)
STOP_WIDGET_GROUP()
STOP_WIDGET_GROUP()
START_WIDGET_GROUP("Random Cars")
ADD_WIDGET_BOOL("Clear Random Cars", bCarsAreOn)
ADD_WIDGET_FLOAT_SLIDER("Clear Distance", fClearSurroundingCarsDistance, 0.0, 500.0, 1.0)
STOP_WIDGET_GROUP()
START_WIDGET_GROUP("Air Resistance")
ADD_WIDGET_FLOAT_SLIDER("Current Air Resistance", fAirRes, 1.0, 15.0, 0.01)
ADD_WIDGET_FLOAT_SLIDER("Max Air Resistance", fMaxAirRes, 1.0, 15.0, 0.01)
ADD_WIDGET_FLOAT_SLIDER("Min Air Resistance", fMinAirRes, 1.0, 15.0, 0.01)
ADD_WIDGET_FLOAT_SLIDER("Air Resistance Multiplier", fAirResMultiplier, 0.0, 5.0, 0.01)
STOP_WIDGET_GROUP()
START_WIDGET_GROUP("Debug Stuff")
ADD_WIDGET_BOOL("bAllRandomCarsAreSwitchedOn", bAllRandomCarsAreSwitchedOn)
ADD_WIDGET_FLOAT_SLIDER("fPlaybackSpeedMaxAcceleration", fPlaybackSpeedMaxAcceleration, 0.0, 5.0, 0.01)
ADD_WIDGET_FLOAT_SLIDER("fPlaybackSpeedMaxDecceleration", fPlaybackSpeedMaxDecceleration, 0.0, 5.0, 0.01)
ADD_WIDGET_BOOL("bPlayerIsAheadOfChase", bPlayerIsAheadOfChase)
ADD_WIDGET_FLOAT_SLIDER("fSwitchOffRoadDist", fSwitchOffRoadDist, 0.0, 1000.0, 1.0)
ADD_WIDGET_BOOL("bCalculatePlaybackSpeedInitialised", bCalculatePlaybackSpeedInitialised)
ADD_WIDGET_BOOL("bCreateAllWaitingCars", bCreateAllWaitingCars)
STOP_WIDGET_GROUP()
STOP_WIDGET_GROUP()
START_WIDGET_GROUP("Recording")
ADD_WIDGET_BOOL("Start Recording", bStartRecordingPlayersCarWithTraffic)
ADD_WIDGET_FLOAT_SLIDER("Recording Time", fRecordingTimer, 0.0, 9999999.9, 1.0)
ADD_WIDGET_BOOL("Reset to start position", bResetToStartPosition)
ADD_WIDGET_BOOL("Clear surrounding area", bClearArea)
ADD_WIDGET_FLOAT_SLIDER("Car Density Multiplier", fCarDensityMultiplier, 0.0, 100.0, 0.1)
START_WIDGET_GROUP("Trigger Car")
ADD_WIDGET_INT_SLIDER("Recording File", iMainCarRecordingFile, 0, LAST_CAR_RECORDING_FILE_NUMBER, 1)
STOP_WIDGET_GROUP()
START_WIDGET_GROUP("Traffic")
ADD_WIDGET_INT_SLIDER("First Traffic Recording File", iInitialRecordingFileNumber, 0, LAST_CAR_RECORDING_FILE_NUMBER, 1)
ADD_WIDGET_INT_SLIDER("Current No Of Recordings", iCurrentNumberOfTrafficRecordings, 0, 99, 1)
ADD_WIDGET_INT_SLIDER("Total No Of Recordings", iTotalNumberOfTrafficCarsRecorded, 0, TOTAL_NUMBER_OF_TRAFFIC_CARS, 1)
ADD_WIDGET_FLOAT_SLIDER("Recording Distance", fRecordingDistance, 0.0, 200.0, 1.0)
ADD_WIDGET_FLOAT_SLIDER("Recording Offset", fMinRecordingOffset, 0.0, 100.0, 0.1)
ADD_WIDGET_FLOAT_SLIDER("Recording Angle", fRecordingAngle, 0.0, 179.0, 1.0)
ADD_WIDGET_FLOAT_SLIDER("Recording Height Angle", fRecordingHeightAngle, 0.0, 89.0, 1.0)
ADD_WIDGET_FLOAT_SLIDER("Recording Min Width", fRecordingMinWidth, 0.0, 20.0, 0.1)
ADD_WIDGET_FLOAT_SLIDER("Recording Min Height", fRecordingMinHeight, 0.0, 20.0, 0.1)
ADD_WIDGET_BOOL("Draw Recording Cone", bShowRecordingCone)
//ADD_WIDGET_BOOL("Delete when recorded", bDeleteTrafficWhenRecorded)
ADD_WIDGET_FLOAT_SLIDER("fRecordingClearAreaPercentageOfCone", fRecordingClearAreaPercentageOfCone, 0.0, 1.0, 0.01)
ADD_WIDGET_FLOAT_SLIDER("fTrafficRecordingDistanceAroundCar", fTrafficRecordingDistanceAroundCar, 0.0, 100.0, 0.1)
ADD_WIDGET_BOOL("bDeleteRedundantTrafficCars", bDeleteRedundantTrafficCars)
STOP_WIDGET_GROUP()
START_WIDGET_GROUP("Parked Cars")
ADD_WIDGET_BOOL("Output current vehicle as a parked car", bOutputParkedCarInfo)
ADD_WIDGET_BOOL("stop parked cars spawning", bStopParkedCarsFromBeingSpawned)
ADD_WIDGET_BOOL("include parked cars", bIncludeParkedCars)
ADD_WIDGET_INT_SLIDER("iTotalNumberOfParkedCarsRecorded", iTotalNumberOfParkedCarsRecorded, 0, 99, 1)
ADD_WIDGET_BOOL("bDeleteRedundantParkedCars", bDeleteRedundantParkedCars)
STOP_WIDGET_GROUP()
START_WIDGET_GROUP("Set Piece Cars")
ADD_WIDGET_BOOL("Set Environment for set piece recording", bSetPieceRecordingsAreActive)
ADD_WIDGET_BOOL("Allow set piece recording overwrite", bAllowSetPieceRecOverwrite)
ADD_WIDGET_BOOL("record new car", bStartRecordingSetPieceCar)
ADD_WIDGET_INT_SLIDER("iSetPieceCarRecordingFile", iSetPieceCarRecordingFile, 0 , LAST_CAR_RECORDING_FILE_NUMBER, 1)
ADD_WIDGET_FLOAT_SLIDER("fNewSetPieceTriggerTime", fNewSetPieceTriggerTime, 0.0, 99999999.9, 1.0)
ADD_WIDGET_BOOL("Grab current position as start", bReGrabSetPiecePositionAndQuat)
ADD_WIDGET_BOOL("bResetSetPiece", bResetSetPiece)
#IF IS_DEBUG_BUILD
START_WIDGET_GROUP("Set piece re-record")
ADD_WIDGET_INT_SLIDER("Set piece array index", iSetPieceReRecNum, 0 , (TOTAL_NUMBER_OF_SET_PIECE_CARS-1), 1)
ADD_WIDGET_BOOL("Load set piece data and go to start", bLoadSetPieceDataForReRec)
ADD_WIDGET_INT_SLIDER("New setpiece recording number", iSetPieceReRecNewRecNum, 0 , LAST_CAR_RECORDING_FILE_NUMBER, 1)
add_widget_bool("Start Recording when accelerator is pressed?", bStartReRecOnButtonPress)
ADD_WIDGET_BOOL("Start recording", bStartSetPieceReRec)
add_widget_bool("Stop Recording when PS SQUARE OR XBOX X is pressed", bStopSetPieceReRecOnButtonPress)
add_widget_bool("Show Setpiece Recording Path", bShowSetPieceReRecPath)
add_widget_bool("Show Setpiece Ghost Car", bShowSetPieceReRecGhost)
STOP_WIDGET_GROUP()
#ENDIF
STOP_WIDGET_GROUP()
IF (bShowExtraTrafficWidgets)
START_WIDGET_GROUP("Re-Recording")
ADD_WIDGET_BOOL("bReRecordingIsEnabled", bReRecordingIsEnabled)
ADD_WIDGET_BOOL("bReRecordingControlHijacked", bReRecordingControlHijacked)
STOP_WIDGET_GROUP()
ENDIF
STOP_WIDGET_GROUP()
ENDIF
STOP_WIDGET_GROUP()
IF (uberParentWidgetGroup != NULL)
CLEAR_CURRENT_WIDGET_GROUP(uberParentWidgetGroup)
ENDIF
bWidgetCreated = TRUE
ENDIF
ENDPROC
#ENDIF
/// PURPOSE:
/// Private function for the traffic header: creates a ped inside a given uber playback vehicle, will determine the right ped based on vehicle type and availability
/// of ambient ped models. NOTE: assumes that the ped model has already loaded.
/// PARAMS:
/// veh - The vehicle to add the ped inside
/// modelVeh - The model of the vehicle
/// ePedModelToUse - Which model typre to use (e.g. cops, default, or attempt to use ambient population).
/// RETURNS:
/// TRUE if the ped successfully created.
FUNC BOOL private_CREATE_PED_INSIDE_UBER_PLAYBACK_CAR(VEHICLE_INDEX &veh, UBER_PLAYBACK_PED_MODEL ePedModelToUse, BOOL bCarIsASetpiece = FALSE)
IF NOT IS_ENTITY_DEAD(veh)
IF IS_VEHICLE_SEAT_FREE(veh, VS_DRIVER)
PED_INDEX pedTemp
IF ePedModelToUse = UBER_PLAYBACK_PED_MODEL_COP
pedTemp = CREATE_PED_INSIDE_VEHICLE(veh, PEDTYPE_COP, COP_PED_MODEL(), DEFAULT, FALSE, FALSE)
SET_PED_RELATIONSHIP_GROUP_HASH(pedTemp, rgh_traffic)
SET_MODEL_AS_NO_LONGER_NEEDED(COP_PED_MODEL())
ELIF ePedModelToUse = UBER_PLAYBACK_PED_MODEL_AMBIENT
pedTemp = CREATE_RANDOM_PED_AS_DRIVER(veh)
IF IS_THIS_MODEL_A_BIKE(GET_ENTITY_MODEL(veh))
GIVE_PED_HELMET(pedTemp)
ENDIF
ELSE
pedTemp = CREATE_PED_INSIDE_VEHICLE(veh, PEDTYPE_CIVMALE, DEFAULT_PED_MODEL(), DEFAULT, FALSE, FALSE)
IF bUberPlaybackRemoveDefaultPedModel
SET_MODEL_AS_NO_LONGER_NEEDED(DEFAULT_PED_MODEL())
ENDIF
ENDIF
IF bCarIsASetpiece
SET_ENTITY_ONLY_DAMAGED_BY_PLAYER(pedTemp, TRUE)
SET_PED_SUFFERS_CRITICAL_HITS(pedTemp, FALSE)
SET_PED_CONFIG_FLAG(pedTemp, PCF_WillFlyThroughWindscreen, FALSE)
ENDIF
// B*1490105 - Used to stop released uber veh drivers interferring with chase by reacting to player shooting
IF bSetReleasedDriversToExitOnFlee
SET_PED_FLEE_ATTRIBUTES(pedTemp, FA_DISABLE_ACCELERATE_IN_VEHICLE, TRUE)
SET_PED_FLEE_ATTRIBUTES(pedTemp, FA_FORCE_EXIT_VEHICLE, TRUE)
SET_PED_FLEE_ATTRIBUTES(pedTemp, FA_USE_VEHICLE, FALSE)
SET_DISABLE_PRETEND_OCCUPANTS(veh, TRUE) // see B*1490105 - could affect fps
ENDIF
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(pedTemp, TRUE)
MARK_CHAR_AS_NO_LONGER_NEEDED_KEEP_ID(pedTemp)
bCreatedUberPlaybackEntityThisFrame = TRUE
#IF IS_DEBUG_BUILD
IF (bTrafficDebugOn)
PRINTLN("traffic.sch - private_CREATE_PED_INSIDE_UBER_PLAYBACK_CAR ", fTriggerCarPlaybackTime, " bCarIsASetpiece = ", PICK_INT(bCarIsASetpiece, 1, 0))
ENDIF
#ENDIF
RETURN TRUE
ELSE
//Already a ped in the seat, just RETURN TRUE.
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
FUNC FLOAT GET_DISTANCE_FROM_LEAD_CAR(VEHICLE_INDEX LeadCar, VEHICLE_INDEX FollowCar)
// Car A is assumed to be the car in front
VECTOR vForward
VECTOR vAB
VECTOR vPosA
VECTOR vPosB
FLOAT fAngle
IF IS_VEHICLE_DRIVEABLE(LeadCar)
vForward.x = GET_ENTITY_FORWARD_X(LeadCar)
vForward.y = GET_ENTITY_FORWARD_Y(LeadCar)
vPosA = GET_ENTITY_COORDS(LeadCar)
ENDIF
IF IS_VEHICLE_DRIVEABLE(FollowCar)
vPosB = GET_ENTITY_COORDS(FollowCar)
ENDIF
vAB = vPosB - vPosA
fAngle = GET_ANGLE_BETWEEN_2D_VECTORS(vAB.x, vAB.y, vForward.x, vForward.y)
fAngle += -90.0
IF (fAngle < 0.0)
fAngle *= -1.0
ENDIF
vAB.z = 0.0
RETURN VMAG(vAB) * SIN(fAngle)
ENDFUNC
FUNC BOOL IS_CAR_FURTHER_IN_FRONT_THAN_WIDE(VEHICLE_INDEX LeadCar, VEHICLE_INDEX FollowCar)
IF NOT IS_ENTITY_DEAD(LeadCar)
AND NOT IS_ENTITY_DEAD(FollowCar)
VECTOR vOffset = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(LeadCar, GET_ENTITY_COORDS(FollowCar))
IF ABSF(vOffset.y) > ABSF(vOffset.x)
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
FUNC FLOAT GET_CHAR_DISTANCE_FROM_LEAD_CAR(VEHICLE_INDEX LeadCar, PED_INDEX FollowChar)
// Car A is assumed to be the car in front
VECTOR vForward
VECTOR vAB
VECTOR vPosA
VECTOR vPosB
FLOAT fAngle
IF IS_VEHICLE_DRIVEABLE(LeadCar)
vForward.x = GET_ENTITY_FORWARD_X(LeadCar)
vForward.y = GET_ENTITY_FORWARD_Y(LeadCar)
vPosA = GET_ENTITY_COORDS(LeadCar)
ENDIF
IF NOT IS_ENTITY_DEAD(FollowChar)
vPosB = GET_ENTITY_COORDS(FollowChar)
ENDIF
vAB = vPosB - vPosA
fAngle = GET_ANGLE_BETWEEN_2D_VECTORS(vAB.x, vAB.y, vForward.x, vForward.y)
fAngle += -90.0
IF (fAngle < 0.0)
fAngle *= -1.0
ENDIF
vAB.z = 0.0
RETURN(VMAG(vAB) * SIN(fAngle))
ENDFUNC
FUNC FLOAT GET_ACTUAL_CHAR_DISTANCE_FROM_LEAD_CAR(VEHICLE_INDEX LeadCar, PED_INDEX FollowChar)
// Car A is assumed to be the car in front
VECTOR vPosA
VECTOR vPosB
VECTOR vAB
FLOAT fDist
IF NOT IS_ENTITY_DEAD(LeadCar)
vPosA = GET_ENTITY_COORDS(LeadCar)
ENDIF
IF NOT IS_ENTITY_DEAD(FollowChar)
vPosB = GET_ENTITY_COORDS(FollowChar)
ENDIF
vAB = vPosB - vPosA
vAB.z = 0.0
fDist = VMAG(vAB)
RETURN(fDist)
ENDFUNC
FUNC FLOAT GET_DIFF_IN_SPEED_HEADINGS_BETWEEN_CHAR_AND_LEAD_CAR(VEHICLE_INDEX LeadCar, PED_INDEX FollowChar)
VECTOR vA
VECTOR vPosB, vPosB2, vB
FLOAT fDiff
VEHICLE_INDEX temp_car
IF NOT IS_ENTITY_DEAD(LeadCar)
// GET_VEHICLE_COORDS @_return_by_value(LeadCar, vPosA.x, vPosA.y, vPosA.z)
// GET_OFFSET_FROM_VEHICLE_IN_WORLD_COORDS @_return_by_value(LeadCar, 0.0, 5.0, 0.0, vPosA2.x, vPosA2.y, vPosA2.z)
// vA = vPosA2 - vPosA
vA.x = GET_ENTITY_FORWARD_X(LeadCar)
vA.y = GET_ENTITY_FORWARD_Y(LeadCar)
ENDIF
IF NOT IS_ENTITY_DEAD(FollowChar)
vPosB = GET_ENTITY_COORDS(FollowChar)
IF IS_PED_IN_ANY_VEHICLE(FollowChar)
temp_car = GET_VEHICLE_PED_IS_IN(FollowChar)
//GET_OFFSET_FROM_VEHICLE_IN_WORLD_COORDS @_return_by_value(FollowChar, 0.0, 5.0, 0.0, vPosB2.x, vPosB2.y, vPosB2.z)
vB.x = GET_ENTITY_FORWARD_X(temp_car)
vB.y = GET_ENTITY_FORWARD_Y(temp_car)
ELSE
vPosB2 = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(FollowChar, <<0.0, 5.0, 0.0>>)
vB = vPosB2 - vPosB
ENDIF
//LINE(vPosB.x, vPosB.y, vPosB.z, vPosB2.x, vPosB2.y, vPosB2.z)
ENDIF
fDiff = GET_ANGLE_BETWEEN_2D_VECTORS(vA.x, vA.y, vB.x, vB.y)
RETURN(fDiff)
ENDFUNC
FUNC BOOL IS_CAR_IN_FRONT_OF_CAR(VEHICLE_INDEX inCar1, VEHICLE_INDEX inCar2, BOOL bBaseOnCar2Speed = FALSE)
VECTOR posA // car1 position
VECTOR posB // car2 position
VECTOR posC
VECTOR vecAB // vector from car1 to car2
VECTOR vecCar2 // unit vector pointing in the direction the car2 is facing
VECTOR vVel
// get positions
IF IS_VEHICLE_DRIVEABLE(inCar1)
posA = GET_ENTITY_COORDS(inCar1)
ENDIF
IF IS_VEHICLE_DRIVEABLE(inCar2)
posB = GET_ENTITY_COORDS(inCar2)
// get unit vector pointing forwards from car2
IF bBaseOnCar2Speed
vVel = GET_ENTITY_VELOCITY(inCar2)
vecCar2 = vVel / VMAG(vVel)
ELSE
posC = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(inCar2, <<0.0, 5.0, 0.0>>)
vecCar2 = posC - posB
ENDIF
ENDIF
// get vec from car1 to car2
vecAB = posB - posA
// take the z out
vecAB.z = 0.0
vecCar2.z = 0.0
// calculate dot product of vecAB and vecCar2
IF (DOT_PRODUCT(vecAB,vecCar2) < 0.0)
RETURN(TRUE)
ENDIF
RETURN(FALSE)
ENDFUNC
FUNC BOOL IS_PED_IN_FRONT_OF_CAR(PED_INDEX inPed, VEHICLE_INDEX inCar)
VECTOR posA // ped position
VECTOR posB // car position
VECTOR posC
VECTOR vecAB // vector from ped to car
VECTOR vecCar // unit vector pointing in the direction the car is facing
FLOAT fTemp
// If ped is in this car RETURN FALSE
IF NOT IS_PED_INJURED(inPed)
IF NOT IS_ENTITY_DEAD(inCar)
IF IS_PED_IN_VEHICLE(inPed, inCar)
RETURN(FALSE)
ENDIF
ENDIF
ENDIF
// get positions
IF NOT IS_ENTITY_DEAD(inPed)
posA = GET_ENTITY_COORDS(inPed)
ENDIF
IF IS_VEHICLE_DRIVEABLE(inCar)
posB = GET_ENTITY_COORDS(inCar)
// get unit vector pointing forwards from car
posC = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(inCar, <<0.0, 5.0, 0.0>>)
vecCar = posC - posB
ENDIF
// get vec from ped to car
vecAB = posB - posA
// take the z out
vecAB.z = 0.0
vecCar.z = 0.0
// calculate dot product of vecAB and vecCar2
fTemp = DOT_PRODUCT(vecAB,vecCar)
IF (fTemp < 0.0)
RETURN(TRUE)
ENDIF
RETURN(FALSE)
ENDFUNC
FUNC BOOL ARE_CARS_TRAVELLING_IN_SAME_DIRECTION(VEHICLE_INDEX inCar1, VEHICLE_INDEX inCar2)
VECTOR vForward1
VECTOR vForward2
FLOAT fTemp
IF IS_VEHICLE_DRIVEABLE(inCar1)
vForward1 = GET_ENTITY_SPEED_VECTOR(inCar1)
ELSE
RETURN(FALSE)
ENDIF
IF IS_VEHICLE_DRIVEABLE(inCar2)
vForward2 = GET_ENTITY_SPEED_VECTOR(inCar2)
ELSE
RETURN(FALSE)
ENDIF
// ignore the z
vForward1.z = 0.0
vForward2.z = 0.0
fTemp = DOT_PRODUCT(vForward1,vForward2)
IF (fTemp < 0.0)
RETURN(FALSE)
ENDIF
RETURN(TRUE)
ENDFUNC
FUNC BOOL ARE_CARS_TRAVELLING_IN_SAME_DIRECTION_BELOW_ANGLE(VEHICLE_INDEX inCar1, VEHICLE_INDEX inCar2, FLOAT fInAngle)
VECTOR vForward1
VECTOR vForward2
FLOAT fTemp
IF IS_VEHICLE_DRIVEABLE(inCar1)
vForward1 = GET_ENTITY_SPEED_VECTOR(inCar1)
ELSE
RETURN(FALSE)
ENDIF
IF IS_VEHICLE_DRIVEABLE(inCar2)
vForward2 = GET_ENTITY_SPEED_VECTOR(inCar2)
ELSE
RETURN(FALSE)
ENDIF
// ignore the z
vForward1.z = 0.0
vForward2.z = 0.0
fTemp = DOT_PRODUCT(vForward1,vForward2)
IF (fTemp < 0.0)
RETURN(FALSE)
ENDIF
// check is within angle
fTemp = GET_ANGLE_BETWEEN_2D_VECTORS(vForward1.x, vForward1.y, vForward2.x, vForward2.y)
IF NOT (fTemp < fInAngle)
RETURN(FALSE)
ENDIF
RETURN(TRUE)
ENDFUNC
PROC DRAW_CAR_SPEED_VECTOR(VEHICLE_INDEX inCar)
VECTOR vForward
VECTOR vPos
IF IS_VEHICLE_DRIVEABLE(inCar)
vForward = GET_ENTITY_SPEED_VECTOR(inCar)
vForward *= 5.0
vPos = GET_ENTITY_COORDS(inCar)
DRAW_DEBUG_LINE(vPos, <<vPos.x+vForward.x, vPos.y+vForward.y, vPos.z+vForward.z>>)
ENDIF
ENDPROC
FUNC BOOL SET_CAR_AT_PLAYBACK_POSITION(VEHICLE_INDEX &InCar, INT iRec, FLOAT fTime, BOOL bPlay, BOOL bUseAI, BOOL bForceUpdate = FALSE,
BOOL bSwitchToAIOnPlayerImpact = FALSE, BOOL bSwitchToAIOnAnyImpact = FALSE)
FLOAT fTemp
IF (iRec > 0)
REQUEST_VEHICLE_RECORDING(iRec, strUberName)
IF HAS_VEHICLE_RECORDING_BEEN_LOADED(iRec, strUberName)
IF IS_VEHICLE_DRIVEABLE(InCar)
IF NOT IS_PLAYBACK_GOING_ON_FOR_VEHICLE(InCar)
FREEZE_ENTITY_POSITION(InCar, FALSE)
IF (bUseAI)
START_PLAYBACK_RECORDED_VEHICLE_USING_AI(InCar, iRec, strUberName)
ELSE
IF iRec != iDontSwitchThisSetpieceRecordingToAI
AND iRec != iDontSwitchThisSetpieceRecordingToAI2
IF bSwitchToAIOnAnyImpact
START_PLAYBACK_RECORDED_VEHICLE_WITH_FLAGS(InCar, iRec, strUberName, ENUM_TO_INT(SWITCH_ON_ANY_VEHICLE_IMPACT) | ENUM_TO_INT(TURN_ON_ENGINE_INSTANTLY))
ELIF bSwitchToAIOnPlayerImpact
START_PLAYBACK_RECORDED_VEHICLE_WITH_FLAGS(InCar, iRec, strUberName, ENUM_TO_INT(SWITCH_ON_PLAYER_VEHICLE_IMPACT) | ENUM_TO_INT(TURN_ON_ENGINE_INSTANTLY))
ELSE
START_PLAYBACK_RECORDED_VEHICLE(InCar, iRec, strUberName)
ENDIF
ELSE
START_PLAYBACK_RECORDED_VEHICLE(InCar, iRec, strUberName)
ENDIF
SKIP_TIME_IN_PLAYBACK_RECORDED_VEHICLE(InCar, fTime)
IF bForceUpdate
FORCE_PLAYBACK_RECORDED_VEHICLE_UPDATE(InCar)
ENDIF
RETURN(TRUE)
ENDIF
ELSE
IF (GET_CURRENT_PLAYBACK_FOR_VEHICLE(InCar) = GET_VEHICLE_RECORDING_ID(iRec, strUberName))
fTemp = GET_TIME_POSITION_IN_RECORDING(InCar)
SKIP_TIME_IN_PLAYBACK_RECORDED_VEHICLE(InCar, (fTime - fTemp))
IF NOT (bPlay)
STOP_PLAYBACK_RECORDED_VEHICLE(InCar)
REQUEST_VEHICLE_RECORDING(iRec, strUberName)
ENDIF
IF bForceUpdate
FORCE_PLAYBACK_RECORDED_VEHICLE_UPDATE(InCar)
ENDIF
RETURN(TRUE)
ELSE
STOP_PLAYBACK_RECORDED_VEHICLE(InCar)
FREEZE_ENTITY_POSITION(InCar, FALSE)
IF (bUseAI)
START_PLAYBACK_RECORDED_VEHICLE_USING_AI(InCar, iRec, strUberName)
ELSE
IF iRec != iDontSwitchThisSetpieceRecordingToAI
AND iRec != iDontSwitchThisSetpieceRecordingToAI2
IF bSwitchToAIOnAnyImpact
START_PLAYBACK_RECORDED_VEHICLE_WITH_FLAGS(InCar, iRec, strUberName, ENUM_TO_INT(SWITCH_ON_ANY_VEHICLE_IMPACT) | ENUM_TO_INT(TURN_ON_ENGINE_INSTANTLY))
ELIF bSwitchToAIOnPlayerImpact
START_PLAYBACK_RECORDED_VEHICLE_WITH_FLAGS(InCar, iRec, strUberName, ENUM_TO_INT(SWITCH_ON_PLAYER_VEHICLE_IMPACT) | ENUM_TO_INT(TURN_ON_ENGINE_INSTANTLY))
ELSE
START_PLAYBACK_RECORDED_VEHICLE(InCar, iRec, strUberName)
ENDIF
ELSE
START_PLAYBACK_RECORDED_VEHICLE(InCar, iRec, strUberName)
ENDIF
ENDIF
SKIP_TIME_IN_PLAYBACK_RECORDED_VEHICLE(InCar, fTime)
IF bForceUpdate
FORCE_PLAYBACK_RECORDED_VEHICLE_UPDATE(InCar)
ENDIF
RETURN(TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
ELSE
#IF IS_DEBUG_BUILD
SCRIPT_ASSERT("SET_CAR_AT_PLAYBACK_POSITION - recording ID must be greater than 0.")
#ENDIF
ENDIF
RETURN(FALSE)
ENDFUNC
/// PURPOSE:
/// New rubber-banding procedure for GTA V: takes into account special abilities and can reduce the player's max speed using new commands.
/// PARAMS:
/// fDesiredPlaybackSpeed - Stores the calculated speed.
/// vehPlayer - The player's vehicle
/// vehTrigger - The trigger vehicle
/// fClosestDist - The minimum distance the player should be behind the trigger.
/// fIdealDist - The ideal distance you want the player to be behind the trigger.
/// fMaxDist - The max distance the player should be behind the trigger.
/// fLosingTriggerDist - At this distance or greater extra slowdown will be applied if safe to do so.
/// fMaxDistInFront - If the player is ahead the speed is increased, the max speed is achieved at this distance.
/// fDefaultPlaybackSpeed - The default playback speed: when at the ideal distance the chase will run around this speed.
/// fMinSpeedIfBehind - The minimum playback speed allowed if behind, values lower than 0.7 may be too noticeable.
/// fMinSpeedIfLosingTrigger - The minimum playback speed allowed if the player is really far behind (this value is only used IF the trigger is not visible).
/// fMaxSpeedIfTooClose - The max speed allowed if the player gets too close.
/// bApplySlowdownToPlayer - If TRUE slowdown will be applied to the player based on playback speed (using MODIFY_VEHICLE_TOP_SPEED).
/// fDefaultSlowdownPercent - The default percentage of top speed removed from the player.
/// fMaxPlayerSlowdownPercent - The maximum percentage of top speed that can be removed from the player.
/// bAccountForSpecialAbility - If TRUE then extra adjustments are made when Franklin's special ability is active.
PROC CALCULATE_DESIRED_PLAYBACK_SPEED_FROM_TRIGGER_CAR(FLOAT &fDesiredPlaybackSpeed, VEHICLE_INDEX &vehPlayer, VEHICLE_INDEX vehTrigger,
FLOAT fClosestDist = 5.0, FLOAT fIdealDist = 10.0, FLOAT fMaxDist = 50.0, FLOAT fLosingTriggerDist = 100.0,
FLOAT fMaxDistInFront = 30.0, FLOAT fDefaultPlaybackSpeed = 1.0, FLOAT fMinSpeedIfBehind = 0.7, FLOAT fMinSpeedIfLosingTrigger = 0.5,
FLOAT fMaxSpeedIfTooClose = 2.0, BOOL bApplySlowdownToPlayer = FALSE, FLOAT fDefaultSlowdownPercent = 0.0, FLOAT fMaxSlowdownPercent = 15.0,
BOOL bAccountForSpecialAbility = TRUE)
VECTOR vPlayerPos = GET_ENTITY_COORDS(vehPlayer)
VECTOR vTriggerPos = GET_ENTITY_COORDS(vehTrigger)
VECTOR vOffset = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(vehTrigger, vPlayerPos)
FLOAT fDist = VDIST(vPlayerPos, vTriggerPos)
FLOAT fDistRatio = 0.0
FLOAT fMaxSpeedToAddIfClose = fMaxSpeedIfTooClose - 1.0
FLOAT fMaxSpeedToRemoveIfBehind = 1.0 - fMinSpeedIfBehind
IF vOffset.y < 1.0 //Player is behind the car.
IF fDist > fMaxDist //Player is a long way behind, slow the trigger car down even more (if not on screen).
BOOL bReallyFarBehind = FALSE
IF fDist > fLosingTriggerDist
IF fDist > fLosingTriggerDist * 2.0
bReallyFarBehind = TRUE
ENDIF
fDist = fLosingTriggerDist
ENDIF
fDistRatio = ((fDist - fMaxDist) / (fLosingTriggerDist - fMaxDist))
IF NOT IS_ENTITY_ON_SCREEN(vehTrigger) OR bReallyFarBehind
fDesiredPlaybackSpeed = fMinSpeedIfBehind - ((fMinSpeedIfBehind - fMinSpeedIfLosingTrigger) * fDistRatio)
ELSE
//Not safe to slow down any further, so cap at min speed.
fDesiredPlaybackSpeed = fMinSpeedIfBehind
ENDIF
ELIF fDist > fIdealDist //Player is slightly behind ideal distance. Slow the trigger car down relative to how far behind the player is.
fDistRatio = ((fDist - fIdealDist) / (fMaxDist - fIdealDist))
fDesiredPlaybackSpeed = 1.0 - (fMaxSpeedToRemoveIfBehind * fDistRatio)
ELSE //Player is getting too close, speed up the trigger car relative to how close the player is.
IF fDist < fClosestDist
fDist = fClosestDist
ENDIF
fDistRatio = (fIdealDist - fDist) / (fIdealDist - fClosestDist)
IF IS_SPECIAL_ABILITY_ACTIVE(PLAYER_ID())
AND bAccountForSpecialAbility
fDesiredPlaybackSpeed = 1.0 + ((fDistRatio * fMaxSpeedToAddIfClose) * 2.0)
ELSE
fDesiredPlaybackSpeed = 1.0 + (fDistRatio * fMaxSpeedToAddIfClose)
ENDIF
ENDIF
ELSE //Player is in front, speed up trigger car based on the player's own speed.
IF fDist > fMaxDistInFront
fDist = fMaxDistInFront
ENDIF
fDistRatio = fDist / fMaxDistInFront
FLOAT fSpeedDiff = GET_ENTITY_SPEED(vehTrigger) - GET_ENTITY_SPEED(vehPlayer)
//If the player is already going slower then don't speed up the buddy as much.
IF fSpeedDiff > 0.0
fDistRatio = fDistRatio * 0.5
ENDIF
IF IS_SPECIAL_ABILITY_ACTIVE(PLAYER_ID())
AND bAccountForSpecialAbility
fDesiredPlaybackSpeed = 2.0 + fDistRatio
ELSE
IF GET_ENTITY_SPEED(vehPlayer) < 5.0
AND fSpeedDiff > 0.0
//If the player has slowed down slow the buddy down so it's not as harsh if they plough through.
fDesiredPlaybackSpeed = 0.6 + fDistRatio
ELSE
fDesiredPlaybackSpeed = 1.0 + fDistRatio
ENDIF
ENDIF
ENDIF
//Adjust final value for any differences in the default.
fDesiredPlaybackSpeed = fDesiredPlaybackSpeed * fDefaultPlaybackSpeed
//Modify the player's speed if the desired playback speed is getting too much.
IF bApplySlowdownToPlayer
FLOAT fPlayersSpeedModifier = fDefaultSlowdownPercent
IF IS_SPECIAL_ABILITY_ACTIVE(PLAYER_ID())
AND bAccountForSpecialAbility
fMaxSlowdownPercent = fMaxSlowdownPercent * 2.0
fDefaultSlowdownPercent = fDefaultSlowdownPercent * 2.0
ENDIF
IF fDesiredPlaybackSpeed > 1.0
fPlayersSpeedModifier = fDefaultSlowdownPercent + ((fMaxSlowdownPercent - fDefaultSlowdownPercent) * (fDesiredPlaybackSpeed - 1.0))
ENDIF
MODIFY_VEHICLE_TOP_SPEED(vehPlayer, -fPlayersSpeedModifier)
ENDIF
ENDPROC
/// PURPOSE:
/// Same as CALCULATE_DESIRED_PLAYBACK_SPEED_FROM_TRIGGER_CAR but with new updates for NG/DLC: this is currently added separately otherwise it will change how the rubber banding works for old missions, but can
/// be used for any new DLC missions (on the next standalone project this will replace the old proc).
PROC CALCULATE_DESIRED_PLAYBACK_SPEED_FROM_TRIGGER_CAR_NG_VERSION(FLOAT &fDesiredPlaybackSpeed, VEHICLE_INDEX &vehPlayer, VEHICLE_INDEX vehTrigger,
FLOAT fClosestDist = 5.0, FLOAT fIdealDist = 10.0, FLOAT fMaxDist = 50.0, FLOAT fLosingTriggerDist = 100.0,
FLOAT fMaxDistInFront = 30.0, FLOAT fDefaultPlaybackSpeed = 1.0, FLOAT fMinSpeedIfBehind = 0.7, FLOAT fMinSpeedIfLosingTrigger = 0.5,
FLOAT fMaxSpeedIfTooClose = 2.0, BOOL bApplySlowdownToPlayer = FALSE, FLOAT fDefaultSlowdownPercent = 0.0, FLOAT fMaxSlowdownPercent = 15.0,
BOOL bAccountForSpecialAbility = TRUE)
VECTOR vPlayerPos = GET_ENTITY_COORDS(vehPlayer)
VECTOR vTriggerPos = GET_ENTITY_COORDS(vehTrigger)
VECTOR vOffset = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(vehTrigger, vPlayerPos)
FLOAT fDist = VDIST(vPlayerPos, vTriggerPos)
FLOAT fDistRatio = 0.0
FLOAT fMaxSpeedToAddIfClose = fMaxSpeedIfTooClose - fDefaultPlaybackSpeed
FLOAT fMaxSpeedToRemoveIfBehind = fDefaultPlaybackSpeed - fMinSpeedIfBehind
IF vOffset.y < 1.0 //Player is behind the car.
IF fDist > fMaxDist //Player is a long way behind, slow the trigger car down even more (if not on screen).
BOOL bReallyFarBehind = FALSE
IF fDist > fLosingTriggerDist
IF fDist > fLosingTriggerDist * 2.0
bReallyFarBehind = TRUE
ENDIF
fDist = fLosingTriggerDist
ENDIF
fDistRatio = ((fDist - fMaxDist) / (fLosingTriggerDist - fMaxDist))
IF NOT IS_ENTITY_ON_SCREEN(vehTrigger) OR bReallyFarBehind
fDesiredPlaybackSpeed = fMinSpeedIfBehind - ((fMinSpeedIfBehind - fMinSpeedIfLosingTrigger) * fDistRatio)
ELSE
//Not safe to slow down any further, so cap at min speed.
fDesiredPlaybackSpeed = fMinSpeedIfBehind
ENDIF
ELIF fDist > fIdealDist //Player is slightly behind ideal distance. Slow the trigger car down relative to how far behind the player is.
fDistRatio = ((fDist - fIdealDist) / (fMaxDist - fIdealDist))
fDesiredPlaybackSpeed = fDefaultPlaybackSpeed - (fMaxSpeedToRemoveIfBehind * fDistRatio)
ELSE //Player is getting too close, speed up the trigger car relative to how close the player is.
IF fDist < fClosestDist
fDist = fClosestDist
ENDIF
fDistRatio = (fIdealDist - fDist) / (fIdealDist - fClosestDist)
IF IS_SPECIAL_ABILITY_ACTIVE(PLAYER_ID())
AND bAccountForSpecialAbility
fDesiredPlaybackSpeed = fDefaultPlaybackSpeed + ((fDistRatio * fMaxSpeedToAddIfClose) * 2.0)
ELSE
fDesiredPlaybackSpeed = fDefaultPlaybackSpeed + (fDistRatio * fMaxSpeedToAddIfClose)
ENDIF
ENDIF
ELSE //Player is in front, speed up trigger car based on the player's own speed.
IF fDist > fMaxDistInFront
fDist = fMaxDistInFront
ENDIF
fDistRatio = fDist / fMaxDistInFront
FLOAT fSpeedDiff = GET_ENTITY_SPEED(vehTrigger) - GET_ENTITY_SPEED(vehPlayer)
//If the player is already going slower then don't speed up the buddy as much.
IF fSpeedDiff > 0.0
fDistRatio = fDistRatio * 0.5
ENDIF
IF IS_SPECIAL_ABILITY_ACTIVE(PLAYER_ID())
AND bAccountForSpecialAbility
fDesiredPlaybackSpeed = (fDefaultPlaybackSpeed * 2.0) + fDistRatio
ELSE
IF GET_ENTITY_SPEED(vehPlayer) < 5.0
AND fSpeedDiff > 0.0
//If the player has slowed down slow the buddy down so it's not as harsh if they plough through.
fDesiredPlaybackSpeed = (fDefaultPlaybackSpeed - 0.4) + fDistRatio
ELSE
fDesiredPlaybackSpeed = fDefaultPlaybackSpeed + fDistRatio
ENDIF
ENDIF
ENDIF
//Modify the player's speed if the desired playback speed is getting too much.
IF bApplySlowdownToPlayer
FLOAT fPlayersSpeedModifier = fDefaultSlowdownPercent
IF IS_SPECIAL_ABILITY_ACTIVE(PLAYER_ID())
AND bAccountForSpecialAbility
fMaxSlowdownPercent = fMaxSlowdownPercent * 2.0
fDefaultSlowdownPercent = fDefaultSlowdownPercent * 2.0
ENDIF
IF fDesiredPlaybackSpeed > 1.0
fPlayersSpeedModifier = fDefaultSlowdownPercent + ((fMaxSlowdownPercent - fDefaultSlowdownPercent) * (fDesiredPlaybackSpeed - 1.0))
ENDIF
MODIFY_VEHICLE_TOP_SPEED(vehPlayer, -fPlayersSpeedModifier)
ENDIF
#IF IS_DEBUG_BUILD
IF bTrafficDebugOn
SET_TEXT_SCALE(0.5, 0.5)
TEXT_LABEL_63 strDist = "Distance: "
strDist += GET_STRING_FROM_FLOAT(fDist)
DISPLAY_TEXT_WITH_LITERAL_STRING(0.1, 0.1, "STRING", strDist)
SET_TEXT_SCALE(0.5, 0.5)
TEXT_LABEL_63 strSpeed = "Desired playback speed: "
strSpeed += GET_STRING_FROM_FLOAT(fDesiredPlaybackSpeed)
DISPLAY_TEXT_WITH_LITERAL_STRING(0.1, 0.15, "STRING", strSpeed)
SET_TEXT_SCALE(0.5, 0.5)
TEXT_LABEL_63 strDiff = "Speed diff (m/s): "
strDiff += GET_STRING_FROM_FLOAT(GET_ENTITY_SPEED(vehTrigger) - GET_ENTITY_SPEED(vehPlayer))
DISPLAY_TEXT_WITH_LITERAL_STRING(0.1, 0.2, "STRING", strDiff)
SET_TEXT_SCALE(0.5, 0.5)
TEXT_LABEL_63 strState = "Trigger car state: "
IF vOffset.y < 0.0
strState += "in front and "
ELSE
strState += "behind and "
ENDIF
IF IS_ENTITY_ON_SCREEN(vehTrigger)
strState += "on screen."
ELSE
strState += "off screen."
ENDIF
DISPLAY_TEXT_WITH_LITERAL_STRING(0.1, 0.25, "STRING", strState)
ENDIF
#ENDIF
ENDPROC
/// PURPOSE:
/// Used in conjunction with CALCULATE_DESIRED_PLAYBACK_SPEED_FROM_TRIGGER_CAR, this will give you a new playback speed that's smoothed based on the current playback speed and
/// the calculated speed. This is separated from the main calculations to allow for special cases for desired speed in missions.
/// PARAMS:
/// fCurrentSpeed - The current playback speed.
/// fDesiredSpeed - The speed the trigger car should be at based on any distance calculations.
/// fAccel - Modify this to increase/decrease the rate that the current speed changes to achieve the desired speed. Changing this can help if you see the trigger car noticeably speed off during a chase.
PROC UPDATE_CURRENT_PLAYBACK_SPEED_WITH_SMOOTHING(FLOAT &fCurrentSpeed, FLOAT fDesiredSpeed, FLOAT fAccel = 0.01)
fCurrentSpeed = fCurrentSpeed +@ (((fDesiredSpeed - fCurrentSpeed) * fAccel) * 30.0)
#IF IS_DEBUG_BUILD
IF bTrafficDebugOn
SET_TEXT_SCALE(0.5, 0.5)
TEXT_LABEL_63 strCurrentSpeed = "Current Speed: "
strCurrentSpeed += GET_STRING_FROM_FLOAT(fCurrentSpeed)
DISPLAY_TEXT_WITH_LITERAL_STRING(0.1, 0.3, "STRING", strCurrentSpeed)
ENDIF
#ENDIF
ENDPROC
/// PURPOSE:
/// Function is now obsolete, please use CALCULATE_DESIRED_PLAYBACK_SPEED_FROM_TRIGGER_CAR.
PROC CALCULATE_NEW_PLAYBACK_SPEED_FROM_CHAR(VEHICLE_INDEX InCarID, PED_INDEX TargetCharID, FLOAT &fPlaybackSpeed, FLOAT fDefaultPlaybackSpeed = 1.0, FLOAT fMinDist = 5.0, FLOAT fIdealDist = 20.0, FLOAT fSlowDownDist = 125.0, FLOAT fMaxPlaybackSpeedMultiplier = 2.0, FLOAT fAirResistanceMultiplier = 1.0, FLOAT fCatchupSpeedMultiplier = 0.7, BOOL bDoAirResistance = TRUE)
FLOAT fMaxPlaybackSpeed
FLOAT fTemp
FLOAT fCurrentDistance
FLOAT fCorrectedDistance
FLOAT fDesiredPlaybackSpeed
FLOAT fCatchupSpeed
FLOAT fCaughtUpDist
FLOAT fMultiplyingFactor
FLOAT fMaxAllowedAccelThisFrame
IF (bCalculatePlaybackSpeedInitialised = FALSE)
IF (fPlaybackSpeed < fDefaultPlaybackSpeed)
fPlaybackSpeed = fDefaultPlaybackSpeed
bCalculatePlaybackSpeedInitialised = TRUE
ENDIF
ENDIF
#IF IS_DEBUG_BUILD
IF (fMinDist < 0.0)
PRINTSTRING("CALCULATE_NEW_PLAYBACK_SPEED_FROM_CHAR - fMinDist = ")
PRINTFLOAT(fMinDist)
PRINTSTRING("\n")
SCRIPT_ASSERT("CALCULATE_NEW_PLAYBACK_SPEED_FROM_CHAR - fMinDist cannot be less than zero.")
ENDIF
IF (fMinDist >= fIdealDist)
PRINTSTRING("CALCULATE_NEW_PLAYBACK_SPEED_FROM_CHAR - fMinDist = ")
PRINTFLOAT(fMinDist)
PRINTSTRING(", fIdealDist = ")
PRINTFLOAT(fIdealDist)
PRINTSTRING("\n")
SCRIPT_ASSERT("CALCULATE_NEW_PLAYBACK_SPEED_FROM_CHAR - fMinDist must be less than fIdealDist")
ENDIF
IF (fMinDist >= fSlowDownDist)
PRINTSTRING("CALCULATE_NEW_PLAYBACK_SPEED_FROM_CHAR - fMinDist = ")
PRINTFLOAT(fMinDist)
PRINTSTRING(", fSlowDownDist = ")
PRINTFLOAT(fSlowDownDist)
PRINTSTRING("\n")
SCRIPT_ASSERT("CALCULATE_NEW_PLAYBACK_SPEED_FROM_CHAR - fMinDist must be less than fSlowDownDist")
ENDIF
IF (fIdealDist < 0.0)
PRINTSTRING("CALCULATE_NEW_PLAYBACK_SPEED_FROM_CHAR - fIdealDist = ")
PRINTFLOAT(fIdealDist)
PRINTSTRING("\n")
SCRIPT_ASSERT("CALCULATE_NEW_PLAYBACK_SPEED_FROM_CHAR - fIdealDist cannot be less than zero.")
ENDIF
IF (fIdealDist >= fSlowDownDist)
PRINTSTRING("CALCULATE_NEW_PLAYBACK_SPEED_FROM_CHAR - fIdealDist = ")
PRINTFLOAT(fIdealDist)
PRINTSTRING(", fSlowDownDist = ")
PRINTFLOAT(fSlowDownDist)
PRINTSTRING("\n")
SCRIPT_ASSERT("CALCULATE_NEW_PLAYBACK_SPEED_FROM_CHAR - fIdealDist must be less than fSlowDownDist")
ENDIF
IF (fSlowDownDist < 0.0)
PRINTSTRING("CALCULATE_NEW_PLAYBACK_SPEED_FROM_CHAR - fSlowDownDist = ")
PRINTFLOAT(fSlowDownDist)
PRINTSTRING("\n")
SCRIPT_ASSERT("CALCULATE_NEW_PLAYBACK_SPEED_FROM_CHAR - fSlowDownDist cannot be less than zero.")
ENDIF
#ENDIF
IF (fAirResistanceMultiplier < 0.0)
fAirResistanceMultiplier = fAirResMultiplier
ENDIF
fMaxPlaybackSpeed = fDefaultPlaybackSpeed * fMaxPlaybackSpeedMultiplier
IF NOT (fMaxPlaybackSpeed > fDefaultPlaybackSpeed)
fMaxPlaybackSpeed = fDefaultPlaybackSpeed + 0.1
ENDIF
fCatchupSpeed = fDefaultPlaybackSpeed * fCatchupSpeedMultiplier
fCaughtUpDist = ((fSlowDownDist - fIdealDist) * CAUGHT_UP_DIST_PERCENT) + fIdealDist
fCurrentDistance = GET_CHAR_DISTANCE_FROM_LEAD_CAR(InCarID, TargetCharID)
IF (fCurrentDistance < 0.0)
fCurrentDistance *= -1.0
ENDIF
// Limit current distance
fCorrectedDistance = fCurrentDistance
IF (fCorrectedDistance < fMinDist)
fCorrectedDistance = fMinDist
ENDIF
IF (fCorrectedDistance > fCaughtUpDist)
fCorrectedDistance = fCaughtUpDist
ENDIF
// figure out the deisried playback speed
fDesiredPlaybackSpeed = fDefaultPlaybackSpeed
IF NOT IS_ENTITY_DEAD(TargetCharID)
IF IS_PED_IN_FRONT_OF_CAR(TargetCharID, InCarID)
IF IS_PED_IN_ANY_VEHICLE(TargetCharID)
// in car , infront of chase car - max speed
fDesiredPlaybackSpeed = fMaxPlaybackSpeed
ELSE
// on foot, infront of chase car - max speed unless within 50m
IF (fCurrentDistance < 50.0)
fDesiredPlaybackSpeed = fDefaultPlaybackSpeed
ELSE
fDesiredPlaybackSpeed = fMaxPlaybackSpeed
ENDIF
ENDIF
ELSE
// in car , behind - adjust the playback speed accordingly
IF (fCurrentDistance < fIdealDist)
IF (GET_ACTUAL_CHAR_DISTANCE_FROM_LEAD_CAR(InCarID, TargetCharID) < fIdealDist)
fTemp = GET_DIFF_IN_SPEED_HEADINGS_BETWEEN_CHAR_AND_LEAD_CAR(InCarID, TargetCharID)
// 15 and under degrees = 1.0
// 90 degrees = 0.0
fTemp += -15.0
IF (fTemp < 0.0)
fTemp = 0.0
ENDIF
IF (fTemp > 75.0)
fTemp = 75.0
ENDIF
fMultiplyingFactor = (75.0 - fTemp) / 75.0
ELSE
fMultiplyingFactor = 1.0
ENDIF
// speed up
fDesiredPlaybackSpeed = (((((fIdealDist - fMinDist) - (fCorrectedDistance - fMinDist)) / (fIdealDist - fMinDist)) * (fMaxPlaybackSpeed - fDefaultPlaybackSpeed)) * fMultiplyingFactor) + fDefaultPlaybackSpeed
ELSE
// slow down if hit catchup distance
IF (fCurrentDistance > fSlowDownDist)
fDesiredPlaybackSpeed = fCatchupSpeed
bIsCatchingUp = TRUE
ELSE
// player is catching up
IF (bIsCatchingUp)
// player has caught up
IF (fCurrentDistance < fCaughtUpDist)
fDesiredPlaybackSpeed = fDefaultPlaybackSpeed
bIsCatchingUp = FALSE
ELSE
fDesiredPlaybackSpeed = fCatchupSpeed
ENDIF
ELSE
// keep the speed at the default
fDesiredPlaybackSpeed = fDefaultPlaybackSpeed
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
// accelerate towards the actual playback speed
fTemp = (fDesiredPlaybackSpeed - fPlaybackSpeed)
IF (fTemp > 0.0)
// check rate of acceleration
fTemp = GET_FRAME_TIME()
fMaxAllowedAccelThisFrame = (fPlaybackSpeedMaxAcceleration * fDefaultPlaybackSpeed) * fTemp
fTemp = (fDesiredPlaybackSpeed - fPlaybackSpeed)
IF (fTemp > fMaxAllowedAccelThisFrame)
fTemp = fMaxAllowedAccelThisFrame
ENDIF
// PRINTSTRING("PLAYBACK SPEED INCREASED BY ")
// PRINTFLOAT(fTemp)
// PRINTSTRING(", fMaxAllowedAccelThisFrame = ")
// PRINTFLOAT(fMaxAllowedAccelThisFrame)
// PRINTSTRING("\n")
fPlaybackSpeed += fTemp
ELSE
// check rate of deceleration
fTemp = GET_FRAME_TIME()
fMaxAllowedAccelThisFrame = (fPlaybackSpeedMaxDecceleration * fDefaultPlaybackSpeed) * fTemp
fTemp = (fDesiredPlaybackSpeed - fPlaybackSpeed)
IF (fTemp < (fMaxAllowedAccelThisFrame * -1.0))
fTemp = (fMaxAllowedAccelThisFrame * -1.0)
ENDIF
// PRINTSTRING("PLAYBACK SPEED DECREASED BY ")
// PRINTFLOAT(fTemp)
// PRINTSTRING(", fMaxAllowedAccelThisFrame = ")
// PRINTFLOAT(fMaxAllowedAccelThisFrame)
// PRINTSTRING("\n")
fPlaybackSpeed += fTemp
ENDIF
// set air resistance for chasing car
VEHICLE_INDEX TempCar
MODEL_NAMES TempModelName
IF (bDoAirResistance)
IF NOT IS_PED_INJURED(TargetCharID)
IF IS_PED_IN_ANY_VEHICLE(TargetCharID)
TempCar = GET_VEHICLE_PED_IS_IN(TargetCharID)
IF NOT IS_ENTITY_DEAD(TempCar)
TempModelName = GET_ENTITY_MODEL(TempCar)
IF IS_THIS_MODEL_A_CAR(TempModelName)
OR IS_THIS_MODEL_A_BIKE(TempModelName)
IF IS_VEHICLE_DRIVEABLE(TempCar)
fTemp = fDesiredPlaybackSpeed
IF (fTemp < fDefaultPlaybackSpeed)
fTemp = fDefaultPlaybackSpeed
ENDIF
fTemp -= fDefaultPlaybackSpeed
fTemp /= (fMaxPlaybackSpeed - fDefaultPlaybackSpeed)
fTemp *= fAirResistanceMultiplier
fTemp *= (fMaxAirRes - fMinAirRes)
fTemp += fMinAirRes
fAirRes = fTemp
IF (fAirRes < fMinAirRes)
fAirRes = fMinAirRes
ENDIF
IF (fAirRes > fMaxAirRes)
fAirRes = fMaxAirRes
ENDIF
SET_AIR_DRAG_MULTIPLIER_FOR_PLAYERS_VEHICLE(PLAYER_ID(), fAirRes)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Function is now obsolete, please use CALCULATE_DESIRED_PLAYBACK_SPEED_FROM_TRIGGER_CAR.
PROC CALCULATE_PLAYBACK_SPEED_FROM_CHAR(VEHICLE_INDEX InCarID, PED_INDEX TargetCharID, FLOAT &fPlaybackSpeed, FLOAT fIdealChaseDist = 20.0, FLOAT fMinChaseDist = 5.0, FLOAT fMaxChaseDist = 40.0, FLOAT fMinPlaybackSpeed = 0.6, FLOAT fMaxPlaybackSpeed = 2.0, FLOAT fDefaultPlaybackSpeed = 1.0,
BOOL bUseAirResistance = TRUE)
FLOAT fMaxPlaybackSpeedMult
FLOAT fCatchupSpeedMult
FLOAT fSlowDist
// check min dist is < than ideal
IF NOT (fMinChaseDist < fIdealChaseDist)
fMinChaseDist = fIdealChaseDist - 0.1
ENDIF
// figure out fDefaultPlaybackSpeed
IF (fMinPlaybackSpeed > fDefaultPlaybackSpeed)
fDefaultPlaybackSpeed = fMinPlaybackSpeed
ENDIF
// figure out fMaxPlaybackSpeedMultiplier
fMaxPlaybackSpeedMult = (fMaxPlaybackSpeed / fDefaultPlaybackSpeed)
// figure out fCatchupSpeedMultiplier
fCatchupSpeedMult = (fMinPlaybackSpeed / fDefaultPlaybackSpeed)
// figure out fSlowDownDist
fSlowDist = ((fMaxChaseDist - fIdealChaseDist) * (1.0 / CAUGHT_UP_DIST_PERCENT)) + fIdealChaseDist
CALCULATE_NEW_PLAYBACK_SPEED_FROM_CHAR(InCarID, TargetCharID, fPlaybackSpeed, fDefaultPlaybackSpeed, fMinChaseDist, fIdealChaseDist, fSlowDist, fMaxPlaybackSpeedMult, 1.0, fCatchupSpeedMult, bUseAirResistance)
ENDPROC
#IF IS_DEBUG_BUILD
STRUCT FACE_STRUCT
// face must be clockwise
VECTOR v1
VECTOR v2
VECTOR v3
VECTOR v4
ENDSTRUCT
FUNC VECTOR GET_FACE_NORMAL(FACE_STRUCT inFace)
VECTOR vReturn
VECTOR v1, v2
v1 = inFace.v2 - inFace.v1
v2 = inFace.v3 - inFace.v2
vReturn = CROSS_PRODUCT(v1, v2)
vReturn *= -1.0
RETURN(vReturn)
ENDFUNC
FUNC VECTOR GET_FACE_MIDPOINT(FACE_STRUCT inFace)
VECTOR vReturn
vReturn = inFace.v1 + inFace.v2 + inFace.v3 + inFace.v4
vReturn *= 0.25
RETURN(vReturn)
ENDFUNC
PROC DRAW_FACE(FACE_STRUCT inFace)
DRAW_DEBUG_LINE(inFace.v1, inFace.v2)
DRAW_DEBUG_LINE(inFace.v2, inFace.v3)
DRAW_DEBUG_LINE(inFace.v3, inFace.v4)
DRAW_DEBUG_LINE(inFace.v4, inFace.v1)
ENDPROC
FUNC BOOL IS_POINT_BEHIND_FACE(VECTOR vInPoint, FACE_STRUCT inFace)
VECTOR vMidpoint
VECTOR vNormal
VECTOR vVecFromPointToMidpoint
vMidpoint = GET_FACE_MIDPOINT(inFace)
vNormal = GET_FACE_NORMAL(inFace)
vVecFromPointToMidpoint = vMidpoint - vInPoint
IF (DOT_PRODUCT(vVecFromPointToMidpoint,vNormal) > 0.0)
RETURN(TRUE)
ENDIF
RETURN(FALSE)
ENDFUNC
FUNC BOOL IS_POINT_INSIDE_RECORDING_CONE(VECTOR vInPoint, VEHICLE_INDEX TriggerCar)
VECTOR posA
VECTOR posB
VECTOR posC
VECTOR posD
VECTOR posE
VECTOR posF
VECTOR posG
VECTOR posH
FLOAT fAngleOffsetDist
FLOAT fHeightAngleOffsetDist
FACE_STRUCT face[6]
// A,B,C,D - quad near car
IF IS_VEHICLE_DRIVEABLE(TriggerCar)
posA = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(TriggerCar, <<(fRecordingMinWidth * -0.5), fMinRecordingOffset, (fRecordingMinHeight * 0.5)>>)
posB = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(TriggerCar, <<(fRecordingMinWidth * 0.5), fMinRecordingOffset, (fRecordingMinHeight * 0.5)>>)
posC = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(TriggerCar, <<(fRecordingMinWidth * -0.5), fMinRecordingOffset, (fRecordingMinHeight * -0.5)>>)
posD = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(TriggerCar, <<(fRecordingMinWidth * 0.5), fMinRecordingOffset, (fRecordingMinHeight * -0.5)>>)
ENDIF
// E,F,G,H - quad away from car
IF IS_VEHICLE_DRIVEABLE(TriggerCar)
fAngleOffsetDist = (fRecordingDistance * TAN(0.5 * fRecordingAngle))
fHeightAngleOffsetDist = (fRecordingDistance * TAN(0.5 * fRecordingHeightAngle))
posE = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(TriggerCar, <<(fRecordingMinWidth * -0.5) - fAngleOffsetDist, fMinRecordingOffset + fRecordingDistance, (fRecordingMinHeight * 0.5) + fHeightAngleOffsetDist>>)
posF = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(TriggerCar, <<(fRecordingMinWidth * 0.5) + fAngleOffsetDist, fMinRecordingOffset + fRecordingDistance, (fRecordingMinHeight * 0.5) + fHeightAngleOffsetDist>>)
posG = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(TriggerCar, <<(fRecordingMinWidth * -0.5) - fAngleOffsetDist, fMinRecordingOffset + fRecordingDistance, (fRecordingMinHeight * -0.5) - fHeightAngleOffsetDist>>)
posH = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(TriggerCar, <<(fRecordingMinWidth * 0.5) + fAngleOffsetDist, fMinRecordingOffset + fRecordingDistance, (fRecordingMinHeight * -0.5) - fHeightAngleOffsetDist>>)
ENDIF
// setup faces
face[0].v1 = posA
face[0].v2 = posB
face[0].v3 = posD
face[0].v4 = posC
face[1].v1 = posA
face[1].v2 = posE
face[1].v3 = posF
face[1].v4 = posB
face[2].v1 = posB
face[2].v2 = posF
face[2].v3 = posH
face[2].v4 = posD
face[3].v1 = posD
face[3].v2 = posH
face[3].v3 = posG
face[3].v4 = posC
face[4].v1 = posC
face[4].v2 = posG
face[4].v3 = posE
face[4].v4 = posA
face[5].v1 = posF
face[5].v2 = posE
face[5].v3 = posG
face[5].v4 = posH
IF IS_POINT_BEHIND_FACE(vInPoint, face[0])
IF IS_POINT_BEHIND_FACE(vInPoint, face[1])
IF IS_POINT_BEHIND_FACE(vInPoint, face[2])
IF IS_POINT_BEHIND_FACE(vInPoint, face[3])
IF IS_POINT_BEHIND_FACE(vInPoint, face[4])
IF IS_POINT_BEHIND_FACE(vInPoint, face[5])
RETURN(TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
RETURN(FALSE)
ENDFUNC
PROC DRAW_RECORDING_CONE(VEHICLE_INDEX TriggerCar)
VECTOR posA
VECTOR posB
VECTOR posC
VECTOR posD
VECTOR posE
VECTOR posF
VECTOR posG
VECTOR posH
FLOAT fAngleOffsetDist
FLOAT fHeightAngleOffsetDist
FACE_STRUCT face[6]
// A,B,C,D - quad near car
IF IS_VEHICLE_DRIVEABLE(TriggerCar)
posA = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(TriggerCar, <<(fRecordingMinWidth * -0.5), fMinRecordingOffset, (fRecordingMinHeight * 0.5)>>)
posB = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(TriggerCar, <<(fRecordingMinWidth * 0.5), fMinRecordingOffset, (fRecordingMinHeight * 0.5)>>)
posC = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(TriggerCar, <<(fRecordingMinWidth * -0.5), fMinRecordingOffset, (fRecordingMinHeight * -0.5)>>)
posD = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(TriggerCar, <<(fRecordingMinWidth * 0.5), fMinRecordingOffset, (fRecordingMinHeight * -0.5)>>)
ENDIF
// E,F,G,H - quad away from car
IF IS_VEHICLE_DRIVEABLE(TriggerCar)
fAngleOffsetDist = (fRecordingDistance * TAN(0.5 * fRecordingAngle))
fHeightAngleOffsetDist = (fRecordingDistance * TAN(0.5 * fRecordingHeightAngle))
posE = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(TriggerCar, <<(fRecordingMinWidth * -0.5) - fAngleOffsetDist, fMinRecordingOffset + fRecordingDistance, (fRecordingMinHeight * 0.5) + fHeightAngleOffsetDist>>)
posF = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(TriggerCar, <<(fRecordingMinWidth * 0.5) + fAngleOffsetDist, fMinRecordingOffset + fRecordingDistance, (fRecordingMinHeight * 0.5) + fHeightAngleOffsetDist>>)
posG = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(TriggerCar, <<(fRecordingMinWidth * -0.5) - fAngleOffsetDist, fMinRecordingOffset + fRecordingDistance, (fRecordingMinHeight * -0.5) - fHeightAngleOffsetDist>>)
posH = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(TriggerCar, <<(fRecordingMinWidth * 0.5) + fAngleOffsetDist, fMinRecordingOffset + fRecordingDistance, (fRecordingMinHeight * -0.5) - fHeightAngleOffsetDist>>)
ENDIF
// setup faces
face[0].v1 = posA
face[0].v2 = posB
face[0].v3 = posD
face[0].v4 = posC
face[1].v1 = posA
face[1].v2 = posE
face[1].v3 = posF
face[1].v4 = posB
face[2].v1 = posB
face[2].v2 = posF
face[2].v3 = posH
face[2].v4 = posD
face[3].v1 = posD
face[3].v2 = posH
face[3].v3 = posG
face[3].v4 = posC
face[4].v1 = posC
face[4].v2 = posG
face[4].v3 = posE
face[4].v4 = posA
face[5].v1 = posF
face[5].v2 = posE
face[5].v3 = posG
face[5].v4 = posH
DRAW_FACE(face[0])
DRAW_FACE(face[1])
DRAW_FACE(face[2])
DRAW_FACE(face[3])
DRAW_FACE(face[4])
DRAW_FACE(face[5])
ENDPROC
#ENDIF
#IF IS_DEBUG_BUILD
FUNC BOOL HAS_TRAFFIC_CAR_BEEN_RECORDED(VEHICLE_INDEX &InCar)
INT i
//REPEAT TOTAL_NUMBER_OF_TRAFFIC_CARS i // remove as once a car has been recorded it gets deleted
REPEAT MAX_NUMBER_OF_TRAFFIC_CARS_PLAYING_BACK i
IF (RecordedTrafficCarID[i] = InCar)
RETURN(TRUE)
ENDIF
ENDREPEAT
// check its not a set peice car
REPEAT TOTAL_NUMBER_OF_SET_PIECE_CARS i
IF (SetPieceCarID[i] = InCar)
RETURN(TRUE)
ENDIF
ENDREPEAT
RETURN(FALSE)
ENDFUNC
FUNC BOOL HAS_PARKED_CAR_BEEN_RECORDED(VEHICLE_INDEX &InCar)
INT i
REPEAT MAX_NUMBER_OF_PARKED_CARS_PLAYING_BACK i
IF (RecordedParkedCarID[i] = InCar)
RETURN(TRUE)
ENDIF
ENDREPEAT
RETURN(FALSE)
ENDFUNC
#ENDIF
#IF IS_DEBUG_BUILD
FUNC BOOL IS_TRAFFIC_CAR_GOOD_TO_RECORD(VEHICLE_INDEX InCar, VEHICLE_INDEX TriggerCar)
PED_INDEX temp_char
VECTOR pos
IF IS_VEHICLE_DRIVEABLE(InCar)
IF NOT (InCar = TriggerCar)
IF NOT IS_ENTITY_A_MISSION_ENTITY(InCar)
IF NOT IS_RECORDING_GOING_ON_FOR_VEHICLE(InCar)
IF NOT IS_VEHICLE_MODEL(InCar, COP_CAR_MODEL())
IF NOT HAS_TRAFFIC_CAR_BEEN_RECORDED(InCar)
IF IS_CAR_IN_FRONT_OF_CAR(InCar, TriggerCar)
pos = GET_ENTITY_COORDS(InCar)
IF IS_POINT_INSIDE_RECORDING_CONE(pos, TriggerCar)
temp_char = GET_PED_IN_VEHICLE_SEAT(InCar)
IF NOT IS_ENTITY_DEAD(temp_char)
RETURN(TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
RETURN(FALSE)
ENDFUNC
#ENDIF
#IF IS_DEBUG_BUILD
FUNC BOOL IS_THIS_A_PARKED_CAR(VEHICLE_INDEX InCar)
PED_INDEX temp_char
IF IS_VEHICLE_DRIVEABLE(InCar)
temp_char = GET_PED_IN_VEHICLE_SEAT(InCar)
IF NOT DOES_ENTITY_EXIST(temp_char)
RETURN(TRUE)
ENDIF
ENDIF
RETURN(FALSE)
ENDFUNC
#ENDIF
#IF IS_DEBUG_BUILD
FUNC BOOL IS_PARKED_CAR_GOOD_TO_RECORD(VEHICLE_INDEX InCar, VEHICLE_INDEX TriggerCar)
VECTOR pos
IF IS_VEHICLE_DRIVEABLE(InCar)
IF NOT (InCar = TriggerCar)
IF NOT IS_ENTITY_A_MISSION_ENTITY(InCar)
IF NOT IS_RECORDING_GOING_ON_FOR_VEHICLE(InCar)
IF IS_THIS_A_PARKED_CAR(InCar)
IF NOT HAS_PARKED_CAR_BEEN_RECORDED(InCar)
pos = GET_ENTITY_COORDS(InCar)
IF IS_POINT_INSIDE_RECORDING_CONE(pos, TriggerCar)
IF IS_CAR_IN_FRONT_OF_CAR(InCar, TriggerCar)
RETURN(TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
RETURN(FALSE)
ENDFUNC
#ENDIF
#IF IS_DEBUG_BUILD
/// PURPOSE:
/// Grabs a random traffic vehicle that's currently in front of the player, and checks if it's inside the recording cone.
FUNC VEHICLE_INDEX FIND_TRAFFIC_CAR_TO_RECORD(VEHICLE_INDEX vehPlayer)
IF IS_VEHICLE_DRIVEABLE(vehPlayer)
VECTOR vSphereCentre = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(vehPlayer, <<0.0, fRecordingDistance * 0.5, 0.0>>)
VEHICLE_INDEX vehResult = GET_RANDOM_VEHICLE_IN_SPHERE(vSphereCentre, fRecordingDistance * 0.5, DUMMY_MODEL_FOR_SCRIPT, VEHICLE_SEARCH_FLAG_RETURN_RANDOM_VEHICLES)
IF IS_TRAFFIC_CAR_GOOD_TO_RECORD(vehResult, vehPlayer)
RETURN vehResult
ENDIF
ENDIF
RETURN NULL
ENDFUNC
/// PURPOSE:
/// Grabs a random parked vehicle that's currently in front of the player, and checks if it's inside the recording cone.
FUNC VEHICLE_INDEX FIND_PARKED_CAR_TO_RECORD(VEHICLE_INDEX vehPlayer)
IF IS_VEHICLE_DRIVEABLE(vehPlayer)
VECTOR vSphereCentre = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(vehPlayer, <<0.0, fRecordingDistance * 0.5, 0.0>>)
VEHICLE_INDEX vehResult = GET_RANDOM_VEHICLE_IN_SPHERE(vSphereCentre, fRecordingDistance * 0.5, DUMMY_MODEL_FOR_SCRIPT, VEHICLE_SEARCH_FLAG_RETURN_RANDOM_VEHICLES)
IF IS_PARKED_CAR_GOOD_TO_RECORD(vehResult, vehPlayer)
RETURN vehResult
ENDIF
ENDIF
RETURN NULL
ENDFUNC
#ENDIF
#IF IS_DEBUG_BUILD
PROC START_RECORDING_SET_PIECE_CAR(VEHICLE_INDEX inCar, VEHICLE_INDEX TriggerCar, BOOL bAllowOverwrite)
TEXT_LABEL_63 str
// start new recording
IF IS_VEHICLE_DRIVEABLE(inCar)
IF NOT START_RECORDING_VEHICLE(inCar, iSetPieceCarRecordingFile, strUberName, bAllowOverwrite)
str = "Error with car recording "
str += iSetPieceCarRecordingFile
str += " ensure file is checked out."
SCRIPT_ASSERT(str)
ENDIF
SetPieceRecordingCar = inCar
OPEN_DEBUG_FILE()
// start position
RecordedSetPieceCarPos = GET_ENTITY_COORDS(inCar)
SAVE_NEWLINE_TO_DEBUG_FILE()
str = "SetPieceCar"
SAVE_STRING_TO_DEBUG_FILE(str)
str = "Pos[] = <<"
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(RecordedSetPieceCarPos.x)
SAVE_STRING_TO_DEBUG_FILE(", ")
SAVE_FLOAT_TO_DEBUG_FILE(RecordedSetPieceCarPos.y)
SAVE_STRING_TO_DEBUG_FILE(", ")
SAVE_FLOAT_TO_DEBUG_FILE(RecordedSetPieceCarPos.z)
SAVE_STRING_TO_DEBUG_FIle(">>")
// start quaternion
GET_ENTITY_QUATERNION(inCar, fSetPieceQuatX, fSetPieceQuatY, fSetPieceQuatZ, fSetPieceQuatW)
SAVE_NEWLINE_TO_DEBUG_FILE()
str = "SetPieceCar"
SAVE_STRING_TO_DEBUG_FILE(str)
str = "QuatX[] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(fSetPieceQuatX)
SAVE_NEWLINE_TO_DEBUG_FILE()
str = "SetPieceCar"
SAVE_STRING_TO_DEBUG_FILE(str)
str = "QuatY[] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(fSetPieceQuatY)
SAVE_NEWLINE_TO_DEBUG_FILE()
str = "SetPieceCar"
SAVE_STRING_TO_DEBUG_FILE(str)
str = "QuatZ[] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(fSetPieceQuatZ)
SAVE_NEWLINE_TO_DEBUG_FILE()
str = "SetPieceCar"
SAVE_STRING_TO_DEBUG_FILE(str)
str = "QuatW[] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(fSetPieceQuatW)
// recording number
SAVE_NEWLINE_TO_DEBUG_FILE()
str = "SetPieceCar"
SAVE_STRING_TO_DEBUG_FILE(str)
str = "Recording[] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_INT_TO_DEBUG_FILE(iSetPieceCarRecordingFile)
// recording start time
SAVE_NEWLINE_TO_DEBUG_FILE()
str = "SetPieceCar"
SAVE_STRING_TO_DEBUG_FILE(str)
str = "Startime[] = "
SAVE_STRING_TO_DEBUG_FILE(str)
IF IS_VEHICLE_DRIVEABLE(TriggerCar)
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(TriggerCar)
fNewSetPieceTriggerTime = GET_TIME_POSITION_IN_RECORDING(TriggerCar)
SAVE_FLOAT_TO_DEBUG_FILE(fNewSetPieceTriggerTime)
ELSE
IF IS_RECORDING_GOING_ON_FOR_VEHICLE(TriggerCar)
fNewSetPieceTriggerTime = GET_TIME_POSITION_IN_RECORDED_RECORDING(TriggerCar)
SAVE_FLOAT_TO_DEBUG_FILE(fNewSetPieceTriggerTime)
ENDIF
ENDIF
ENDIF
// recording speed
SAVE_NEWLINE_TO_DEBUG_FILE()
str = "SetPieceCar"
SAVE_STRING_TO_DEBUG_FILE(str)
str = "RecordingSpeed"
SAVE_STRING_TO_DEBUG_FILE(str)
str = "[] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(1.0 / fMasterPlaybackSpeed)
// model type
SAVE_NEWLINE_TO_DEBUG_FILE()
str = "SetPieceCar"
SAVE_STRING_TO_DEBUG_FILE(str)
str = "Model[] = "
SAVE_STRING_TO_DEBUG_FILE(str)
str = GET_MODEL_NAME_OF_VEHICLE_FOR_DEBUG_ONLY(inCar)
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_NEWLINE_TO_DEBUG_FILE()
CLOSE_DEBUG_FILE()
ENDIF
ENDPROC
#ENDIF
#IF IS_DEBUG_BUILD
PROC RECORD_TRAFFIC(VEHICLE_INDEX TriggerCar)
VEHICLE_INDEX vehNew
VEHICLE_INDEX car_to_delete
VECTOR pos, pos2, vec
FLOAT QuatX, QuatY, QuatZ, QuatW
FLOAT fTemp
TEXT_LABEL_63 str
INT i
INT iRecordingSlot
IF (bShowRecordingCone)
DRAW_RECORDING_CONE(TriggerCar)
ENDIF
// start new recordings
REPEAT 20 i
IF iCurrentNumberOfTrafficRecordings < MAX_NUMBER_OF_TRAFFIC_CARS_PLAYING_BACK
vehNew = FIND_TRAFFIC_CAR_TO_RECORD(TriggerCar)
// get free recoded traffic car slot
iRecordingSlot = GET_FREE_RECORDED_TRAFFIC_CAR_SLOT()
IF NOT (iRecordingSlot = -1)
IF IS_VEHICLE_DRIVEABLE(vehNew)
IF DOES_BLIP_EXIST(ActiveTrafficCarBlipID[iRecordingSlot])
REMOVE_BLIP(ActiveTrafficCarBlipID[iRecordingSlot])
ENDIF
ActiveTrafficCarBlipID[iRecordingSlot] = ADD_BLIP_FOR_ENTITY(vehNew)
RecordedTrafficCarID[iRecordingSlot] = vehNew
SET_ENTITY_AS_MISSION_ENTITY(vehNew)
IF NOT START_RECORDING_VEHICLE(vehNew, (iTotalNumberOfTrafficCarsRecorded + iInitialRecordingFileNumber), strUberName, TRUE)
str = "Error with car recording "
str += (iTotalNumberOfTrafficCarsRecorded + iInitialRecordingFileNumber)
str += " ensure file is checked out."
SCRIPT_ASSERT(str)
ENDIF
// start position
pos = GET_ENTITY_COORDS(vehNew)
SAVE_NEWLINE_TO_DEBUG_FILE()
str = "TrafficCarPos["
SAVE_STRING_TO_DEBUG_FILE(str)
str = iTotalNumberOfTrafficCarsRecorded
str += "] = <<"
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(pos.x)
SAVE_STRING_TO_DEBUG_FILE(", ")
SAVE_FLOAT_TO_DEBUG_FILE(pos.y)
SAVE_STRING_TO_DEBUG_FILE(", ")
SAVE_FLOAT_TO_DEBUG_FILE(pos.z)
SAVE_STRING_TO_DEBUG_FIle(">>")
// start quaternion
GET_ENTITY_QUATERNION(vehNew, QuatX, QuatY, QuatZ, QuatW)
SAVE_NEWLINE_TO_DEBUG_FILE()
str = "TrafficCarQuatX"
SAVE_STRING_TO_DEBUG_FILE(str)
str = "["
str += iTotalNumberOfTrafficCarsRecorded
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(QuatX)
SAVE_NEWLINE_TO_DEBUG_FILE()
str = "TrafficCarQuatY"
SAVE_STRING_TO_DEBUG_FILE(str)
str = "["
str += iTotalNumberOfTrafficCarsRecorded
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(QuatY)
SAVE_NEWLINE_TO_DEBUG_FILE()
str = "TrafficCarQuatZ"
SAVE_STRING_TO_DEBUG_FILE(str)
str = "["
str += iTotalNumberOfTrafficCarsRecorded
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(QuatZ)
SAVE_NEWLINE_TO_DEBUG_FILE()
str = "TrafficCarQuatW"
SAVE_STRING_TO_DEBUG_FILE(str)
str = "["
str += iTotalNumberOfTrafficCarsRecorded
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(QuatW)
// recording number
SAVE_NEWLINE_TO_DEBUG_FILE()
str = "TrafficCarRecor"
SAVE_STRING_TO_DEBUG_FILE(str)
str = "ding["
str += iTotalNumberOfTrafficCarsRecorded
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_INT_TO_DEBUG_FILE(iTotalNumberOfTrafficCarsRecorded + iInitialRecordingFileNumber)
// recording start time
SAVE_NEWLINE_TO_DEBUG_FILE()
str = "TrafficCarStart"
SAVE_STRING_TO_DEBUG_FILE(str)
str = "ime["
str += iTotalNumberOfTrafficCarsRecorded
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
IF IS_VEHICLE_DRIVEABLE(TriggerCar)
IF IS_RECORDING_GOING_ON_FOR_VEHICLE(TriggerCar)
fTemp = GET_TIME_POSITION_IN_RECORDED_RECORDING(TriggerCar)
SAVE_FLOAT_TO_DEBUG_FILE(fTemp)
ENDIF
ENDIF
// model type
SAVE_NEWLINE_TO_DEBUG_FILE()
str = "TrafficCarModel"
SAVE_STRING_TO_DEBUG_FILE(str)
str = "["
str += iTotalNumberOfTrafficCarsRecorded
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
str = GET_MODEL_NAME_OF_VEHICLE_FOR_DEBUG_ONLY(vehNew)
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_NEWLINE_TO_DEBUG_FILE()
iTotalNumberOfTrafficCarsRecorded++
ENDIF
ENDIF
ENDIF
ENDREPEAT
// end existing recordings
IF IS_VEHICLE_DRIVEABLE(TriggerCar)
REPEAT MAX_NUMBER_OF_TRAFFIC_CARS_PLAYING_BACK i
IF NOT IS_ENTITY_DEAD(RecordedTrafficCarID[i])
IF IS_RECORDING_GOING_ON_FOR_VEHICLE(RecordedTrafficCarID[i])
IF NOT IS_CAR_IN_FRONT_OF_CAR(RecordedTrafficCarID[i], TriggerCar)
pos = GET_ENTITY_COORDS(TriggerCar)
pos2 = GET_ENTITY_COORDS(RecordedTrafficCarID[i])
vec = pos2 - pos
vec.z = 0.0
IF (VMAG2(vec) > (fTrafficRecordingDistanceAroundCar * fTrafficRecordingDistanceAroundCar))
//IF NOT IS_VEHICLE_AT_COORD @_No_of_params (RecordedTrafficCarID[i], pos.x, pos.y, fTrafficRecordingDistanceAroundCar, fTrafficRecordingDistanceAroundCar, FALSE)
STOP_RECORDING_VEHICLE(RecordedTrafficCarID[i])
IF (bDeleteTrafficWhenRecorded)
#IF IS_DEBUG_BUILD
IF (bTrafficDebugOn)
PRINTLN("traffic.sch - DELETING TRAFFIC CAR - been recorded and now behind fTrafficRecordingDistanceAroundCar distance away")
ENDIF
#ENDIF
IF DOES_BLIP_EXIST(ActiveTrafficCarBlipID[i])
REMOVE_BLIP(ActiveTrafficCarBlipID[i])
ENDIF
DELETE_VEHICLE(RecordedTrafficCarID[i])
RecordedTrafficCarID[i] = NULL
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDREPEAT
ENDIF
// remove any cars that arn't being recorded
IF (bDeleteRedundantTrafficCars)
REPEAT 10 i
pos = GET_ENTITY_COORDS(TriggerCar)
car_to_delete = GET_RANDOM_VEHICLE_IN_SPHERE(pos, 30.0 ,DUMMY_MODEL_FOR_SCRIPT, VEHICLE_SEARCH_FLAG_RETURN_RANDOM_VEHICLES)
IF IS_VEHICLE_DRIVEABLE(car_to_delete)
IF NOT IS_THIS_A_PARKED_CAR(car_to_delete)
IF NOT HAS_TRAFFIC_CAR_BEEN_RECORDED(car_to_delete)
IF NOT IS_RECORDING_GOING_ON_FOR_VEHICLE(car_to_delete)
#IF IS_DEBUG_BUILD
IF (bTrafficDebugOn)
PRINTLN("traffic.sch - DELETING TRAFFIC CAR - deemed redundant")
ENDIF
#ENDIF
DELETE_VEHICLE(car_to_delete)
ENDIF
ENDIF
ENDIF
ENDIF
ENDREPEAT
ENDIF
// delete ANY cop cars
REPEAT 10 i
pos = GET_ENTITY_COORDS(TriggerCar)
car_to_delete = GET_RANDOM_VEHICLE_IN_SPHERE(pos, fRecordingDistance, DUMMY_MODEL_FOR_SCRIPT, VEHICLE_SEARCH_FLAG_RETURN_LAW_ENFORCER_VEHICLES_ONLY)
IF IS_VEHICLE_DRIVEABLE(car_to_delete)
IF NOT IS_RECORDING_GOING_ON_FOR_VEHICLE(car_to_delete)
DELETE_VEHICLE(car_to_delete)
ENDIF
ENDIF
ENDREPEAT
// clear area around car, soon only cars that get recorded in the cone survive
pos = GET_ENTITY_COORDS(TriggerCar)
CLEAR_AREA_OF_VEHICLES(pos, (fRecordingDistance + fMinRecordingOffset) * fRecordingClearAreaPercentageOfCone) //, TRUE)
// count all the current cars being recorded / delete any old ones
iCurrentNumberOfTrafficRecordings = 0
REPEAT MAX_NUMBER_OF_TRAFFIC_CARS_PLAYING_BACK i
IF DOES_ENTITY_EXIST(RecordedTrafficCarID[i])
IF NOT IS_ENTITY_DEAD(RecordedTrafficCarID[i])
IF IS_RECORDING_GOING_ON_FOR_VEHICLE(RecordedTrafficCarID[i])
iCurrentNumberOfTrafficRecordings++
ELSE
#IF IS_DEBUG_BUILD
IF (bTrafficDebugOn)
PRINTLN("traffic.sch - DELETING TRAFFIC CAR - recorded and finished")
ENDIF
#ENDIF
IF DOES_BLIP_EXIST(ActiveTrafficCarBlipID[i])
REMOVE_BLIP(ActiveTrafficCarBlipID[i])
ENDIF
DELETE_VEHICLE(RecordedTrafficCarID[i])
RecordedTrafficCarID[i] = NULL
ENDIF
ELSE
#IF IS_DEBUG_BUILD
IF (bTrafficDebugOn)
PRINTLN("traffic.sch - DELETING TRAFFIC CAR - car is dead")
ENDIF
#ENDIF
IF DOES_BLIP_EXIST(ActiveTrafficCarBlipID[i])
REMOVE_BLIP(ActiveTrafficCarBlipID[i])
ENDIF
DELETE_VEHICLE(RecordedTrafficCarID[i])
RecordedTrafficCarID[i] = NULL
ENDIF
ENDIF
ENDREPEAT
ENDPROC
#ENDIF
#IF IS_DEBUG_BUILD
FUNC BOOL IS_SET_PIECE_CAR_VALID(INT i)
IF NOT (bSetPieceCarsConverted[i])
IF (SetPieceCarRecording[i] > 0)
IF NOT (SetPieceCarModel[i] = DUMMY_MODEL_FOR_SCRIPT)
RETURN(TRUE)
ENDIF
ENDIF
ENDIF
RETURN(FALSE)
ENDFUNC
FUNC BOOL IS_TRAFFIC_CAR_VALID(INT i)
IF (TrafficCarRecording[i] > 0)
IF NOT (TrafficCarModel[i] = DUMMY_MODEL_FOR_SCRIPT)
RETURN(TRUE)
ENDIF
ENDIF
RETURN(FALSE)
ENDFUNC
FUNC BOOL IS_PARKED_CAR_VALID(INT i)
IF NOT (ParkedCarModel[i] = DUMMY_MODEL_FOR_SCRIPT)
RETURN(TRUE)
ENDIF
RETURN(FALSE)
ENDFUNC
/// PURPOSE:
/// Sorts the traffic array in order of start time.
PROC SORT_TRAFFIC_ARRAY()
INT i = 0
INT j = TOTAL_NUMBER_OF_TRAFFIC_CARS - 1
WHILE i < TOTAL_NUMBER_OF_TRAFFIC_CARS
j = TOTAL_NUMBER_OF_TRAFFIC_CARS - 1
WHILE j > i
IF TrafficCarStartime[j-1] > TrafficCarStartime[j]
OR NOT IS_TRAFFIC_CAR_VALID(j-1)
VEHICLE_INDEX tempID = TrafficCarID[j-1]
MODEL_NAMES tempModel = TrafficCarModel[j-1]
VECTOR tempPos = TrafficCarPos[j-1]
INT tempProgress = TrafficCarProgress[j-1]
FLOAT tempQuatW = TrafficCarQuatW[j-1]
FLOAT tempQuatX = TrafficCarQuatX[j-1]
FLOAT tempQuatY = TrafficCarQuatY[j-1]
FLOAT tempQuatZ = TrafficCarQuatZ[j-1]
INT tempRecording = TrafficCarRecording[j-1]
FLOAT tempStartTime = TrafficCarStartime[j-1]
TrafficCarID[j-1] = TrafficCarID[j]
TrafficCarModel[j-1] = TrafficCarModel[j]
TrafficCarPos[j-1] = TrafficCarPos[j]
TrafficCarProgress[j-1] = TrafficCarProgress[j]
TrafficCarQuatW[j-1] = TrafficCarQuatW[j]
TrafficCarQuatX[j-1] = TrafficCarQuatX[j]
TrafficCarQuatY[j-1] = TrafficCarQuatY[j]
TrafficCarQuatZ[j-1] = TrafficCarQuatZ[j]
TrafficCarRecording[j-1] = TrafficCarRecording[j]
TrafficCarStartime[j-1] = TrafficCarStartime[j]
TrafficCarID[j] = tempID
TrafficCarModel[j] = tempModel
TrafficCarPos[j] = tempPos
TrafficCarProgress[j] = tempProgress
TrafficCarQuatW[j] = tempQuatW
TrafficCarQuatX[j] = tempQuatX
TrafficCarQuatY[j] = tempQuatY
TrafficCarQuatZ[j] = tempQuatZ
TrafficCarRecording[j] = tempRecording
TrafficCarStartime[j] = tempStartTime
ENDIF
j--
ENDWHILE
i++
IF (i % 5) = 0
WAIT(0) //This is required due to the number of operations needed to sort the array, the downside is this proc can take a few seconds to finish if the array is large.
ENDIF
ENDWHILE
ENDPROC
FUNC INT LOWEST_SET_PIECE_CAR_TO_CONVERT()
INT i
FLOAT fCurrentLowestTime
INT iCurrentLowestNumber
fCurrentLowestTime = 9999999.9
iCurrentLowestNumber = -1
REPEAT TOTAL_NUMBER_OF_SET_PIECE_CARS i
IF (bSetPieceCarsToConvert[i])
IF (SetPieceCarStartime[i] < fCurrentLowestTime)
IF IS_SET_PIECE_CAR_VALID(i)
fCurrentLowestTime = SetPieceCarStartime[i]
iCurrentLowestNumber = i
ENDIF
ENDIF
ENDIF
ENDREPEAT
RETURN(iCurrentLowestNumber)
ENDFUNC
PROC OUTPUT_PARKED_CAR_DATA(VEHICLE_INDEX veh)
#IF IS_DEBUG_BUILD
IF NOT IS_ENTITY_DEAD(veh)
VECTOR v_pos = GET_ENTITY_COORDS(veh)
FLOAT fQuatX, fQuatY, fQuatZ, fQuatW
GET_ENTITY_QUATERNION(veh, fQuatX, fQuatY, fQuatZ, fQuatW)
OPEN_DEBUG_FILE()
SAVE_NEWLINE_TO_DEBUG_FILE()
SAVE_STRING_TO_DEBUG_FILE("ParkedCarPos[] = <<")
SAVE_FLOAT_TO_DEBUG_FILE(v_pos.x)
SAVE_STRING_TO_DEBUG_FILE(", ")
SAVE_FLOAT_TO_DEBUG_FILE(v_pos.y)
SAVE_STRING_TO_DEBUG_FILE(", ")
SAVE_FLOAT_TO_DEBUG_FILE(v_pos.z)
SAVE_STRING_TO_DEBUG_FIle(">>")
SAVE_NEWLINE_TO_DEBUG_FILE()
SAVE_STRING_TO_DEBUG_FILE("ParkedCarQuatX[] = ")
SAVE_FLOAT_TO_DEBUG_FILE(fQuatX)
SAVE_NEWLINE_TO_DEBUG_FILE()
SAVE_STRING_TO_DEBUG_FILE("ParkedCarQuatY[] = ")
SAVE_FLOAT_TO_DEBUG_FILE(fQuatY)
SAVE_NEWLINE_TO_DEBUG_FILE()
SAVE_STRING_TO_DEBUG_FILE("ParkedCarQuatZ[] = ")
SAVE_FLOAT_TO_DEBUG_FILE(fQuatZ)
SAVE_NEWLINE_TO_DEBUG_FILE()
SAVE_STRING_TO_DEBUG_FILE("ParkedCarQuatW[] = ")
SAVE_FLOAT_TO_DEBUG_FILE(fQuatW)
SAVE_NEWLINE_TO_DEBUG_FILE()
SAVE_STRING_TO_DEBUG_FILE("ParkedCarModel[] = ")
SAVE_STRING_TO_DEBUG_FILE(GET_MODEL_NAME_FOR_DEBUG(GET_ENTITY_MODEL(veh)))
SAVE_NEWLINE_TO_DEBUG_FILE()
CLOSE_DEBUG_FILE()
ENDIF
#ENDIF
ENDPROC
PROC OUTPUT_CLEANED_DATA()
INT iTotalNoOfOutputTraffic
INT iTotalNoOfOutputParkedCars
INT iTotalNoOfOutputSetPieceCars
INT i
INT iLowestCarToConvert
TEXT_LABEL str
BOOL bSetPieceCarConverted
iTotalNoOfOutputTraffic = 0
iTotalNoOfOutputParkedCars = 0
iTotalNoOfOutputSetPieceCars = 0
#IF IS_DEBUG_BUILD
PRINTLN("traffic.sch - Sorting traffic array, may take a few seconds...")
#ENDIF
SORT_TRAFFIC_ARRAY()
#IF IS_DEBUG_BUILD
PRINTLN("traffic.sch - Saving data to temp_debug...")
#ENDIF
OPEN_DEBUG_FILE()
// output traffic
//str = "\n\n// **** UBER RECORDED TRAFFIC **** \n\n"
SAVE_STRING_TO_DEBUG_FILE("\n\n// **** UBER RECORDED TRAFFIC **** \n\n")
REPEAT TOTAL_NUMBER_OF_TRAFFIC_CARS i
iLowestCarToConvert = LOWEST_SET_PIECE_CAR_TO_CONVERT()
bSetPieceCarConverted = FALSE
// should we insert the set piece car here?
IF NOT (iLowestCarToConvert = -1)
IF (SetPieceCarStartime[iLowestCarToConvert] < TrafficCarStartime[i])
SAVE_STRING_TO_DEBUG_FILE("TrafficCarPos[")
str = iTotalNoOfOutputTraffic
str += "] = <<"
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(SetPieceCarPos[iLowestCarToConvert].x)
SAVE_STRING_TO_DEBUG_FILE(", ")
SAVE_FLOAT_TO_DEBUG_FILE(SetPieceCarPos[iLowestCarToConvert].y)
SAVE_STRING_TO_DEBUG_FILE(", ")
SAVE_FLOAT_TO_DEBUG_FILE(SetPieceCarPos[iLowestCarToConvert].z)
SAVE_STRING_TO_DEBUG_FIle(">>\n")
SAVE_STRING_TO_DEBUG_FILE("TrafficCarQuatX[")
str = iTotalNoOfOutputTraffic
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(SetPieceCarQuatX[iLowestCarToConvert])
SAVE_STRING_TO_DEBUG_FILE("\n")
SAVE_STRING_TO_DEBUG_FILE("TrafficCarQuatY[")
str = iTotalNoOfOutputTraffic
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(SetPieceCarQuatY[iLowestCarToConvert])
SAVE_STRING_TO_DEBUG_FILE("\n")
SAVE_STRING_TO_DEBUG_FILE("TrafficCarQuatZ[")
str = iTotalNoOfOutputTraffic
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(SetPieceCarQuatZ[iLowestCarToConvert])
SAVE_STRING_TO_DEBUG_FILE("\n")
SAVE_STRING_TO_DEBUG_FILE("TrafficCarQuatW[")
str = iTotalNoOfOutputTraffic
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(SetPieceCarQuatW[iLowestCarToConvert])
SAVE_STRING_TO_DEBUG_FILE("\n")
SAVE_STRING_TO_DEBUG_FILE("TrafficCarRecording[")
str = iTotalNoOfOutputTraffic
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_INT_TO_DEBUG_FILE(SetPieceCarRecording[iLowestCarToConvert])
SAVE_STRING_TO_DEBUG_FILE("\n")
SAVE_STRING_TO_DEBUG_FILE("TrafficCarStartime[")
str = iTotalNoOfOutputTraffic
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(SetPieceCarStartime[iLowestCarToConvert])
SAVE_STRING_TO_DEBUG_FILE("\n")
SAVE_STRING_TO_DEBUG_FILE("TrafficCarModel")
str = "["
str += iTotalNoOfOutputTraffic
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
str = GET_MODEL_NAME_FOR_DEBUG(SetPieceCarModel[iLowestCarToConvert])
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_STRING_TO_DEBUG_FILE("\n")
SAVE_STRING_TO_DEBUG_FILE("\n")
bSetPieceCarsConverted[iLowestCarToConvert] = TRUE
iTotalNoOfOutputTraffic++
bSetPieceCarConverted = TRUE
ENDIF
ENDIF
// normal traffic cars
IF NOT (bSetPieceCarConverted)
IF IS_TRAFFIC_CAR_VALID(i)
SAVE_STRING_TO_DEBUG_FILE("TrafficCarPos[")
str = iTotalNoOfOutputTraffic
str += "] = <<"
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(TrafficCarPos[i].x)
SAVE_STRING_TO_DEBUG_FILE(", ")
SAVE_FLOAT_TO_DEBUG_FILE(TrafficCarPos[i].y)
SAVE_STRING_TO_DEBUG_FILE(", ")
SAVE_FLOAT_TO_DEBUG_FILE(TrafficCarPos[i].z)
SAVE_STRING_TO_DEBUG_FIle(">>\n")
SAVE_STRING_TO_DEBUG_FILE("TrafficCarQuatX[")
str = iTotalNoOfOutputTraffic
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(TrafficCarQuatX[i])
SAVE_STRING_TO_DEBUG_FILE("\n")
SAVE_STRING_TO_DEBUG_FILE("TrafficCarQuatY[")
str = iTotalNoOfOutputTraffic
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(TrafficCarQuatY[i])
SAVE_STRING_TO_DEBUG_FILE("\n")
SAVE_STRING_TO_DEBUG_FILE("TrafficCarQuatZ[")
str = iTotalNoOfOutputTraffic
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(TrafficCarQuatZ[i])
SAVE_STRING_TO_DEBUG_FILE("\n")
SAVE_STRING_TO_DEBUG_FILE("TrafficCarQuatW[")
str = iTotalNoOfOutputTraffic
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(TrafficCarQuatW[i])
SAVE_STRING_TO_DEBUG_FILE("\n")
SAVE_STRING_TO_DEBUG_FILE("TrafficCarRecording[")
str = iTotalNoOfOutputTraffic
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_INT_TO_DEBUG_FILE(TrafficCarRecording[i])
SAVE_STRING_TO_DEBUG_FILE("\n")
SAVE_STRING_TO_DEBUG_FILE("TrafficCarStartime[")
str = iTotalNoOfOutputTraffic
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(TrafficCarStartime[i])
SAVE_STRING_TO_DEBUG_FILE("\n")
SAVE_STRING_TO_DEBUG_FILE("TrafficCarModel")
str = "["
str += iTotalNoOfOutputTraffic
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
str = GET_MODEL_NAME_FOR_DEBUG(TrafficCarModel[i])
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_STRING_TO_DEBUG_FILE("\n")
SAVE_STRING_TO_DEBUG_FILE("\n")
iTotalNoOfOutputTraffic++
ENDIF
ELSE
i--
ENDIF
ENDREPEAT
SAVE_STRING_TO_DEBUG_FILE("\n\n// **** UBER RECORDED PARKED CARS **** \n\n")
REPEAT TOTAL_NUMBER_OF_PARKED_CARS i
IF IS_PARKED_CAR_VALID(i)
SAVE_STRING_TO_DEBUG_FILE("ParkedCarPos[")
str = iTotalNoOfOutputParkedCars
str += "] = <<"
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(ParkedCarPos[i].x)
SAVE_STRING_TO_DEBUG_FILE(", ")
SAVE_FLOAT_TO_DEBUG_FILE(ParkedCarPos[i].y)
SAVE_STRING_TO_DEBUG_FILE(", ")
SAVE_FLOAT_TO_DEBUG_FILE(ParkedCarPos[i].z)
SAVE_STRING_TO_DEBUG_FIle(">>\n")
SAVE_STRING_TO_DEBUG_FILE("ParkedCarQuatX[")
str = iTotalNoOfOutputParkedCars
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(ParkedCarQuatX[i])
SAVE_STRING_TO_DEBUG_FILE("\n")
SAVE_STRING_TO_DEBUG_FILE("ParkedCarQuatY[")
str = iTotalNoOfOutputParkedCars
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(ParkedCarQuatY[i])
SAVE_STRING_TO_DEBUG_FILE("\n")
SAVE_STRING_TO_DEBUG_FILE("ParkedCarQuatZ[")
str = iTotalNoOfOutputParkedCars
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(ParkedCarQuatZ[i])
SAVE_STRING_TO_DEBUG_FILE("\n")
SAVE_STRING_TO_DEBUG_FILE("ParkedCarQuatW[")
str = iTotalNoOfOutputParkedCars
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(ParkedCarQuatW[i])
SAVE_STRING_TO_DEBUG_FILE("\n")
SAVE_STRING_TO_DEBUG_FILE("ParkedCarModel")
str = "["
str += iTotalNoOfOutputParkedCars
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
str = GET_MODEL_NAME_FOR_DEBUG(ParkedCarModel[i])
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_STRING_TO_DEBUG_FILE("\n")
SAVE_STRING_TO_DEBUG_FILE("\n")
iTotalNoOfOutputParkedCars++
ENDIF
ENDREPEAT
SAVE_STRING_TO_DEBUG_FILE("\n\n// **** UBER RECORDED SET PIECE CARS **** \n\n")
REPEAT TOTAL_NUMBER_OF_SET_PIECE_CARS i
IF IS_SET_PIECE_CAR_VALID(i)
SAVE_STRING_TO_DEBUG_FILE("SetPieceCarPos[")
str = iTotalNoOfOutputSetPieceCars
str += "] = <<"
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(SetPieceCarPos[i].x)
SAVE_STRING_TO_DEBUG_FILE(", ")
SAVE_FLOAT_TO_DEBUG_FILE(SetPieceCarPos[i].y)
SAVE_STRING_TO_DEBUG_FILE(", ")
SAVE_FLOAT_TO_DEBUG_FILE(SetPieceCarPos[i].z)
SAVE_STRING_TO_DEBUG_FIle(">>\n")
SAVE_STRING_TO_DEBUG_FILE("SetPieceCarQuatX[")
str = iTotalNoOfOutputSetPieceCars
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(SetPieceCarQuatX[i])
SAVE_STRING_TO_DEBUG_FILE("\n")
SAVE_STRING_TO_DEBUG_FILE("SetPieceCarQuatY[")
str = iTotalNoOfOutputSetPieceCars
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(SetPieceCarQuatY[i])
SAVE_STRING_TO_DEBUG_FILE("\n")
SAVE_STRING_TO_DEBUG_FILE("SetPieceCarQuatZ[")
str = iTotalNoOfOutputSetPieceCars
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(SetPieceCarQuatZ[i])
SAVE_STRING_TO_DEBUG_FILE("\n")
SAVE_STRING_TO_DEBUG_FILE("SetPieceCarQuatW[")
str = iTotalNoOfOutputSetPieceCars
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(SetPieceCarQuatW[i])
SAVE_STRING_TO_DEBUG_FILE("\n")
SAVE_STRING_TO_DEBUG_FILE("SetPieceCarRecording[")
str = iTotalNoOfOutputSetPieceCars
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_INT_TO_DEBUG_FILE(SetPieceCarRecording[i])
SAVE_STRING_TO_DEBUG_FILE("\n")
SAVE_STRING_TO_DEBUG_FILE("SetPieceCarStartime[")
str = iTotalNoOfOutputSetPieceCars
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(SetPieceCarStartime[i])
SAVE_STRING_TO_DEBUG_FILE("\n")
SAVE_STRING_TO_DEBUG_FILE("SetPieceCarRecordingSpeed[")
str = iTotalNoOfOutputSetPieceCars
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(SetPieceCarRecordingSpeed[i])
SAVE_STRING_TO_DEBUG_FILE("\n")
SAVE_STRING_TO_DEBUG_FILE("SetPieceCarModel")
str = "["
str += iTotalNoOfOutputSetPieceCars
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
str = GET_MODEL_NAME_FOR_DEBUG(SetPieceCarModel[i])
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_STRING_TO_DEBUG_FILE("\n")
SAVE_STRING_TO_DEBUG_FILE("\n")
iTotalNoOfOutputSetPieceCars++
ENDIF
ENDREPEAT
SAVE_STRING_TO_DEBUG_FILE("\n\n// **** POSSIBLE REDUNDANT CAR RECORDINGS **** \n")
SAVE_STRING_TO_DEBUG_FILE("//\n")
SAVE_STRING_TO_DEBUG_FILE("// The following car recordings MIGHT be redundant. \n")
SAVE_STRING_TO_DEBUG_FILE("// They were associated with traffic and set piece cars \n")
SAVE_STRING_TO_DEBUG_FILE("// which are now invalid. Please check carefully if they \n")
SAVE_STRING_TO_DEBUG_FILE("// are being used somewhere else. If not, remove them from \n")
SAVE_STRING_TO_DEBUG_FILE("// alienbrian and the car recording image. \n")
SAVE_STRING_TO_DEBUG_FILE("//\n")
// traffic
REPEAT TOTAL_NUMBER_OF_TRAFFIC_CARS i
IF NOT IS_TRAFFIC_CAR_VALID(i)
IF NOT (TrafficCarRecording[i] = 0)
SAVE_STRING_TO_DEBUG_FILE("// ")
SAVE_INT_TO_DEBUG_FILE(TrafficCarRecording[i])
SAVE_STRING_TO_DEBUG_FILE("\n")
ENDIF
ENDIF
ENDREPEAT
// set piece
REPEAT TOTAL_NUMBER_OF_SET_PIECE_CARS i
IF NOT IS_SET_PIECE_CAR_VALID(i)
IF NOT (SetPieceCarRecording[i] = 0)
SAVE_STRING_TO_DEBUG_FILE("// ")
SAVE_INT_TO_DEBUG_FILE(SetPieceCarRecording[i])
SAVE_STRING_TO_DEBUG_FILE("\n")
ENDIF
ENDIF
ENDREPEAT
SAVE_STRING_TO_DEBUG_FILE("//\n")
SAVE_STRING_TO_DEBUG_FILE("\n // **** end of uber output **** \n")
CLOSE_DEBUG_FILE()
ENDPROC
#ENDIF
PROC MAKE_CAR_DRIVE_RANDOMLY(VEHICLE_INDEX inCar)
FLOAT fTemp
PED_INDEX temp_char
IF IS_VEHICLE_DRIVEABLE(inCar)
temp_char = GET_PED_IN_VEHICLE_SEAT(inCar)
IF NOT IS_PED_INJURED(temp_char)
IF NOT (temp_char = PLAYER_PED_ID())
fTemp = GET_ENTITY_SPEED(inCar)
IF (fTemp < MIN_CAR_CRUISE_SPEED)
fTemp = MIN_CAR_CRUISE_SPEED
ENDIF
IF (fTemp > MAX_CAR_CRUISE_SPEED)
fTemp = MAX_CAR_CRUISE_SPEED
ENDIF
TASK_VEHICLE_MISSION(temp_char, inCar, NULL, MISSION_CRUISE, fTemp, DRIVINGMODE_STOPFORCARS, 5, 5)
SET_PED_FLEE_ATTRIBUTES(temp_char, FA_DISABLE_ACCELERATE_IN_VEHICLE, TRUE)
// B*1490105 - Used to stop released uber veh drivers interferring with chase by reacting to player shooting
IF bSetReleasedDriversToExitOnFlee
SET_PED_FLEE_ATTRIBUTES(temp_char, FA_FORCE_EXIT_VEHICLE, TRUE)
SET_PED_FLEE_ATTRIBUTES(temp_char, FA_USE_VEHICLE, FALSE)
ENDIF
SET_PED_COMBAT_ATTRIBUTES(temp_char, CA_FLEE_WHILST_IN_VEHICLE, FALSE)
ENDIF
ENDIF
ENDIF
ENDPROC
PROC CHANGE_PLAYBACK_TO_USE_AI_AND_KEEP_SPEED(VEHICLE_INDEX inCar)
IF IS_VEHICLE_DRIVEABLE(inCar)
MAKE_CAR_DRIVE_RANDOMLY(inCar)
SET_PLAYBACK_TO_USE_AI(inCar)
ENDIF
ENDPROC
#IF IS_DEBUG_BUILD
PROC RECORD_PARKED_CARS(VEHICLE_INDEX TriggerCar)
VEHICLE_INDEX vehNew
VEHICLE_INDEX car_to_delete
VECTOR pos, pos2, vec
FLOAT QuatX, QuatY, QuatZ, QuatW
TEXT_LABEL str
INT iParkedCarSlot
INT i
// start new recordings
//IF iTotalNumberOfParkedCarsRecorded < TOTAL_NUMBER_OF_PARKED_CARS
REPEAT 10 i
IF (iCurrentNumberOfParkedCars < MAX_NUMBER_OF_PARKED_CARS_PLAYING_BACK)
vehNew = FIND_PARKED_CAR_TO_RECORD(TriggerCar)
IF IS_VEHICLE_DRIVEABLE(vehNew)
iParkedCarSlot = GET_FREE_RECORDED_PARKED_CAR_SLOT()
IF NOT (iParkedCarSlot = -1)
IF DOES_BLIP_EXIST(ActiveParkedCarBlipID[iParkedCarSlot])
REMOVE_BLIP(ActiveParkedCarBlipID[iParkedCarSlot])
ENDIF
SET_ENTITY_AS_MISSION_ENTITY(vehNew)
ActiveParkedCarBlipID[iParkedCarSlot] = ADD_BLIP_FOR_ENTITY(vehNew)
SET_BLIP_SCALE(ActiveParkedCarBlipID[iParkedCarSlot], 0.5)
RecordedParkedCarID[iParkedCarSlot] = vehNew
// start position
pos = GET_ENTITY_COORDS(vehNew)
SAVE_NEWLINE_TO_DEBUG_FILE()
str = "ParkedCarPos["
SAVE_STRING_TO_DEBUG_FILE(str)
str = iTotalNumberOfParkedCarsRecorded
str += "] = <<"
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(pos.x)
SAVE_STRING_TO_DEBUG_FILE(", ")
SAVE_FLOAT_TO_DEBUG_FILE(pos.y)
SAVE_STRING_TO_DEBUG_FILE(", ")
SAVE_FLOAT_TO_DEBUG_FILE(pos.z)
SAVE_STRING_TO_DEBUG_FIle(">>")
// start quaternion
GET_ENTITY_QUATERNION(vehNew, QuatX, QuatY, QuatZ, QuatW)
SAVE_NEWLINE_TO_DEBUG_FILE()
str = "ParkedCarQuatX"
SAVE_STRING_TO_DEBUG_FILE(str)
str = "["
str += iTotalNumberOfParkedCarsRecorded
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(QuatX)
SAVE_NEWLINE_TO_DEBUG_FILE()
str = "ParkedCarQuatY"
SAVE_STRING_TO_DEBUG_FILE(str)
str = "["
str += iTotalNumberOfParkedCarsRecorded
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(QuatY)
SAVE_NEWLINE_TO_DEBUG_FILE()
str = "ParkedCarQuatZ"
SAVE_STRING_TO_DEBUG_FILE(str)
str = "["
str += iTotalNumberOfParkedCarsRecorded
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(QuatZ)
SAVE_NEWLINE_TO_DEBUG_FILE()
str = "ParkedCarQuatW"
SAVE_STRING_TO_DEBUG_FILE(str)
str = "["
str += iTotalNumberOfParkedCarsRecorded
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_FLOAT_TO_DEBUG_FILE(QuatW)
// model type
SAVE_NEWLINE_TO_DEBUG_FILE()
str = "ParkedCarModel"
SAVE_STRING_TO_DEBUG_FILE(str)
str = "["
str += iTotalNumberOfParkedCarsRecorded
str += "] = "
SAVE_STRING_TO_DEBUG_FILE(str)
str = GET_MODEL_NAME_OF_VEHICLE_FOR_DEBUG_ONLY(vehNew)
SAVE_STRING_TO_DEBUG_FILE(str)
SAVE_NEWLINE_TO_DEBUG_FILE()
iTotalNumberOfParkedCarsRecorded++
ENDIF
ENDIF
ENDIF
ENDREPEAT
// remove parked cars that have been recorded
IF IS_VEHICLE_DRIVEABLE(TriggerCar)
REPEAT MAX_NUMBER_OF_PARKED_CARS_PLAYING_BACK i
IF DOES_ENTITY_EXIST(RecordedParkedCarID[i])
IF IS_VEHICLE_DRIVEABLE(RecordedParkedCarID[i])
IF NOT IS_RECORDING_GOING_ON_FOR_VEHICLE(RecordedParkedCarID[i])
IF NOT IS_CAR_IN_FRONT_OF_CAR(RecordedParkedCarID[i], TriggerCar)
pos = GET_ENTITY_COORDS(TriggerCar)
pos2 = GET_ENTITY_COORDS(RecordedParkedCarID[i])
vec = pos2 - pos
vec.z = 0.0
IF (VMAG2(vec) > (fTrafficRecordingDistanceAroundCar * fTrafficRecordingDistanceAroundCar))
//IF NOT IS_VEHICLE_AT_COORD @_No_of_params (RecordedParkedCarID[i], pos.x, pos.y, fTrafficRecordingDistanceAroundCar, fTrafficRecordingDistanceAroundCar, FALSE)
IF (bDeleteTrafficWhenRecorded)
IF DOES_BLIP_EXIST(ActiveParkedCarBlipID[i])
REMOVE_BLIP(ActiveParkedCarBlipID[i])
ENDIF
DELETE_VEHICLE(RecordedParkedCarID[i])
ENDIF
ENDIF
ENDIF
ENDIF
ELSE
IF DOES_BLIP_EXIST(ActiveParkedCarBlipID[i])
REMOVE_BLIP(ActiveParkedCarBlipID[i])
ENDIF
DELETE_VEHICLE(RecordedParkedCarID[i])
ENDIF
ENDIF
ENDREPEAT
ENDIF
// remove any cars that arn't being recorded
IF (bDeleteRedundantParkedCars)
REPEAT 20 i
pos = GET_ENTITY_COORDS(TriggerCar)
car_to_delete = GET_RANDOM_VEHICLE_IN_SPHERE(pos, 30.0 ,DUMMY_MODEL_FOR_SCRIPT, VEHICLE_SEARCH_FLAG_RETURN_RANDOM_VEHICLES)
IF DOES_ENTITY_EXIST(car_to_delete)
IF NOT IS_RECORDING_GOING_ON_FOR_VEHICLE(car_to_delete)
IF IS_THIS_A_PARKED_CAR(car_to_delete)
IF NOT HAS_PARKED_CAR_BEEN_RECORDED(car_to_delete)
DELETE_VEHICLE(car_to_delete)
ENDIF
ENDIF
ENDIF
ENDIF
ENDREPEAT
ENDIF
// count current number of parked cars
iCurrentNumberOfParkedCars = 0
REPEAT MAX_NUMBER_OF_PARKED_CARS_PLAYING_BACK i
IF DOES_ENTITY_EXIST(RecordedParkedCarID[i])
iCurrentNumberOfParkedCars++
ENDIF
ENDREPEAT
ENDPROC
#ENDIF
#IF IS_DEBUG_BUILD
PROC RECORD_CAR(VEHICLE_INDEX InCar, INT iRecNo)
IF IS_VEHICLE_DRIVEABLE(InCar)
IF NOT IS_RECORDING_GOING_ON_FOR_VEHICLE(InCar)
OPEN_DEBUG_FILE()
vMainRecordingStartPosition = GET_ENTITY_COORDS(InCar)
GET_ENTITY_QUATERNION(InCar, fMainRecordingStartQuatX, fMainRecordingStartQuatY, fMainRecordingStartQuatZ, fMainRecordingStartQuatW)
PRINT_NOW("CRECSTART5", 5000, 1)
// PRINT_NOW("STARTED", 5000, 1)
IF NOT START_RECORDING_VEHICLE(InCar, iRecNo, strUberName, TRUE)
TEXT_LABEL_63 str
str = "Error with car recording "
str += iRecNo
str += " ensure file is checked out."
SCRIPT_ASSERT(str)
ENDIF
fRecordingTimer = 0.0
ELSE
FLOAT frame_time
frame_time = GET_FRAME_TIME()
fRecordingTimer += (frame_time * 1000.0)
//fRecordingTimer = GET_TIME_POSITION_IN_RECORDING(InCar)
ENDIF
ENDIF
ENDPROC
#ENDIF
#IF IS_DEBUG_BUILD
FUNC BOOL RECORD_PLAYERS_CAR_WITH_TRAFFIC()
IF IS_PLAYER_PLAYING(PLAYER_ID())
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
MainRecordingCar = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())
ELSE
RETURN(FALSE)
ENDIF
ENDIF
IF IS_VEHICLE_DRIVEABLE(MainRecordingCar)
RECORD_CAR(MainRecordingCar, iMainCarRecordingFile)
IF IS_RECORDING_GOING_ON_FOR_VEHICLE(MainRecordingCar)
IF (bIncludeParkedCars)
RECORD_PARKED_CARS(MainRecordingCar)
ENDIF
RECORD_TRAFFIC(MainRecordingCar)
RETURN(TRUE)
ELSE
ENDIF
ENDIF
RETURN(FALSE)
ENDFUNC
#ENDIF
#IF IS_DEBUG_BUILD
PROC STOP_RECORDING_PLAYERS_CAR_AND_TRAFFIC()
INT i
IF IS_VEHICLE_DRIVEABLE(MainRecordingCar)
IF IS_RECORDING_GOING_ON_FOR_VEHICLE(MainRecordingCar)
STOP_RECORDING_VEHICLE(MainRecordingCar)
//PRINT_NOW("STOPPED", 5000, 1)
PRINT_NOW("CRECSTOP5", 5000, 1)
CLOSE_DEBUG_FILE()
ENDIF
ENDIF
REPEAT MAX_NUMBER_OF_TRAFFIC_CARS_PLAYING_BACK i
IF IS_VEHICLE_DRIVEABLE(RecordedTrafficCarID[i])
IF IS_RECORDING_GOING_ON_FOR_VEHICLE(RecordedTrafficCarID[i])
STOP_RECORDING_VEHICLE(RecordedTrafficCarID[i])
ENDIF
IF DOES_BLIP_EXIST(ActiveTrafficCarBlipID[i])
REMOVE_BLIP(ActiveTrafficCarBlipID[i])
ENDIF
DELETE_VEHICLE(RecordedTrafficCarID[i])
ENDIF
ENDREPEAT
REPEAT MAX_NUMBER_OF_PARKED_CARS_PLAYING_BACK i
IF IS_VEHICLE_DRIVEABLE(RecordedParkedCarID[i])
IF IS_RECORDING_GOING_ON_FOR_VEHICLE(RecordedParkedCarID[i])
STOP_RECORDING_VEHICLE(RecordedParkedCarID[i])
ENDIF
IF DOES_BLIP_EXIST(ActiveParkedCarBlipID[i])
REMOVE_BLIP(ActiveParkedCarBlipID[i])
ENDIF
DELETE_VEHICLE(RecordedParkedCarID[i])
ENDIF
ENDREPEAT
// reset variables
iCurrentNumberOfTrafficRecordings = 0
iCurrentNumberOfParkedCars = 0
iTotalNumberOfParkedCarsRecorded = 0
iTotalNumberOfTrafficCarsRecorded = 0
ENDPROC
#ENDIF
#IF IS_DEBUG_BUILD
PROC UPDATE_TRAFFIC_RECORDING()
CREATE_TRAFFIC_WIDGET()
VECTOR pos
// clear surrounding area
IF (bClearArea)
IF IS_PLAYER_PLAYING(PLAYER_ID())
pos = GET_ENTITY_COORDS(PLAYER_PED_ID())
CLEAR_AREA(pos, 1000.0, TRUE)
ENDIF
bClearArea = FALSE
ENDIF
IF (bStopParkedCarsFromBeingSpawned)
SET_NUMBER_OF_PARKED_VEHICLES(0)
ELSE
SET_NUMBER_OF_PARKED_VEHICLES(-1)
ENDIF
// traffic density
SET_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME(fCarDensityMultiplier)
IF (bResetToStartPosition)
bStartRecordingPlayersCarWithTraffic = FALSE
ENDIF
IF (bStartRecordingPlayersCarWithTraffic)
IF NOT RECORD_PLAYERS_CAR_WITH_TRAFFIC()
bStartRecordingPlayersCarWithTraffic = FALSE
ENDIF
ELSE
STOP_RECORDING_PLAYERS_CAR_AND_TRAFFIC()
IF (bResetToStartPosition)
IF IS_PLAYER_PLAYING(PLAYER_ID())
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
MainRecordingCar = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())
IF IS_VEHICLE_DRIVEABLE(MainRecordingCar)
SET_ENTITY_HEALTH(MainRecordingCar, 1000)
SET_VEHICLE_FIXED(MainRecordingCar)
SET_ENTITY_COORDS(MainRecordingCar, vMainRecordingStartPosition)
SET_ENTITY_QUATERNION(MainRecordingCar, fMainRecordingStartQuatX, fMainRecordingStartQuatY, fMainRecordingStartQuatZ, fMainRecordingStartQuatW)
LOAD_SCENE(vMainRecordingStartPosition)
SET_ENTITY_COORDS(MainRecordingCar, vMainRecordingStartPosition)
SET_ENTITY_QUATERNION(MainRecordingCar, fMainRecordingStartQuatX, fMainRecordingStartQuatY, fMainRecordingStartQuatZ, fMainRecordingStartQuatW)
ENDIF
ENDIF
ENDIF
bResetToStartPosition = FALSE
ENDIF
ENDIF
ENDPROC
#ENDIF
PROC DELETE_ALL_TRAFFIC_CARS()
INT i
REPEAT TOTAL_NUMBER_OF_TRAFFIC_CARS i
IF DOES_ENTITY_EXIST(TrafficCarID[i])
IF IS_VEHICLE_DRIVEABLE(TrafficCarID[i])
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(TrafficCarID[i])
STOP_PLAYBACK_RECORDED_VEHICLE(TrafficCarID[i])
ENDIF
//Delete the driver
PED_INDEX ped_temp = GET_PED_IN_VEHICLE_SEAT(TrafficCarID[i])
IF DOES_ENTITY_EXIST(ped_temp)
AND ped_temp != PLAYER_PED_ID()
IF IS_ENTITY_A_MISSION_ENTITY(ped_temp)
DELETE_PED(ped_temp)
ENDIF
ENDIF
ENDIF
IF IS_ENTITY_A_MISSION_ENTITY(TrafficCarID[i])
DELETE_VEHICLE(TrafficCarID[i])
ENDIF
ENDIF
IF NOT bSetPieceRecordingsAreActive AND NOT bTrafficDontCleanupRecordingFiles
IF TrafficCarRecording[i] > 0
REMOVE_VEHICLE_RECORDING(TrafficCarRecording[i], strUberName)
ENDIF
ENDIF
TrafficCarProgress[i] = 0
ENDREPEAT
REPEAT TOTAL_NUMBER_OF_TRAFFIC_CARS i
IF NOT (TrafficCarModel[i] = DUMMY_MODEL_FOR_SCRIPT)
SET_MODEL_AS_NO_LONGER_NEEDED(TrafficCarModel[i])
ENDIF
ENDREPEAT
iFirstCarToProcess = 0
iCurrentNumberOfTrafficPlaybacks = 0
ENDPROC
PROC DELETE_ALL_PARKED_CARS()
INT i
REPEAT TOTAL_NUMBER_OF_PARKED_CARS i
IF DOES_ENTITY_EXIST(ParkedCarID[i])
IF IS_ENTITY_A_MISSION_ENTITY(ParkedCarID[i])
DELETE_VEHICLE(ParkedCarID[i])
ENDIF
ENDIF
ParkedCarProgress[i] = 0
ENDREPEAT
REPEAT TOTAL_NUMBER_OF_PARKED_CARS i
IF NOT (ParkedCarModel[i] = DUMMY_MODEL_FOR_SCRIPT)
SET_MODEL_AS_NO_LONGER_NEEDED(ParkedCarModel[i])
ENDIF
ENDREPEAT
iFirstParkedCarToProcess = 0
iCurrentNumberOfParkedCars = 0
ENDPROC
PROC DELETE_ALL_SET_PIECE_CARS()
INT i
REPEAT TOTAL_NUMBER_OF_SET_PIECE_CARS i
IF DOES_ENTITY_EXIST(SetPieceCarID[i])
IF IS_VEHICLE_DRIVEABLE(SetPieceCarID[i])
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(SetPieceCarID[i])
STOP_PLAYBACK_RECORDED_VEHICLE(SetPieceCarID[i])
ENDIF
//Delete the driver
PED_INDEX ped_temp = GET_PED_IN_VEHICLE_SEAT(SetPieceCarID[i])
IF DOES_ENTITY_EXIST(ped_temp)
AND ped_temp != PLAYER_PED_ID()
IF IS_ENTITY_A_MISSION_ENTITY(ped_temp)
DELETE_PED(ped_temp)
ENDIF
ENDIF
ENDIF
IF IS_ENTITY_A_MISSION_ENTITY(SetPieceCarID[i])
DELETE_VEHICLE(SetPieceCarID[i])
ENDIF
ENDIF
SetPieceCarProgress[i] = 0
IF NOT bSetPieceRecordingsAreActive AND NOT bTrafficDontCleanupRecordingFiles
IF SetPieceCarRecording[i] > 0
REMOVE_VEHICLE_RECORDING(SetPieceCarRecording[i], strUberName)
ENDIF
ENDIF
ENDREPEAT
REPEAT TOTAL_NUMBER_OF_SET_PIECE_CARS i
IF NOT (SetPieceCarModel[i] = DUMMY_MODEL_FOR_SCRIPT)
SET_MODEL_AS_NO_LONGER_NEEDED(SetPieceCarModel[i])
ENDIF
ENDREPEAT
ENDPROC
PROC DELETE_ALL_CARS_IN_UBER_PLAYBACK()
DELETE_ALL_TRAFFIC_CARS()
DELETE_ALL_PARKED_CARS()
DELETE_ALL_SET_PIECE_CARS()
ENDPROC
PROC MARK_ALL_TRAFFIC_CARS_AS_NO_LONGER_NEEDED()
INT i
REPEAT TOTAL_NUMBER_OF_TRAFFIC_CARS i
IF DOES_ENTITY_EXIST(TrafficCarID[i])
IF NOT IS_ENTITY_DEAD(TrafficCarID[i])
SET_ENTITY_COLLISION(TrafficCarID[i], TRUE)
ENDIF
IF IS_VEHICLE_DRIVEABLE(TrafficCarID[i])
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(TrafficCarID[i])
STOP_PLAYBACK_RECORDED_VEHICLE(TrafficCarID[i])
ENDIF
ENDIF
MAKE_CAR_DRIVE_RANDOMLY(TrafficCarID[i])
MARK_CAR_AS_NO_LONGER_NEEDED_KEEP_ID(TrafficCarID[i])
ENDIF
TrafficCarProgress[i] = 0
TrafficCarFlags[i] = 0
IF NOT bSetPieceRecordingsAreActive AND NOT bTrafficDontCleanupRecordingFiles
IF TrafficCarRecording[i] > 0
REMOVE_VEHICLE_RECORDING(TrafficCarRecording[i], strUberName)
ENDIF
ENDIF
ENDREPEAT
REPEAT TOTAL_NUMBER_OF_TRAFFIC_CARS i
IF NOT (TrafficCarModel[i] = DUMMY_MODEL_FOR_SCRIPT)
SET_MODEL_AS_NO_LONGER_NEEDED(TrafficCarModel[i])
ENDIF
ENDREPEAT
iFirstCarToProcess = 0
iCurrentNumberOfTrafficPlaybacks = 0
ENDPROC
PROC MARK_ALL_PARKED_CARS_AS_NO_LONGER_NEEDED()
INT i
REPEAT TOTAL_NUMBER_OF_PARKED_CARS i
IF DOES_ENTITY_EXIST(ParkedCarID[i])
IF NOT IS_ENTITY_DEAD(ParkedCarID[i])
SET_ENTITY_COLLISION(ParkedCarID[i], TRUE)
ENDIF
MARK_CAR_AS_NO_LONGER_NEEDED_KEEP_ID(ParkedCarID[i])
ENDIF
ENDREPEAT
REPEAT TOTAL_NUMBER_OF_PARKED_CARS i
IF NOT (ParkedCarModel[i] = DUMMY_MODEL_FOR_SCRIPT)
SET_MODEL_AS_NO_LONGER_NEEDED(ParkedCarModel[i])
ENDIF
ENDREPEAT
iFirstParkedCarToProcess = 0
iCurrentNumberOfParkedCars = 0
ENDPROC
PROC MARK_ALL_SET_PIECE_CARS_AS_NO_LONGER_NEEDED()
INT i
REPEAT TOTAL_NUMBER_OF_SET_PIECE_CARS i
IF DOES_ENTITY_EXIST(SetPieceCarID[i])
// IF NOT IS_ENTITY_DEAD(SetPieceCarID[i])
// SET_ENTITY_COLLISION(SetPieceCarID[i], TRUE)
// ENDIF
IF IS_VEHICLE_DRIVEABLE(SetPieceCarID[i])
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(SetPieceCarID[i])
STOP_PLAYBACK_RECORDED_VEHICLE(SetPieceCarID[i])
ENDIF
ENDIF
MAKE_CAR_DRIVE_RANDOMLY(SetPieceCarID[i])
MARK_CAR_AS_NO_LONGER_NEEDED_KEEP_ID(SetPieceCarID[i])
ENDIF
SetPieceCarProgress[i] = 0
SetPieceCarFlags[i] = 0
IF NOT bSetPieceRecordingsAreActive AND NOT bTrafficDontCleanupRecordingFiles
IF SetPieceCarRecording[i] > 0
REMOVE_VEHICLE_RECORDING(SetPieceCarRecording[i], strUberName)
ENDIF
ENDIF
ENDREPEAT
REPEAT TOTAL_NUMBER_OF_SET_PIECE_CARS i
IF NOT (SetPieceCarModel[i] = DUMMY_MODEL_FOR_SCRIPT)
SET_MODEL_AS_NO_LONGER_NEEDED(SetPieceCarModel[i])
ENDIF
ENDREPEAT
iFirstSetpieceCarToProcess = 0
ENDPROC
PROC FLUSH_ALL_TRAFFIC_DATA()
INT i
REPEAT TOTAL_NUMBER_OF_TRAFFIC_CARS i
TrafficCarID[i] = NULL
TrafficCarPos[i] = <<0.0, 0.0, 0.0>>
TrafficCarQuatX[i] = 0.0
TrafficCarQuatY[i] = 0.0
TrafficCarQuatZ[i] = 0.0
TrafficCarQuatW[i] = 0.0
TrafficCarRecording[i] = 0
TrafficCarStartime[i] = 0.0
TrafficCarProgress[i] = 0
TrafficCarModel[i] = DUMMY_MODEL_FOR_SCRIPT
TrafficCarFlags[i] = 0
ENDREPEAT
REPEAT MAX_NUMBER_OF_TRAFFIC_CARS_PLAYING_BACK i
RecordedTrafficCarID[i] = NULL
ENDREPEAT
iCurrentNumberOfTrafficPlaybacks = 0
#IF IS_DEBUG_BUILD
iTotalNumberOfTrafficCarsRecorded = 0
iCurrentNumberOfTrafficRecordings = 0
#ENDIF
REPEAT TOTAL_NUMBER_OF_PARKED_CARS i
ParkedCarID[i] = NULL
ParkedCarPos[i] = <<0.0, 0.0, 0.0>>
ParkedCarQuatX[i] = 0.0
ParkedCarQuatY[i] = 0.0
ParkedCarQuatZ[i] = 0.0
ParkedCarQuatW[i] = 0.0
ParkedCarProgress[i] = 0
ParkedCarModel[i] = DUMMY_MODEL_FOR_SCRIPT
ENDREPEAT
REPEAT MAX_NUMBER_OF_PARKED_CARS_PLAYING_BACK i
RecordedParkedCarID[i] = NULL
ENDREPEAT
#IF IS_DEBUG_BUILD
iTotalNumberOfParkedCarsRecorded = 0
#ENDIF
iCurrentNumberOfParkedCars = 0
REPEAT TOTAL_NUMBER_OF_SET_PIECE_CARS i
SetPieceCarID[i] = NULL
SetPieceCarPos[i] = <<0.0, 0.0, 0.0>>
SetPieceCarQuatX[i] = 0.0
SetPieceCarQuatY[i] = 0.0
SetPieceCarQuatZ[i] = 0.0
SetPieceCarQuatW[i] = 0.0
SetPieceCarRecording[i] = 0
SetPieceCarStartime[i] = 0.0
SetPieceCarProgress[i] = 0
SetPieceCarModel[i] = DUMMY_MODEL_FOR_SCRIPT
SetPieceCarFlags[i] = 0
ENDREPEAT
iCurrentNumberOfSetPieceCarPlaybacks = 0
iFirstCarToProcess = 0
iParkedCarsWaitingToCreate = 0
iSetPieceCarsWaitingToCreate = 0
iTrafficCarsWaitingToCreate = 0
ENDPROC
PROC UPDATE_PARKED_CARS(VEHICLE_INDEX TriggerCar)
INT i
VECTOR vPlayerPos, vParkedCarPos
//INTERIOR_INSTANCE_INDEX CarInterior
IF IS_PLAYER_PLAYING(PLAYER_ID())
vPlayerPos = GET_ENTITY_COORDS(PLAYER_PED_ID())
ENDIF
//iParkedCarsProcessedThisFrame = 0
#IF IS_DEBUG_BUILD
IF (iHighlightedParkedCar > -1)
AND (iHighlightedParkedCar < TOTAL_NUMBER_OF_PARKED_CARS)
// remove blip if car doesn't exist
IF NOT DOES_ENTITY_EXIST(ParkedCarID[iHighlightedParkedCar])
IF DOES_BLIP_EXIST(HighlightedParkedCarBlipID)
REMOVE_BLIP(HighlightedParkedCarBlipID)
ENDIF
HighlightedParkedCarID = NULL
ENDIF
// remove blip if highlighted car is dIFferent from the current one.
IF DOES_ENTITY_EXIST(HighlightedParkedCarID)
IF DOES_ENTITY_EXIST(ParkedCarID[iHighlightedParkedCar])
IF NOT (ParkedCarID[iHighlightedParkedCar] = HighlightedParkedCarID)
IF DOES_BLIP_EXIST(HighlightedParkedCarBlipID)
REMOVE_BLIP(HighlightedParkedCarBlipID)
ENDIF
HighlightedParkedCarID = NULL
ENDIF
ENDIF
ELSE
IF DOES_BLIP_EXIST(HighlightedParkedCarBlipID)
REMOVE_BLIP(HighlightedParkedCarBlipID)
ENDIF
ENDIF
// add blip
IF NOT DOES_ENTITY_EXIST(HighlightedParkedCarID)
IF DOES_ENTITY_EXIST(ParkedCarID[iHighlightedParkedCar])
IF NOT DOES_BLIP_EXIST(HighlightedParkedCarBlipID)
HighlightedParkedCarBlipID = ADD_BLIP_FOR_ENTITY(ParkedCarID[iHighlightedParkedCar])
SET_BLIP_COLOUR(HighlightedParkedCarBlipID, BLIP_COLOUR_WHITE)
HighlightedParkedCarID = ParkedCarID[iHighlightedParkedCar]
ENDIF
ENDIF
ENDIF
ELSE
IF DOES_BLIP_EXIST(HighlightedParkedCarBlipID)
REMOVE_BLIP(HighlightedParkedCarBlipID)
ENDIF
ENDIF
#ENDIF
IF IS_VEHICLE_DRIVEABLE(TriggerCar)
BOOL bRemovedCarThisFrame = FALSE
BOOL bFoundFirstCarToProcess = FALSE
#IF IS_DEBUG_BUILD
TEXT_LABEL_63 debugCarName
#ENDIF
i = iFirstParkedCarToProcess
WHILE i < TOTAL_NUMBER_OF_PARKED_CARS
SWITCH ParkedCarProgress[i]
CASE 0
IF NOT (ParkedCarModel[i] = DUMMY_MODEL_FOR_SCRIPT)
IF IS_ENTITY_AT_COORD(TriggerCar, ParkedCarPos[i], <<fPlaybackCarStreamingDistance, fPlaybackCarStreamingDistance, fPlaybackCarStreamingDistance>>, FALSE, TRUE)
iParkedCarsWaitingToCreate++
ParkedCarProgress[i]++
ENDIF
ELSE
ParkedCarProgress[i] = 99
ENDIF
BREAK
CASE 1
IF MAX_NUMBER_OF_PARKED_CARS_PLAYING_BACK > iCurrentNumberOfParkedCars
IF NOT DOES_ENTITY_EXIST(ParkedCarID[i])
REQUEST_MODEL(ParkedCarModel[i])
IF HAS_MODEL_LOADED(ParkedCarModel[i])
IF bResetPlaybackToTime
OR bCreateAllWaitingCars
OR (NOT bCreatedUberPlaybackEntityThisFrame AND NOT private_IS_POINT_VISIBLE_TO_PLAYER_POS(ParkedCarPos[i], vPlayerPos, 5.0, fUberPlaybackMinCreationDistance))
IF (bCarsAreOn)
private_SAFE_CLEAR_AREA_OF_VEHICLES(ParkedCarPos[i], vPlayerPos, fClearSurroundingCarsDistance)
ENDIF
ParkedCarID[i] = CREATE_VEHICLE(ParkedCarModel[i], ParkedCarPos[i], DEFAULT, FALSE, FALSE)
IF ParkedCarModel[i] = POLMAV
SET_VEHICLE_LIVERY(ParkedCarID[i], 0)
ENDIF
#IF IS_DEBUG_BUILD
debugCarName += "Parked "
debugCarName += i
SET_VEHICLE_NAME_DEBUG(ParkedCarID[i], debugCarName)
#ENDIF
SET_ENTITY_QUATERNION(ParkedCarID[i], ParkedCarQuatX[i], ParkedCarQuatY[i], ParkedCarQuatZ[i], ParkedCarQuatW[i])
SET_MODEL_AS_NO_LONGER_NEEDED(ParkedCarModel[i])
IF IS_VEHICLE_MODEL(ParkedCarID[i], COP_CAR_MODEL())
SET_VEHICLE_SIREN(ParkedCarID[i], TRUE)
IF NOT IS_THIS_MODEL_A_BIKE(ParkedCarModel[i])
SET_SIREN_WITH_NO_DRIVER(ParkedCarID[i], TRUE)
ENDIF
ENDIF
IF IS_VEHICLE_MODEL(ParkedCarID[i], DEFAULT_CAR_MODEL())
SET_VEHICLE_COLOURS(ParkedCarID[i], 0, 0)
ENDIF
SET_ENTITY_SHOULD_FREEZE_WAITING_ON_COLLISION(ParkedCarID[i], TRUE) //[MF] Fix for B* 1699535
// check if in an interior
//CarInterior = GET_INTERIOR_FROM_ENTITY(ParkedCarID[i])
//IF NOT (CarInterior = NULL)
//SET_CAR_HAS_BEEN_CREATED_IN_INTERIOR(ParkedCarID[i])
//ENDIF
iParkedCarsWaitingToCreate--
iCurrentNumberOfParkedCars++
ParkedCarProgress[i]++
bCreatedUberPlaybackEntityThisFrame = TRUE
ENDIF
ENDIF
ELSE
//Parked car already exists, so just progress as normal.
iParkedCarsWaitingToCreate--
iCurrentNumberOfParkedCars++
ParkedCarProgress[i]++
ENDIF
ENDIF
BREAK
CASE 2
IF NOT bRemovedCarThisFrame
IF IS_VEHICLE_DRIVEABLE(ParkedCarID[i])
vParkedCarPos = GET_ENTITY_COORDS(ParkedCarID[i])
ENDIF
//If the parked cars are more critical to the mission the scripter can set fUberPlaybackParkedCarCleanupDistance. This means the player has to be within
//this distance of the parked car before it's set as no longer needed.
IF fUberPlaybackParkedCarCleanupDistance = 0.0
OR VDIST2(vPlayerPos, vParkedCarPos) < (fUberPlaybackParkedCarCleanupDistance * fUberPlaybackParkedCarCleanupDistance)
IF NOT IS_CAR_IN_FRONT_OF_CAR(ParkedCarID[i], TriggerCar)
IF NOT (bDeleteCarsWhenDone)
MARK_CAR_AS_NO_LONGER_NEEDED_KEEP_ID(ParkedCarID[i])
ELSE
DELETE_VEHICLE(ParkedCarID[i])
ENDIF
iCurrentNumberOfParkedCars--
ParkedCarProgress[i] = 99
bRemovedCarThisFrame = TRUE
ENDIF
ENDIF
ENDIF
BREAK
ENDSWITCH
IF ParkedCarProgress[i] != 99
//If this is the first car we've reached that hasn't been removed from processing, mark it as the start point for the next frame.
IF NOT bFoundFirstCarToProcess
iFirstParkedCarToProcess = i
bFoundFirstCarToProcess = TRUE
ENDIF
ENDIF
i++
ENDWHILE
ELSE
MARK_ALL_PARKED_CARS_AS_NO_LONGER_NEEDED()
ENDIF
ENDPROC
PROC REMOVE_TRAFFIC_CAR_FROM_PROCESSING(INT iTrafficArrayIndex, FLOAT fCruiseSpeed = MIN_CAR_CRUISE_SPEED)
PED_INDEX pedDriver
IF NOT (TrafficCarModel[iTrafficArrayIndex] = DUMMY_MODEL_FOR_SCRIPT)
SET_MODEL_AS_NO_LONGER_NEEDED(TrafficCarModel[iTrafficArrayIndex])
ENDIF
IF NOT IS_ENTITY_DEAD(TrafficCarID[iTrafficArrayIndex])
SET_ENTITY_COLLISION(TrafficCarID[iTrafficArrayIndex], TRUE)
FREEZE_ENTITY_POSITION(TrafficCarID[iTrafficArrayIndex], FALSE)
pedDriver = GET_PED_IN_VEHICLE_SEAT(TrafficCarID[iTrafficArrayIndex])
IF NOT IS_PED_INJURED(pedDriver)
AND pedDriver != PLAYER_PED_ID()
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(pedDriver, FALSE)
IF (fCruiseSpeed < MIN_CAR_CRUISE_SPEED)
fCruiseSpeed = MIN_CAR_CRUISE_SPEED
ENDIF
IF (fCruiseSpeed > MAX_CAR_CRUISE_SPEED)
fCruiseSpeed = MAX_CAR_CRUISE_SPEED
ENDIF
TASK_VEHICLE_MISSION(pedDriver, TrafficCarID[iTrafficArrayIndex], NULL, MISSION_CRUISE, fCruiseSpeed, DRIVINGMODE_STOPFORCARS, 5, 5)
SET_PED_FLEE_ATTRIBUTES(pedDriver, FA_DISABLE_ACCELERATE_IN_VEHICLE, TRUE)
// B*1490105 - Used to stop released uber veh drivers interferring with chase by reacting to player shooting
IF bSetReleasedDriversToExitOnFlee
SET_PED_FLEE_ATTRIBUTES(pedDriver, FA_FORCE_EXIT_VEHICLE, TRUE)
SET_PED_FLEE_ATTRIBUTES(pedDriver, FA_USE_VEHICLE, FALSE)
ENDIF
SET_PED_COMBAT_ATTRIBUTES(pedDriver, CA_FLEE_WHILST_IN_VEHICLE, FALSE)
SET_DRIVE_TASK_CRUISE_SPEED(pedDriver, fCruiseSpeed)
ENDIF
ENDIF
IF NOT bDeleteCarsWhenDone
IF NOT bDontCleanUpUberCarsForTrailer
MARK_CHAR_AS_NO_LONGER_NEEDED_KEEP_ID(pedDriver)
MARK_CAR_AS_NO_LONGER_NEEDED_KEEP_ID(TrafficCarID[iTrafficArrayIndex])
ENDIF
ELSE
IF DOES_ENTITY_EXIST(pedDriver)
DELETE_PED(pedDriver)
ENDIF
IF DOES_ENTITY_EXIST(TrafficCarID[iTrafficArrayIndex])
DELETE_VEHICLE(TrafficCarID[iTrafficArrayIndex])
ENDIF
ENDIF
IF NOT bSetPieceRecordingsAreActive AND NOT bTrafficDontCleanupRecordingFiles
IF TrafficCarRecording[iTrafficArrayIndex] > 0
REMOVE_VEHICLE_RECORDING(TrafficCarRecording[iTrafficArrayIndex], strUberName)
ENDIF
ENDIF
TrafficCarProgress[iTrafficArrayIndex] = 99
ENDPROC
//allows you to block 2 vehicle colours. If you only need to block one colour just pass in NULL to colour_1
PROC traffic_block_vehicle_colour(BOOL block_colour, block_colour_ENUM colour_0, block_colour_ENUM colour_1 = dont_block_colour)
IF block_colour
block_vehicle_colour = TRUE
colour_to_block_0 = colour_0
colour_to_block_1 = colour_1
ENDIF
ENDPROC
PROC traffic_block_vehicle_colour_from_generating(VEHICLE_INDEX traffic_file_veh)
INT random_INT
block_colour_ENUM traffic_colour
random_int = get_random_int_in_range(0, 12)
IF (colour_to_block_0 >= dont_block_colour) and (colour_to_block_1 >= dont_block_colour)
while (random_int = ENUM_TO_INT(colour_to_block_0)) or (random_int = ENUM_TO_INT(colour_to_block_1))
random_int++
endwhile
elif (colour_to_block_0 >= dont_block_colour)
IF random_int = ENUM_TO_INT(colour_to_block_0)//colour_to_block is set in traffic_block_vehicle_colour()
random_int++
ENDIF
ENDIF
traffic_colour = INT_TO_ENUM(block_colour_ENUM, random_int)
switch traffic_colour
case traffic_black
set_vehicle_colours(traffic_file_veh, 0, 0)
break
case traffic_grey
set_vehicle_colours(traffic_file_veh, 2, 2)
break
case traffic_silver
set_vehicle_colours(traffic_file_veh, 4, 4)
break
case traffic_red
set_vehicle_colours(traffic_file_veh, 27, 27)
break
case traffic_white
set_vehicle_colours(traffic_file_veh, 7, 7)
break
case traffic_blue
set_vehicle_colours(traffic_file_veh, 73, 73)
break
case traffic_navy
set_vehicle_colours(traffic_file_veh, 68, 68)
break
case traffic_light_blue
set_vehicle_colours(traffic_file_veh, 62, 62)
break
case traffic_cream
set_vehicle_colours(traffic_file_veh, 132, 132)
break
case traffic_turquoise
set_vehicle_colours(traffic_file_veh, 117, 0)
break
case traffic_green
set_vehicle_colours(traffic_file_veh, 52, 52)
break
case traffic_orange
set_vehicle_colours(traffic_file_veh, 88, 88)
break
case traffic_gun_metal_grey
set_vehicle_colours(traffic_file_veh, 1, 1)
break
case traffic_burgundy
set_vehicle_colours(traffic_file_veh, 36, 36)
break
case traffic_gold
set_vehicle_colours(traffic_file_veh, 95, 95) //blue
break
default
set_vehicle_colours(traffic_file_veh, 73, 73) //blue
break
endswitch
ENDPROC
/// PURPOSE:
/// Call every frame: this stops the uber playback from processing horns and lights. This may be useful if you need to cut down on processor time (these can be costly)
/// or if you have your own scripts in place for triggering horns/lights.
PROC DONT_PROCESS_UBER_PLAYBACK_HORNS_AND_LIGHTS()
bDontProcessTrafficHornsAndLights = TRUE
ENDPROC
FUNC BOOL is_trailer_touching_entity(VEHICLE_INDEX mission_vehicle)
IF allow_trailer_touching_check
VEHICLE_INDEX trailer_veh
VEHICLE_INDEX players_last_veh
MODEL_NAMES truck_model
players_last_veh = GET_PLAYERS_LAST_VEHICLE()
IF NOT IS_ENTITY_DEAD(players_last_veh)
truck_model = GET_ENTITY_MODEL(players_last_veh)
IF truck_model = phantom
IF IS_VEHICLE_ATTACHED_TO_TRAILER(players_last_veh)
IF GET_VEHICLE_TRAILER_VEHICLE(players_last_veh, trailer_veh)
IF IS_VEHICLE_DRIVEABLE(trailer_veh)
IF IS_ENTITY_TOUCHING_ENTITY(trailer_veh, mission_vehicle)
RETURN TRUE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
PROC UPDATE_TRAFFIC_PLAYBACK(VEHICLE_INDEX TriggerCar, FLOAT fPlaybackSpeed, BOOL bForceCreateCars = FALSE)
CONST_INT MAX_NUM_CARS_TO_COLLISION_PROCESS_PER_FRAME 3
CONST_INT MAX_NUM_CARS_TO_CREATION_PROCESS_PER_FRAME 8
INT i, iExitCount, iNumTrafficCarsProcessedThisFrame, iNumTrafficCarsProcessedForCreationThisFrame
PED_INDEX temp_char
VEHICLE_INDEX vehPlayersCar = NULL
VECTOR pos, pos2, vPlayerPos
FLOAT fSkipTime, fTemp
BOOL bFlag
BOOL bPlayerIsAlive = IS_PLAYER_PLAYING(PLAYER_ID())
BOOL bCanCreateRandomDriver = CAN_CREATE_RANDOM_DRIVER()
BOOL bCanCreateRandomBikeRider = CAN_CREATE_RANDOM_BIKE_RIDER()
UBER_PLAYBACK_PED_MODEL ePedModelToUse
//INTERIOR_INSTANCE_INDEX CarInterior
IF bPlayerIsAlive
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
vehPlayersCar = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())
ENDIF
vPlayerPos = GET_ENTITY_COORDS(PLAYER_PED_ID())
ENDIF
iExitCount = 0
#IF IS_DEBUG_BUILD
iCarsProcessedThisFrame = 0
IF (iHighlightedTrafficCar > -1)
AND (iHighlightedTrafficCar < TOTAL_NUMBER_OF_TRAFFIC_CARS)
// remove blip if car doesn't exist
IF NOT DOES_ENTITY_EXIST(TrafficCarID[iHighlightedTrafficCar])
IF DOES_BLIP_EXIST(HighlightedTrafficCarBlipID)
REMOVE_BLIP(HighlightedTrafficCarBlipID)
ENDIF
HighlightedTrafficCarID = NULL
ENDIF
// remove blip if highlighted car is dIFferent from the current one.
IF DOES_ENTITY_EXIST(HighlightedTrafficCarID)
IF DOES_ENTITY_EXIST(TrafficCarID[iHighlightedTrafficCar])
IF NOT (TrafficCarID[iHighlightedTrafficCar] = HighlightedTrafficCarID)
IF DOES_BLIP_EXIST(HighlightedTrafficCarBlipID)
REMOVE_BLIP(HighlightedTrafficCarBlipID)
ENDIF
HighlightedTrafficCarID = NULL
ENDIF
ENDIF
ELSE
IF DOES_BLIP_EXIST(HighlightedTrafficCarBlipID)
REMOVE_BLIP(HighlightedTrafficCarBlipID)
ENDIF
ENDIF
// add blip
IF NOT DOES_ENTITY_EXIST(HighlightedTrafficCarID)
IF DOES_ENTITY_EXIST(TrafficCarID[iHighlightedTrafficCar])
IF NOT DOES_BLIP_EXIST(HighlightedTrafficCarBlipID)
HighlightedTrafficCarBlipID = ADD_BLIP_FOR_ENTITY(TrafficCarID[iHighlightedTrafficCar])
SET_BLIP_COLOUR(HighlightedTrafficCarBlipID, BLIP_COLOUR_WHITE)
HighlightedTrafficCarID = TrafficCarID[iHighlightedTrafficCar]
ENDIF
ENDIF
ENDIF
ELSE
IF DOES_BLIP_EXIST(HighlightedTrafficCarBlipID)
REMOVE_BLIP(HighlightedTrafficCarBlipID)
ENDIF
ENDIF
#ENDIF
IF IS_VEHICLE_DRIVEABLE(TriggerCar)
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(TriggerCar)
fTriggerCarPlaybackTime = GET_TIME_POSITION_IN_RECORDING(TriggerCar)
ENDIF
// to help save on processing time, skip to the first car that needs processed (when cars are removed from processing this number is increased)
INT iFirstCarThatNeedsProcessingThisFrame = -1
BOOL bExitLoop = FALSE
BOOL bSwitchToAI = FALSE
i = iFirstCarToProcess
WHILE i < TOTAL_NUMBER_OF_TRAFFIC_CARS AND NOT bExitLoop
//SWITCH TrafficCarProgress[i]
//CASE 0
IF TrafficCarProgress[i] != 99
IF TrafficCarProgress[i] = 0
IF TrafficCarRecording[i] > 0
AND TrafficCarModel[i] != DUMMY_MODEL_FOR_SCRIPT
IF NOT (bResetPlaybackToTime)
IF fTriggerCarPlaybackTime < TrafficCarStartime[i] + 20000.0
IF (fTriggerCarPlaybackTime >= (TrafficCarStartime[i] - (LOAD_AHEAD_TIME * fPlaybackSpeed)))
IF IS_VEH_MODEL_A_COP_MODEL(TrafficCarModel[i])
SET_BIT(TrafficCarFlags[i], TRAFFIC_FLAGS_VEH_IS_A_COP)
ELIF IS_THIS_MODEL_A_BIKE(TrafficCarModel[i])
SET_BIT(TrafficCarFlags[i], TRAFFIC_FLAGS_VEH_IS_A_BIKE)
ENDIF
CLEAR_BIT(TrafficCarFlags[i], TRAFFIC_FLAGS_DRIVER_HAS_BEEN_CREATED)
iTrafficCarsWaitingToCreate++
TrafficCarProgress[i]++
ELSE
IF (iExitCount > 2)
bExitLoop = TRUE //Future cars in the array don't require processing yet: quit the loop to save processor time.
ELSE
iExitCount++
ENDIF
ENDIF
ELSE
#IF IS_DEBUG_BUILD
IF (bTrafficDebugOn)
PRINTLN("traffic.sch - Removing car: Trigger time is already passed recording point - ", i)
ENDIF
#ENDIF
REMOVE_TRAFFIC_CAR_FROM_PROCESSING(i)
ENDIF
ELSE
// should this traffic car be playing?
fSkipTime = fTriggerCarPlaybackTime - TrafficCarStartime[i]
IF (fSkipTime >= 0.0)
IF (fSkipTime < GET_RECORDING_LENGTH(TrafficCarRecording[i]))
IF IS_VEH_MODEL_A_COP_MODEL(TrafficCarModel[i])
SET_BIT(TrafficCarFlags[i], TRAFFIC_FLAGS_VEH_IS_A_COP)
ELIF IS_THIS_MODEL_A_BIKE(TrafficCarModel[i])
SET_BIT(TrafficCarFlags[i], TRAFFIC_FLAGS_VEH_IS_A_BIKE)
ENDIF
CLEAR_BIT(TrafficCarFlags[i], TRAFFIC_FLAGS_DRIVER_HAS_BEEN_CREATED)
iTrafficCarsWaitingToCreate++
TrafficCarProgress[i]++
ELSE
REMOVE_TRAFFIC_CAR_FROM_PROCESSING(i)
ENDIF
ENDIF
ENDIF
ELSE
REMOVE_TRAFFIC_CAR_FROM_PROCESSING(i)
ENDIF
ELIF TrafficCarProgress[i] = 1
REQUEST_VEHICLE_RECORDING(TrafficCarRecording[i], strUberName)
bFlag = FALSE
IF IS_BIT_SET(TrafficCarFlags[i], TRAFFIC_FLAGS_VEH_IS_A_COP)
REQUEST_MODEL(COP_PED_MODEL())
IF HAS_MODEL_LOADED(COP_PED_MODEL())
bFlag = TRUE
ENDIF
ELSE
IF NOT bTrafficForceDefaultPedModel
AND ((NOT IS_BIT_SET(TrafficCarFlags[i], TRAFFIC_FLAGS_VEH_IS_A_BIKE) AND bCanCreateRandomDriver)
OR (IS_BIT_SET(TrafficCarFlags[i], TRAFFIC_FLAGS_VEH_IS_A_BIKE) AND bCanCreateRandomBikeRider))
bFlag = TRUE
ELSE
REQUEST_MODEL(DEFAULT_PED_MODEL())
bFlag = HAS_MODEL_LOADED(DEFAULT_PED_MODEL())
ENDIF
ENDIF
//Create the car if safe to do so.
IF NOT DOES_ENTITY_EXIST(TrafficCarID[i])
REQUEST_MODEL(TrafficCarModel[i])
IF HAS_MODEL_LOADED(TrafficCarModel[i])
AND HAS_VEHICLE_RECORDING_BEEN_LOADED(TrafficCarRecording[i], strUberName)
AND bFlag
IF (fTriggerCarPlaybackTime >= (TrafficCarStartime[i] - (fUberMinTimeBeforePlaybackStartToCreate * fPlaybackSpeed)))
IF bCreateAllWaitingCars
OR bForceCreateCars
OR (NOT bCreatedUberPlaybackEntityThisFrame AND NOT private_IS_POINT_VISIBLE_TO_PLAYER_POS(TrafficCarPos[i], vPlayerPos, 5.0, fUberPlaybackMinCreationDistance))
//Create the car if the creation point isn't visible/obstructed or IF it's being forced to create.
IF (bCarsAreOn)
private_SAFE_CLEAR_AREA_OF_VEHICLES(TrafficCarPos[i], vPlayerPos, fClearSurroundingCarsDistance)
ENDIF
TrafficCarID[i] = CREATE_VEHICLE(TrafficCarModel[i], TrafficCarPos[i], DEFAULT, FALSE, FALSE)
IF TrafficCarModel[i] = POLMAV
SET_VEHICLE_LIVERY(TrafficCarID[i], 0)
ENDIF
IF block_vehicle_colour
AND NOT IS_BIT_SET(TrafficCarFlags[i], TRAFFIC_FLAGS_VEH_IS_A_COP)
traffic_block_vehicle_colour_from_generating(TrafficCarID[i])
ENDIF
#IF IS_DEBUG_BUILD
TEXT_LABEL_63 debugCarName = "Traffic "
debugCarName += i
SET_VEHICLE_NAME_DEBUG(TrafficCarID[i], debugCarName)
#ENDIF
SET_ENTITY_COORDS_NO_OFFSET(TrafficCarID[i], TrafficCarPos[i])
SET_ENTITY_QUATERNION(TrafficCarID[i], TrafficCarQuatX[i], TrafficCarQuatY[i], TrafficCarQuatZ[i], TrafficCarQuatW[i])
IF IS_THIS_MODEL_A_CAR(TrafficCarModel[i])
OR IS_THIS_MODEL_A_BIKE(TrafficCarModel[i])
SET_VEHICLE_ON_GROUND_PROPERLY(TrafficCarID[i])
ENDIF
IF IS_BIT_SET(TrafficCarFlags[i], TRAFFIC_FLAGS_FREEZE_CAR_FOR_COLLISION)
SET_ENTITY_SHOULD_FREEZE_WAITING_ON_COLLISION(TrafficCarID[i], TRUE)
ENDIF
IF NOT IS_BIT_SET(TrafficCarFlags[i], TRAFFIC_FLAGS_VEH_IS_A_COP)
SET_VEHICLE_ENGINE_ON(TrafficCarID[i], TRUE, TRUE)
IF GET_CLOCK_HOURS() > 19 OR GET_CLOCK_HOURS() < 7
SET_VEHICLE_LIGHTS(TrafficCarID[i], SET_VEHICLE_LIGHTS_ON)
ENDIF
ENDIF
FREEZE_ENTITY_POSITION(TrafficCarID[i], TRUE)
SET_ENTITY_ONLY_DAMAGED_BY_PLAYER(TrafficCarID[i], TRUE)
SET_MODEL_AS_NO_LONGER_NEEDED(TrafficCarModel[i])
iTrafficCarsWaitingToCreate--
TrafficCarProgress[i]++
bCreatedUberPlaybackEntityThisFrame = TRUE
ELSE
IF (fTriggerCarPlaybackTime > TrafficCarStartime[i])
#IF IS_DEBUG_BUILD
IF (bTrafficDebugOn)
PRINTLN("traffic.sch - Traffic Car not created - point was visible to player - i = ", i)
ENDIF
#ENDIF
iTrafficCarsWaitingToCreate--
REMOVE_TRAFFIC_CAR_FROM_PROCESSING(i)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ELIF TrafficCarProgress[i] = 2
bFlag = FALSE
IF (iNumTrafficCarsProcessedForCreationThisFrame < MAX_NUM_CARS_TO_CREATION_PROCESS_PER_FRAME AND (i > iLastTrafficCarProcessedForCreation OR iLastTrafficCarProcessedForCreation = 0))
OR bCreateAllWaitingCars
OR bForceCreateCars
IF NOT IS_BIT_SET(TrafficCarFlags[i], TRAFFIC_FLAGS_DRIVER_HAS_BEEN_CREATED)
IF IS_BIT_SET(TrafficCarFlags[i], TRAFFIC_FLAGS_VEH_IS_A_COP)
REQUEST_MODEL(COP_PED_MODEL())
bFlag = HAS_MODEL_LOADED(COP_PED_MODEL())
ePedModelToUse = UBER_PLAYBACK_PED_MODEL_COP
ELSE
IF NOT bTrafficForceDefaultPedModel
AND ((NOT IS_BIT_SET(TrafficCarFlags[i], TRAFFIC_FLAGS_VEH_IS_A_BIKE) AND bCanCreateRandomDriver)
OR (IS_BIT_SET(TrafficCarFlags[i], TRAFFIC_FLAGS_VEH_IS_A_BIKE) AND bCanCreateRandomBikeRider))
bFlag = TRUE
ePedModelToUse = UBER_PLAYBACK_PED_MODEL_AMBIENT
ELSE
REQUEST_MODEL(DEFAULT_PED_MODEL())
bFlag = HAS_MODEL_LOADED(DEFAULT_PED_MODEL())
ePedModelToUse = UBER_PLAYBACK_PED_MODEL_DEFAULT
ENDIF
ENDIF
//Peds now aren't created until playback starts, as a failsafe also create the ped if the player gets close to the vehicle.
IF NOT IS_ENTITY_DEAD(TrafficCarID[i])
IF NOT bCreatedUberPlaybackEntityThisFrame
AND IS_VEHICLE_SEAT_FREE(TrafficCarID[i])
IF bFlag
IF VDIST2(GET_ENTITY_COORDS(TrafficCarID[i]), vPlayerPos) < 10000.0
OR bForceCreateCars
OR bCreateAllWaitingCars
#IF IS_DEBUG_BUILD
IF (bTrafficDebugOn)
PRINTLN("traffic.sch - Traffic ped created early: ", fTriggerCarPlaybackTime, " index = ", i)
ENDIF
#ENDIF
private_CREATE_PED_INSIDE_UBER_PLAYBACK_CAR(TrafficCarID[i], ePedModelToUse)
SET_BIT(TrafficCarFlags[i], TRAFFIC_FLAGS_DRIVER_HAS_BEEN_CREATED)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
IF IS_VEHICLE_DRIVEABLE(TrafficCarID[i])
REQUEST_VEHICLE_RECORDING(TrafficCarRecording[i], strUberName)
IF (fTriggerCarPlaybackTime >= TrafficCarStartime[i])
IF MAX_NUMBER_OF_TRAFFIC_CARS_PLAYING_BACK > iCurrentNumberOfTrafficPlaybacks
fSkipTime = fTriggerCarPlaybackTime - TrafficCarStartime[i]
// check its not too late
IF HAS_VEHICLE_RECORDING_BEEN_LOADED(TrafficCarRecording[i], strUberName)
IF fSkipTime < GET_TOTAL_DURATION_OF_VEHICLE_RECORDING(TrafficCarRecording[i],strUberName)
// check we're not updating to a position on screen, from an offscreen position
pos = GET_ENTITY_COORDS(TrafficCarID[i])
pos2 = GET_POSITION_OF_VEHICLE_RECORDING_AT_TIME(TrafficCarRecording[i], fSkipTime,strUberName)
IF NOT private_IS_POINT_VISIBLE_TO_PLAYER_POS(pos, vPlayerPos, 5.0, fUberPlaybackMinCreationDistance)
AND private_IS_POINT_VISIBLE_TO_PLAYER_POS(pos2, vPlayerPos, 5.0, fUberPlaybackMinCreationDistance)
#IF IS_DEBUG_BUILD
IF (bTrafficDebugOn)
PRINTLN("traffic.sch - Traffic car failed to start: start pos is visible car = ", i)
ENDIF
#ENDIF
IF NOT IS_BIT_SET(TrafficCarFlags[i], TRAFFIC_FLAGS_DRIVER_HAS_BEEN_CREATED)
private_CREATE_PED_INSIDE_UBER_PLAYBACK_CAR(TrafficCarID[i], ePedModelToUse)
ENDIF
REMOVE_TRAFFIC_CAR_FROM_PROCESSING(i)
ELSE
IF NOT bCreatedUberPlaybackEntityThisFrame
OR IS_BIT_SET(TrafficCarFlags[i], TRAFFIC_FLAGS_DRIVER_HAS_BEEN_CREATED)
OR bCreateAllWaitingCars
OR bForceCreateCars
IF SET_CAR_AT_PLAYBACK_POSITION(TrafficCarID[i], TrafficCarRecording[i], fSkipTime, TRUE, FALSE, FALSE, TRUE, allow_veh_to_stop_on_any_veh_impact)
IF NOT IS_BIT_SET(TrafficCarFlags[i], TRAFFIC_FLAGS_DRIVER_HAS_BEEN_CREATED)
private_CREATE_PED_INSIDE_UBER_PLAYBACK_CAR(TrafficCarID[i], ePedModelToUse)
ENDIF
SET_ENTITY_COLLISION(TrafficCarID[i], TRUE)
SET_PLAYBACK_SPEED(TrafficCarID[i], fPlaybackSpeed)
iCurrentNumberOfTrafficPlaybacks++
TrafficCarProgress[i]++
ENDIF
ENDIF
ENDIF
ELSE
#IF IS_DEBUG_BUILD
IF (bTrafficDebugOn)
PRINTLN("traffic.sch - Traffic car removed from processing (check A: already passed the playback end time) car = ", i)
ENDIF
#ENDIF
IF NOT IS_BIT_SET(TrafficCarFlags[i], TRAFFIC_FLAGS_DRIVER_HAS_BEEN_CREATED)
private_CREATE_PED_INSIDE_UBER_PLAYBACK_CAR(TrafficCarID[i], ePedModelToUse)
ENDIF
REMOVE_TRAFFIC_CAR_FROM_PROCESSING(i)
ENDIF
ELSE
IF fSkipTime > GET_TOTAL_DURATION_OF_VEHICLE_RECORDING(TrafficCarRecording[i],strUberName)
#IF IS_DEBUG_BUILD
IF (bTrafficDebugOn)
PRINTLN("traffic.sch - Traffic car removed from processing (check B: recording didn't load in time) car = ", i)
ENDIF
#ENDIF
IF NOT IS_BIT_SET(TrafficCarFlags[i], TRAFFIC_FLAGS_DRIVER_HAS_BEEN_CREATED)
private_CREATE_PED_INSIDE_UBER_PLAYBACK_CAR(TrafficCarID[i], ePedModelToUse)
ENDIF
REMOVE_TRAFFIC_CAR_FROM_PROCESSING(i)
ENDIF
ENDIF
ELSE
#IF IS_DEBUG_BUILD
IF (bTrafficDebugOn)
PRINTLN("traffic.sch - Traffic car removed from processing (check C: reached limit of simultaneous playbacks) car = ", i)
ENDIF
#ENDIF
IF NOT IS_BIT_SET(TrafficCarFlags[i], TRAFFIC_FLAGS_DRIVER_HAS_BEEN_CREATED)
private_CREATE_PED_INSIDE_UBER_PLAYBACK_CAR(TrafficCarID[i], ePedModelToUse)
ENDIF
REMOVE_TRAFFIC_CAR_FROM_PROCESSING(i)
ENDIF
ELSE
IF (bPlayerIsAheadOfChase)
AND NOT (bPlayTrafficRecordingEvenIfPlayerIsAheadOfChase)
#IF IS_DEBUG_BUILD
IF (bTrafficDebugOn)
PRINTLN("traffic.sch - Traffic car removed from processing (check D: player ahead of chase, not safe to create) car = ", i)
ENDIF
#ENDIF
IF NOT IS_BIT_SET(TrafficCarFlags[i], TRAFFIC_FLAGS_DRIVER_HAS_BEEN_CREATED)
private_CREATE_PED_INSIDE_UBER_PLAYBACK_CAR(TrafficCarID[i], ePedModelToUse)
ENDIF
REMOVE_TRAFFIC_CAR_FROM_PROCESSING(i)
ENDIF
ENDIF
ELSE
#IF IS_DEBUG_BUILD
IF (bTrafficDebugOn)
PRINTLN("traffic.sch - Traffic car removed from processing (check E: car is undriveable) car = ", i)
ENDIF
#ENDIF
IF NOT IS_BIT_SET(TrafficCarFlags[i], TRAFFIC_FLAGS_DRIVER_HAS_BEEN_CREATED)
private_CREATE_PED_INSIDE_UBER_PLAYBACK_CAR(TrafficCarID[i], ePedModelToUse)
ENDIF
REMOVE_TRAFFIC_CAR_FROM_PROCESSING(i)
ENDIF
iNumTrafficCarsProcessedForCreationThisFrame++
iLastTrafficCarProcessedForCreation = i
ENDIF
ELIF TrafficCarProgress[i] = 3
IF IS_VEHICLE_DRIVEABLE(TrafficCarID[i])
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(TrafficCarID[i])
#IF IS_DEBUG_BUILD
IF (bShowTrafficCarPaths)
DISPLAY_PLAYBACK_RECORDED_VEHICLE(TrafficCarID[i], RDM_WHOLELINE)
ELSE
DISPLAY_PLAYBACK_RECORDED_VEHICLE(TrafficCarID[i], RDM_NONE)
ENDIF
#ENDIF
temp_char = GET_PED_IN_VEHICLE_SEAT(TrafficCarID[i])
IF NOT IS_PED_INJURED(temp_char)
// player his hit traffic? if so switch to ai
IF bPlayerIsAlive
bSwitchToAI = FALSE
//Traffic cars by default are set to switch to AI on player collisions. Do any additional checks here.
IF NOT bTrafficDontSwitchToAI
IF NOT bSetPieceCarIsRecording
AND NOT bPausePlayback
AND is_trailer_touching_entity(TrafficCarID[i])
IF iNumTrafficCarsProcessedThisFrame < MAX_NUM_CARS_TO_COLLISION_PROCESS_PER_FRAME
AND (i > iLastTrafficCarProcessedForCollisions OR iLastTrafficCarProcessedForCollisions = 0)
IF NOT IS_ENTITY_DEAD(vehPlayersCar)
bFlag = FALSE
IF NOT ARE_CARS_TRAVELLING_IN_SAME_DIRECTION(TrafficCarID[i], vehPlayersCar)
OR IS_CAR_IN_FRONT_OF_CAR(vehPlayersCar, TrafficCarID[i])
bSwitchToAI = TRUE
ENDIF
ENDIF
iLastTrafficCarProcessedForCollisions = i
iNumTrafficCarsProcessedThisFrame++
ENDIF
ELSE
IF NOT bTrafficOnlySwitchToAIOnCollision
AND NOT IS_BIT_SET(TrafficCarFlags[i], TRAFFIC_FLAGS_DONT_SWITCH_TO_AI_EARLY)
AND iNumTrafficCarsProcessedThisFrame < MAX_NUM_CARS_TO_COLLISION_PROCESS_PER_FRAME
AND (i > iLastTrafficCarProcessedForCollisions OR iLastTrafficCarProcessedForCollisions = 0)
//Switch the car to AI if it's behind the trigger car by a significant amount.
VECTOR vTrafficOffsetFromTrigger = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(TriggerCar, GET_ENTITY_COORDS(TrafficCarID[i]))
IF vTrafficOffsetFromTrigger.y < 0.0
IF ABSF(vTrafficOffsetFromTrigger.y) > ABSF(vTrafficOffsetFromTrigger.x)
bSwitchToAI = TRUE
ENDIF
ENDIF
//Old version
/*IF IS_CAR_IN_FRONT_OF_CAR(TriggerCar, TrafficCarID[i])
IF IS_CAR_FURTHER_IN_FRONT_THAN_WIDE(TriggerCar, TrafficCarID[i])
bSwitchToAI = TRUE
ENDIF
ENDIF*/
iNumTrafficCarsProcessedThisFrame++
iLastTrafficCarProcessedForCollisions = i
ENDIF
ENDIF
ENDIF
IF bSwitchToAI
CHANGE_PLAYBACK_TO_USE_AI_AND_KEEP_SPEED(TrafficCarID[i])
TrafficCarProgress[i]++
ELSE
SET_PLAYBACK_SPEED(TrafficCarID[i], fPlaybackSpeed)
ENDIF
ENDIF
ELSE
STOP_PLAYBACK_RECORDED_VEHICLE(TrafficCarID[i])
ENDIF
ELSE
TrafficCarProgress[i]++
ENDIF
ELSE
TrafficCarProgress[i]++
ENDIF
ELIF TrafficCarProgress[i] = 4
IF IS_VEHICLE_DRIVEABLE(TrafficCarID[i])
IF NOT IS_PLAYBACK_GOING_ON_FOR_VEHICLE(TrafficCarID[i])
TrafficCarProgress[i]++
ELSE
temp_char = GET_PED_IN_VEHICLE_SEAT(TrafficCarID[i])
IF NOT IS_PED_INJURED(temp_char)
SET_PLAYBACK_SPEED(TrafficCarID[i], fPlaybackSpeed)
#IF IS_DEBUG_BUILD
IF (bShowTrafficCarPaths)
DISPLAY_PLAYBACK_RECORDED_VEHICLE(TrafficCarID[i], RDM_WHOLELINE)
ELSE
DISPLAY_PLAYBACK_RECORDED_VEHICLE(TrafficCarID[i], RDM_NONE)
ENDIF
#ENDIF
ELSE
STOP_PLAYBACK_RECORDED_VEHICLE(TrafficCarID[i])
ENDIF
// check if current time is after the finish time
IF HAS_VEHICLE_RECORDING_BEEN_LOADED(TrafficCarRecording[i], strUberName)
IF (fTriggerCarPlaybackTime > (TrafficCarStartime[i] + GET_TOTAL_DURATION_OF_VEHICLE_RECORDING(TrafficCarRecording[i],strUberName)))
STOP_PLAYBACK_RECORDED_VEHICLE(TrafficCarID[i])
ENDIF
ELSE
STOP_PLAYBACK_RECORDED_VEHICLE(TrafficCarID[i])
ENDIF
ENDIF
ELSE
TrafficCarProgress[i]++
ENDIF
ELIF TrafficCarProgress[i] = 5
IF NOT IS_ENTITY_DEAD(TrafficCarID[i])
fTemp = GET_ENTITY_SPEED(TrafficCarID[i])
ENDIF
iCurrentNumberOfTrafficPlaybacks--
REMOVE_TRAFFIC_CAR_FROM_PROCESSING(i, fTemp)
ENDIF
//If this is the first car to still require processing then mark it as the start point for the next frame.
IF iFirstCarThatNeedsProcessingThisFrame = -1
iFirstCarThatNeedsProcessingThisFrame = i
ENDIF
ENDIF
//ENDSWITCH
#IF IS_DEBUG_BUILD
iCarsProcessedThisFrame++
TEXT_LABEL str_index = ""
//Draws the array index for each traffic car above it
IF bShowTrafficIndices
IF DOES_ENTITY_EXIST(TrafficCarID[i])
str_index = i
DRAW_DEBUG_TEXT(str_index, GET_ENTITY_COORDS(TrafficCarID[i], FALSE) + <<0.0, 0.0, 2.5>>)
ENDIF
ENDIF
IF bDrawTrafficProgress
IF DOES_ENTITY_EXIST(TrafficCarID[i])
str_index = TrafficCarProgress[i]
DRAW_DEBUG_TEXT(str_index, GET_ENTITY_COORDS(TrafficCarID[i], FALSE) + <<0.0, 0.0, 2.0>>)
ENDIF
ENDIF
#ENDIF
// maximum of 20 cars processed per frame
// IF (iCarsProcessedThisFrame >= 20)
// bExitLoop = TRUE
// ENDIF
i++
ENDWHILE
IF iFirstCarThatNeedsProcessingThisFrame != -1
iFirstCarToProcess = iFirstCarThatNeedsProcessingThisFrame
ENDIF
//If we didn't hit enough cars to process this frame then reset the last car counter to start back at the beginning.
IF iNumTrafficCarsProcessedThisFrame < MAX_NUM_CARS_TO_COLLISION_PROCESS_PER_FRAME
iLastTrafficCarProcessedForCollisions = 0
ENDIF
IF iNumTrafficCarsProcessedForCreationThisFrame < MAX_NUM_CARS_TO_CREATION_PROCESS_PER_FRAME
iLastTrafficCarProcessedForCreation = 0
ENDIF
ELSE
MARK_ALL_TRAFFIC_CARS_AS_NO_LONGER_NEEDED()
ENDIF
ENDPROC
PROC UPDATE_SET_PIECE_CARS(VEHICLE_INDEX TriggerCar, FLOAT fPlaybackSpeed, BOOL bForceCreateCars = FALSE)
INT i
PED_INDEX temp_char
VEHICLE_INDEX vehPlayersCar
VECTOR pos, pos2, vPlayerPos
FLOAT fSkipTime, fTemp
BOOL bFlag
BOOL bPlayerAlive = IS_PLAYER_PLAYING(PLAYER_ID())
BOOL bCanCreateRandomDriver = CAN_CREATE_RANDOM_DRIVER()
BOOL bCanCreateRandomBikeRider = CAN_CREATE_RANDOM_BIKE_RIDER()
BOOL bFoundFirstCarToProcess = FALSE
UBER_PLAYBACK_PED_MODEL eModelToUse
//INTERIOR_INSTANCE_INDEX CarInterior
IF bPlayerAlive
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
vehPlayersCar = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())
ENDIF
vPlayerPos = GET_ENTITY_COORDS(PLAYER_PED_ID())
ENDIF
IF IS_VEHICLE_DRIVEABLE(TriggerCar)
i = iFirstSetpieceCarToProcess
WHILE i < TOTAL_NUMBER_OF_SET_PIECE_CARS
//SWITCH SetPieceCarProgress[i]
//CASE 0
IF SetPieceCarProgress[i] != 99
IF SetPieceCarProgress[i] = 0
IF (SetPieceCarRecording[i] > 0)
IF NOT (bResetPlaybackToTime)
IF (fTriggerCarPlaybackTime > (SetPieceCarStartime[i] - (LOAD_AHEAD_TIME * fPlaybackSpeed)))
IF IS_VEH_MODEL_A_COP_MODEL(SetPieceCarModel[i])
SET_BIT(SetPieceCarFlags[i], TRAFFIC_FLAGS_VEH_IS_A_COP)
ELIF IS_THIS_MODEL_A_BIKE(SetPieceCarModel[i])
SET_BIT(SetPieceCarFlags[i], TRAFFIC_FLAGS_VEH_IS_A_BIKE)
ENDIF
CLEAR_BIT(SetPieceCarFlags[i], TRAFFIC_FLAGS_DRIVER_HAS_BEEN_CREATED)
SetPieceCarProgress[i]++
iSetPieceCarsWaitingToCreate++
ENDIF
ELSE
// should this set piece car be playing?
fSkipTime = fTriggerCarPlaybackTime - SetPieceCarStartime[i]
fSkipTime *= SetPieceCarRecordingSpeed[i]
IF (fSkipTime >= 0.0)
IF (fSkipTime < GET_RECORDING_LENGTH(SetPieceCarRecording[i]))
IF IS_VEH_MODEL_A_COP_MODEL(SetPieceCarModel[i])
SET_BIT(SetPieceCarFlags[i], TRAFFIC_FLAGS_VEH_IS_A_COP)
ELIF IS_THIS_MODEL_A_BIKE(SetPieceCarModel[i])
SET_BIT(SetPieceCarFlags[i], TRAFFIC_FLAGS_VEH_IS_A_BIKE)
ENDIF
CLEAR_BIT(SetPieceCarFlags[i], TRAFFIC_FLAGS_DRIVER_HAS_BEEN_CREATED)
SetPieceCarProgress[i]++
iSetPieceCarsWaitingToCreate++
ELSE
SetPieceCarProgress[i] = 99 // this playback would have already finished
ENDIF
ENDIF
ENDIF
ELSE
SetPieceCarProgress[i] = 99
ENDIF
ELIF SetPieceCarProgress[i] = 1
bFlag = FALSE
REQUEST_VEHICLE_RECORDING(SetPieceCarRecording[i], strUberName)
IF IS_BIT_SET(SetPieceCarFlags[i], TRAFFIC_FLAGS_VEH_IS_A_COP)
REQUEST_MODEL(COP_PED_MODEL())
bFlag = HAS_MODEL_LOADED(COP_PED_MODEL())
ELSE
IF NOT bTrafficForceDefaultPedModel
AND ((NOT IS_BIT_SET(SetPieceCarFlags[i], TRAFFIC_FLAGS_VEH_IS_A_BIKE) AND bCanCreateRandomDriver)
OR (IS_BIT_SET(SetPieceCarFlags[i], TRAFFIC_FLAGS_VEH_IS_A_BIKE) AND bCanCreateRandomBikeRider))
bFlag = TRUE
ELSE
REQUEST_MODEL(DEFAULT_PED_MODEL())
bFlag = HAS_MODEL_LOADED(DEFAULT_PED_MODEL())
ENDIF
ENDIF
//Create the car if safe to do so.
IF bFlag
IF NOT DOES_ENTITY_EXIST(SetPieceCarID[i])
REQUEST_MODEL(SetPieceCarModel[i])
IF HAS_MODEL_LOADED(SetPieceCarModel[i])
AND HAS_VEHICLE_RECORDING_BEEN_LOADED(SetPieceCarRecording[i], strUberName)
IF (fTriggerCarPlaybackTime >= (SetPieceCarStartime[i] - (fUberMinTimeBeforePlaybackStartToCreate * fPlaybackSpeed)))
IF bCreateAllWaitingCars
OR bForceCreateCars
OR (NOT bCreatedUberPlaybackEntityThisFrame AND NOT private_IS_POINT_VISIBLE_TO_PLAYER_POS(SetPieceCarPos[i], vPlayerPos, 5.0, fUberPlaybackMinCreationDistance))
//Create the car if the creation point isn't visible/obstructed or IF it's being forced to create.
IF (bCarsAreOn)
private_SAFE_CLEAR_AREA_OF_VEHICLES(SetPieceCarPos[i], vPlayerPos, fClearSurroundingCarsDistance)
ENDIF
SetPieceCarID[i] = CREATE_VEHICLE(SetPieceCarModel[i], SetPieceCarPos[i], DEFAULT, FALSE, FALSE)
IF SetPieceCarModel[i] = POLMAV
SET_VEHICLE_LIVERY(SetPieceCarID[i], 0)
ENDIF
IF block_vehicle_colour
AND NOT IS_BIT_SET(SetPieceCarFlags[i], TRAFFIC_FLAGS_VEH_IS_A_COP)
traffic_block_vehicle_colour_from_generating(SetPieceCarID[i])
ENDIF
IF IS_BIT_SET(SetPieceCarFlags[i], TRAFFIC_FLAGS_FREEZE_CAR_FOR_COLLISION)
SET_ENTITY_SHOULD_FREEZE_WAITING_ON_COLLISION(SetPieceCarID[i], TRUE)
ENDIF
#IF IS_DEBUG_BUILD
TEXT_LABEL_63 debugCarName = "SetPiece "
debugCarName += i
SET_VEHICLE_NAME_DEBUG(SetPieceCarID[i], debugCarName)
#ENDIF
SET_ENTITY_COORDS_NO_OFFSET(SetPieceCarID[i], SetPieceCarPos[i])
SET_ENTITY_QUATERNION(SetPieceCarID[i], SetPieceCarQuatX[i], SetPieceCarQuatY[i], SetPieceCarQuatZ[i], SetPieceCarQuatW[i])
IF IS_THIS_MODEL_A_CAR(SetPieceCarModel[i])
OR IS_THIS_MODEL_A_BIKE(SetPieceCarModel[i])
SET_VEHICLE_ON_GROUND_PROPERLY(SetPieceCarID[i])
ENDIF
IF NOT IS_BIT_SET(SetPieceCarFlags[i], TRAFFIC_FLAGS_VEH_IS_A_COP)
SET_VEHICLE_ENGINE_ON(SetPieceCarID[i], TRUE, TRUE)
IF GET_CLOCK_HOURS() > 19 OR GET_CLOCK_HOURS() < 7
SET_VEHICLE_LIGHTS(SetPieceCarID[i], SET_VEHICLE_LIGHTS_ON)
ENDIF
ENDIF
FREEZE_ENTITY_POSITION(SetPieceCarID[i], TRUE)
SET_MODEL_AS_NO_LONGER_NEEDED(SetPieceCarModel[i])
iSetpieceCarsWaitingToCreate--
SetPieceCarProgress[i]++
bCreatedUberPlaybackEntityThisFrame = TRUE
ENDIF
ENDIF
ENDIF
ELSE
//The vehicle already exists.
IF NOT IS_ENTITY_DEAD(SetPieceCarID[i]) AND IS_VEHICLE_DRIVEABLE(SetPieceCarID[i])
#IF IS_DEBUG_BUILD
TEXT_LABEL_63 debugCarName = "SetPiece "
debugCarName += i
SET_VEHICLE_NAME_DEBUG(SetPieceCarID[i], debugCarName)
#ENDIF
SET_ENTITY_COORDS_NO_OFFSET(SetPieceCarID[i], SetPieceCarPos[i])
SET_ENTITY_QUATERNION(SetPieceCarID[i], SetPieceCarQuatX[i], SetPieceCarQuatY[i], SetPieceCarQuatZ[i], SetPieceCarQuatW[i])
IF IS_THIS_MODEL_A_CAR(SetPieceCarModel[i])
OR IS_THIS_MODEL_A_BIKE(SetPieceCarModel[i])
SET_VEHICLE_ON_GROUND_PROPERLY(SetPieceCarID[i])
ENDIF
FREEZE_ENTITY_POSITION(SetPieceCarID[i], TRUE)
SET_MODEL_AS_NO_LONGER_NEEDED(SetPieceCarModel[i])
iSetpieceCarsWaitingToCreate--
SetPieceCarProgress[i]++
ENDIF
ENDIF
ENDIF
ELIF SetPieceCarProgress[i] = 2
REQUEST_VEHICLE_RECORDING(SetPieceCarRecording[i], strUberName)
IF NOT IS_BIT_SET(SetPieceCarFlags[i], TRAFFIC_FLAGS_DRIVER_HAS_BEEN_CREATED)
bFlag = FALSE
IF IS_BIT_SET(SetPieceCarFlags[i], TRAFFIC_FLAGS_VEH_IS_A_COP)
REQUEST_MODEL(COP_PED_MODEL())
bFlag = HAS_MODEL_LOADED(COP_PED_MODEL())
eModelToUse = UBER_PLAYBACK_PED_MODEL_COP
ELSE
IF NOT bTrafficForceDefaultPedModel
AND ((NOT IS_BIT_SET(SetPieceCarFlags[i], TRAFFIC_FLAGS_VEH_IS_A_BIKE) AND bCanCreateRandomDriver)
OR (IS_BIT_SET(SetPieceCarFlags[i], TRAFFIC_FLAGS_VEH_IS_A_BIKE) AND bCanCreateRandomBikeRider))
bFlag = TRUE
eModelToUse = UBER_PLAYBACK_PED_MODEL_AMBIENT
ELSE
REQUEST_MODEL(DEFAULT_PED_MODEL())
bFlag = HAS_MODEL_LOADED(DEFAULT_PED_MODEL())
eModelToUse = UBER_PLAYBACK_PED_MODEL_DEFAULT
ENDIF
ENDIF
//Peds now aren't created until playback starts, as a failsafe also create the ped if the player gets close to the vehicle.
IF NOT IS_ENTITY_DEAD(SetPieceCarID[i])
IF NOT bCreatedUberPlaybackEntityThisFrame
AND IS_VEHICLE_SEAT_FREE(SetPieceCarID[i])
IF bFlag
IF VDIST2(GET_ENTITY_COORDS(SetPieceCarID[i]), vPlayerPos) < 10000.0
OR bForceCreateCars
OR bCreateAllWaitingCars
private_CREATE_PED_INSIDE_UBER_PLAYBACK_CAR(SetPieceCarID[i], eModelToUse, TRUE)
SET_BIT(SetPieceCarFlags[i], TRAFFIC_FLAGS_DRIVER_HAS_BEEN_CREATED)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
IF IS_VEHICLE_DRIVEABLE(SetPieceCarID[i])
IF (fTriggerCarPlaybackTime >= SetPieceCarStartime[i])
IF MAX_NUMBER_OF_SET_PIECE_CARS_PLAYING_BACK > iCurrentNumberOfSetPieceCarPlaybacks
// work out skip time
fSkipTime = fTriggerCarPlaybackTime - SetPieceCarStartime[i]
fSkipTime *= SetPieceCarRecordingSpeed[i]
// check its not too late
IF HAS_VEHICLE_RECORDING_BEEN_LOADED(SetPieceCarRecording[i], strUberName)
IF fSkipTime < GET_TOTAL_DURATION_OF_VEHICLE_RECORDING(SetPieceCarRecording[i],strUberName)
// check we're not updating to a position on screen, from an offscreen position
pos = GET_ENTITY_COORDS(SetPieceCarID[i])
pos2 = GET_POSITION_OF_VEHICLE_RECORDING_AT_TIME(SetPieceCarRecording[i], fSkipTime,strUberName)
IF NOT private_IS_POINT_VISIBLE_TO_PLAYER_POS(pos, vPlayerPos, 5.0, fUberPlaybackMinCreationDistance)
AND private_IS_POINT_VISIBLE_TO_PLAYER_POS(pos2, vPlayerPos, 5.0, fUberPlaybackMinCreationDistance)
AND NOT (bCreateAllWaitingCars)
AND NOT bForceCreateCars
#IF IS_DEBUG_BUILD
IF (bTrafficDebugOn)
PRINTLN("traffic.sch - Couldn't start set-piece playback ", i, ": point is visible.")
ENDIF
#ENDIF
IF NOT IS_BIT_SET(SetPieceCarFlags[i], TRAFFIC_FLAGS_DRIVER_HAS_BEEN_CREATED)
private_CREATE_PED_INSIDE_UBER_PLAYBACK_CAR(SetPieceCarID[i], eModelToUse, TRUE)
ENDIF
iCurrentNumberOfSetPieceCarPlaybacks++ // increment this regardless
SetPieceCarProgress[i]++
ELSE
IF NOT bCreatedUberPlaybackEntityThisFrame
OR IS_BIT_SET(SetPieceCarFlags[i], TRAFFIC_FLAGS_DRIVER_HAS_BEEN_CREATED)
OR bCreateAllWaitingCars
OR bForceCreateCars
IF SET_CAR_AT_PLAYBACK_POSITION(SetPieceCarID[i], SetPieceCarRecording[i], fSkipTime, TRUE, FALSE, FALSE, allow_veh_to_stop_on_PLAYER_impact, allow_veh_to_stop_on_any_veh_impact)
SET_PLAYBACK_SPEED(SetPieceCarID[i], (fPlaybackSpeed * SetPieceCarRecordingSpeed[i]))
//SET_ENTITY_COLLISION(SetPieceCarID[i], TRUE)
#IF IS_DEBUG_BUILD
IF (bTrafficDebugOn)
PRINTLN("traffic.sch - Set-piece playback started ", i)
ENDIF
#ENDIF
IF IS_VEHICLE_DRIVEABLE(SetPieceCarID[i])
IF IS_BIT_SET(SetPieceCarFlags[i], TRAFFIC_FLAGS_VEH_IS_A_COP)
SET_VEHICLE_ENGINE_ON(SetPieceCarID[i], TRUE, TRUE)
SET_VEHICLE_SIREN(SetPieceCarID[i], TRUE)
SET_VEHICLE_LIGHTS(SetPieceCarID[i], FORCE_VEHICLE_LIGHTS_ON)
IF NOT IS_THIS_MODEL_A_BIKE(SetPieceCarModel[i])
SET_SIREN_WITH_NO_DRIVER(SetPieceCarID[i], TRUE)
ENDIF
ENDIF
ENDIF
#IF IS_DEBUG_BUILD
IF (bShowSetPiecePaths)
DISPLAY_PLAYBACK_RECORDED_VEHICLE(SetPieceCarID[i], RDM_WHOLELINE)
ELSE
DISPLAY_PLAYBACK_RECORDED_VEHICLE(SetPieceCarID[i], RDM_NONE)
ENDIF
#ENDIF // IS_DEBUG_BUILD
IF NOT IS_BIT_SET(SetPieceCarFlags[i], TRAFFIC_FLAGS_DRIVER_HAS_BEEN_CREATED)
private_CREATE_PED_INSIDE_UBER_PLAYBACK_CAR(SetPieceCarID[i], eModelToUse, TRUE)
ENDIF
iCurrentNumberOfSetPieceCarPlaybacks++
SetPieceCarProgress[i]++
ENDIF
ENDIF
ENDIF
ELSE
#IF IS_DEBUG_BUILD
IF (bTrafficDebugOn)
PRINTLN("traffic.sch - Couldn't start set-piece playback ", i, ": chase already passed the start time.")
ENDIF
#ENDIF
IF NOT IS_BIT_SET(SetPieceCarFlags[i], TRAFFIC_FLAGS_DRIVER_HAS_BEEN_CREATED)
private_CREATE_PED_INSIDE_UBER_PLAYBACK_CAR(SetPieceCarID[i], eModelToUse, TRUE)
ENDIF
iCurrentNumberOfSetPieceCarPlaybacks++ // increment this regardless
SetPieceCarProgress[i]++
ENDIF
ENDIF
ELSE
#IF IS_DEBUG_BUILD
IF (bTrafficDebugOn)
PRINTLN("traffic.sch - Couldn't start set-piece playback ", i, ": too many set-piece cars playing at once.")
ENDIF
#ENDIF
IF NOT IS_BIT_SET(SetPieceCarFlags[i], TRAFFIC_FLAGS_DRIVER_HAS_BEEN_CREATED)
private_CREATE_PED_INSIDE_UBER_PLAYBACK_CAR(SetPieceCarID[i], eModelToUse, TRUE)
ENDIF
iCurrentNumberOfSetPieceCarPlaybacks++ // increment this regardless
SetPieceCarProgress[i]++
ENDIF
ENDIF
ELSE
#IF IS_DEBUG_BUILD
IF (bTrafficDebugOn)
PRINTLN("traffic.sch - Couldn't start set-piece playback ", i, ": vehicle is not driveable.")
ENDIF
#ENDIF
IF NOT IS_BIT_SET(SetPieceCarFlags[i], TRAFFIC_FLAGS_DRIVER_HAS_BEEN_CREATED)
private_CREATE_PED_INSIDE_UBER_PLAYBACK_CAR(SetPieceCarID[i], eModelToUse, TRUE)
ENDIF
iCurrentNumberOfSetPieceCarPlaybacks++ // increment this regardless
SetPieceCarProgress[i]++
ENDIF
ELIF SetPieceCarProgress[i] = 3
IF IS_VEHICLE_DRIVEABLE(SetPieceCarID[i])
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(SetPieceCarID[i])
#IF IS_DEBUG_BUILD
IF (bShowSetPiecePaths)
DISPLAY_PLAYBACK_RECORDED_VEHICLE(SetPieceCarID[i], RDM_WHOLELINE)
ELSE
DISPLAY_PLAYBACK_RECORDED_VEHICLE(SetPieceCarID[i], RDM_NONE)
ENDIF
#ENDIF
temp_char = GET_PED_IN_VEHICLE_SEAT(SetPieceCarID[i])
IF NOT IS_PED_INJURED(temp_char)
#IF IS_DEBUG_BUILD
IF (bDrawSpeedVector)
DRAW_CAR_SPEED_VECTOR(SetPieceCarID[i])
ENDIF
#ENDIF
// switch to ai?
IF bPlayerAlive
IF NOT bSetPieceCarIsRecording
AND NOT bPausePlayback
AND NOT bSetPieceCarsDontSwitchToAI
AND ((NOT allow_veh_to_stop_on_PLAYER_impact AND NOT allow_veh_to_stop_on_any_veh_impact AND IS_ENTITY_TOUCHING_ENTITY(PLAYER_PED_ID(), SetPieceCarID[i]))
OR is_trailer_touching_entity(SetPieceCarID[i]))
//Old stuff for switching cars to AI.
IF DOES_ENTITY_EXIST(vehPlayersCar)
bFlag = FALSE
IF switch_SetPieceCar_to_ai_on_collision
#IF IS_DEBUG_BUILD
IF (bTrafficDebugOn)
PRINTLN("traffic.sch - Set Piece Car ", i, " switch_SetPieceCar_to_ai_on_collision = TRUE - switching to ai")
ENDIF
#ENDIF
bFlag = TRUE
ELSE
fTemp = GET_ENTITY_SPEED(vehPlayersCar)
IF fTemp < 1.0
#IF IS_DEBUG_BUILD
IF (bTrafficDebugOn)
PRINTLN("traffic.sch - Set Piece Car ", i, " hit players stationary car - switching to ai")
ENDIF
#ENDIF
bFlag = TRUE
ELIF ABSF(fTemp - GET_ENTITY_SPEED(SetPieceCarID[i])) > 15.0
#IF IS_DEBUG_BUILD
IF (bTrafficDebugOn)
PRINTLN("traffic.sch - Set Piece Car ", i, " and players car hit with different speeds - switching to ai")
ENDIF
#ENDIF
bFlag = TRUE
ELIF NOT ARE_CARS_TRAVELLING_IN_SAME_DIRECTION_BELOW_ANGLE(SetPieceCarID[i], vehPlayersCar, 45.0)
#IF IS_DEBUG_BUILD
IF (bTrafficDebugOn)
PRINTLN("traffic.sch - Set Piece Car ", i, " is not travelling in same direction - switching to ai")
ENDIF
#ENDIF
bFlag = TRUE
ELIF IS_CAR_IN_FRONT_OF_CAR(vehPlayersCar, SetPieceCarID[i])
#IF IS_DEBUG_BUILD
IF (bTrafficDebugOn)
PRINTLN("traffic.sch - Set Piece Car ", i, " is behind player - switching to ai")
ENDIF
#ENDIF
bFlag = TRUE
ENDIF
ENDIF
IF (bFlag)
CHANGE_PLAYBACK_TO_USE_AI_AND_KEEP_SPEED(SetPieceCarID[i])
SetPieceCarProgress[i]++
ENDIF
ENDIF
ELSE
SET_PLAYBACK_SPEED(SetPieceCarID[i], (fPlaybackSpeed * SetPieceCarRecordingSpeed[i]))
ENDIF
ENDIF
ELSE
#IF IS_DEBUG_BUILD
IF (bTrafficDebugOn)
IF DOES_ENTITY_EXIST(temp_char)
PRINTLN("traffic.sch - Set Piece Car ", i, " driver does not exist")
ELSE
PRINTLN("traffic.sch - Set Piece Car ", i, " driver is injured.")
ENDIF
ENDIF
#ENDIF
STOP_PLAYBACK_RECORDED_VEHICLE(SetPieceCarID[i])
ENDIF
ELSE
#IF IS_DEBUG_BUILD
IF (bTrafficDebugOn)
PRINTLN("traffic.sch - Set Piece Car ", i, " playback already stopped.")
ENDIF
#ENDIF
SetPieceCarProgress[i]++
ENDIF
ELSE
#IF IS_DEBUG_BUILD
IF (bTrafficDebugOn)
PRINTLN("traffic.sch - Set Piece Car ", i, " vehicle is not driveable")
ENDIF
#ENDIF
SetPieceCarProgress[i]++
ENDIF
ELIF SetPieceCarProgress[i] = 4
IF IS_VEHICLE_DRIVEABLE(SetPieceCarID[i])
IF NOT IS_PLAYBACK_GOING_ON_FOR_VEHICLE(SetPieceCarID[i])
SetPieceCarProgress[i]++
ELSE
temp_char = GET_PED_IN_VEHICLE_SEAT(SetPieceCarID[i])
IF NOT IS_PED_INJURED(temp_char)
SET_PLAYBACK_SPEED(SetPieceCarID[i], (fPlaybackSpeed * SetPieceCarRecordingSpeed[i]))
#IF IS_DEBUG_BUILD
IF (bShowSetPiecePaths)
DISPLAY_PLAYBACK_RECORDED_VEHICLE(SetPieceCarID[i], RDM_WHOLELINE)
ELSE
DISPLAY_PLAYBACK_RECORDED_VEHICLE(SetPieceCarID[i], RDM_NONE)
ENDIF
#ENDIF // IS_DEBUG_BUILD
ELSE
STOP_PLAYBACK_RECORDED_VEHICLE(SetPieceCarID[i])
ENDIF
// check if current time is after the finish time
IF HAS_VEHICLE_RECORDING_BEEN_LOADED(SetPieceCarRecording[i], strUberName)
IF (fTriggerCarPlaybackTime > (SetPieceCarStartime[i] + GET_TOTAL_DURATION_OF_VEHICLE_RECORDING(SetPieceCarRecording[i],strUberName)))
STOP_PLAYBACK_RECORDED_VEHICLE(SetPieceCarID[i])
ENDIF
ELSE
STOP_PLAYBACK_RECORDED_VEHICLE(SetPieceCarID[i])
ENDIF
ENDIF
ELSE
SetPieceCarProgress[i]++
ENDIF
ELIF SetPieceCarProgress[i] = 5
IF NOT (SetPieceCarID[i] = DontRemoveThisCar)
// set the cruise speed.
IF IS_VEHICLE_DRIVEABLE(SetPieceCarID[i])
temp_char = GET_PED_IN_VEHICLE_SEAT(SetPieceCarID[i])
IF NOT IS_PED_INJURED(temp_char)
SCRIPTTASKSTATUS TempTaskStatus
TempTaskStatus = GET_SCRIPT_TASK_STATUS(temp_char, SCRIPT_TASK_PERFORM_SEQUENCE)
IF (TempTaskStatus = FINISHED_TASK)
fTemp = GET_ENTITY_SPEED(SetPieceCarID[i])
IF (fTemp < MIN_CAR_CRUISE_SPEED)
fTemp = MIN_CAR_CRUISE_SPEED
ENDIF
IF (fTemp > MAX_CAR_CRUISE_SPEED)
fTemp = MAX_CAR_CRUISE_SPEED
ENDIF
SET_DRIVE_TASK_CRUISE_SPEED(temp_char, fTemp)
ENDIF
ENDIF
ENDIF
//Remove the vehicle recording
#IF IS_DEBUG_BUILD
IF NOT bStartSetPieceReRec
IF i <> iSetPieceReRecNum
IF NOT bSetPieceRecordingsAreActive AND NOT bTrafficDontCleanupRecordingFiles
IF SetPieceCarRecording[i] > 0
REMOVE_VEHICLE_RECORDING(SetPieceCarRecording[i], strUberName)
ENDIF
ENDIF
ENDIF
ENDIF
#ENDIF
#IF IS_FINAL_BUILD
IF NOT bSetPieceRecordingsAreActive AND NOT bTrafficDontCleanupRecordingFiles
IF SetPieceCarRecording[i] > 0
REMOVE_VEHICLE_RECORDING(SetPieceCarRecording[i], strUberName)
ENDIF
ENDIF
#ENDIF
IF NOT (bDeleteCarsWhenDone)
IF NOT bDontCleanUpUberCarsForTrailer
#IF IS_DEBUG_BUILD
IF NOT bStartSetPieceReRec
IF i <> iSetPieceReRecNum
//-- Added by Dave W
//-- If running debug mode, only clean up setpiece car rec if set piece re-recording isn't takeing place
//-- This is because the collision on the set-piece vehicle gets turned on when it gets cleaned up
//-- which can mess up the re-recording.
MARK_CAR_AS_NO_LONGER_NEEDED_KEEP_ID(SetPieceCarID[i])
ENDIF
ENDIF
#ENDIF
#IF IS_FINAL_BUILD
MARK_CAR_AS_NO_LONGER_NEEDED_KEEP_ID(SetPieceCarID[i])
#ENDIF
ENDIF
ELSE
IF DOES_ENTITY_EXIST(SetPieceCarID[i])
DELETE_VEHICLE(SetPieceCarID[i])
ENDIF
ENDIF
ENDIF
iCurrentNumberOfSetPieceCarPlaybacks--
SetPieceCarProgress[i] = 99
ENDIF
//If this is the first car we've reached that hasn't been removed from processing, mark it as the start point for the next frame.
IF NOT bFoundFirstCarToProcess
iFirstSetPieceCarToProcess = i
bFoundFirstCarToProcess = TRUE
ENDIF
ENDIF
//ENDSWITCH
#IF IS_DEBUG_BUILD
TEXT_LABEL str_index = ""
//Draws the array index for each traffic car above it
IF bShowSetPieceIndices
IF DOES_ENTITY_EXIST(SetPieceCarID[i])
str_index = i
DRAW_DEBUG_TEXT(str_index, GET_ENTITY_COORDS(SetPieceCarID[i], FALSE) + <<0.0, 0.0, 2.5>>)
ENDIF
ENDIF
IF bDrawSetpieceProgress
IF DOES_ENTITY_EXIST(SetPieceCarID[i])
str_index = SetPieceCarProgress[i]
DRAW_DEBUG_TEXT(str_index, GET_ENTITY_COORDS(SetPieceCarID[i], FALSE) + <<0.0, 0.0, 2.0>>)
ENDIF
ENDIF
#ENDIF
i++
ENDWHILE
ELSE
MARK_ALL_SET_PIECE_CARS_AS_NO_LONGER_NEEDED()
ENDIF
ENDPROC
PROC deactivate_SetPieceCars_up_to_time(INT deactivate_time)
INT i = 0
FOR i = 0 to TOTAL_NUMBER_OF_SET_PIECE_CARS - 1
IF SetPieceCarStartime[i] < deactivate_time
SetPieceCarProgress[i] = 99
ENDIF
ENDFOR
ENDPROC
#IF IS_DEBUG_BUILD
PROC INIT_UBER_RECORDING(STRING strNameOfUber)
MARK_ALL_TRAFFIC_CARS_AS_NO_LONGER_NEEDED()
MARK_ALL_PARKED_CARS_AS_NO_LONGER_NEEDED()
MARK_ALL_SET_PIECE_CARS_AS_NO_LONGER_NEEDED()
SET_WANTED_LEVEL_MULTIPLIER(0.0)
SET_WEATHER_TYPE_NOW_PERSIST("EXTRASUNNY")
//ALLOW_EMERGENCY_SERVICES(FALSE)
IF IS_PLAYER_PLAYING(PLAYER_ID())
CLEAR_PLAYER_WANTED_LEVEL(PLAYER_ID())
SET_DISPATCH_COPS_FOR_PLAYER(PLAYER_ID(), FALSE)
SET_CREATE_RANDOM_COPS(FALSE)
ENDIF
ADD_RELATIONSHIP_GROUP("rgh_traffic", rgh_traffic)
strUberName = strNameOfUber
SWITCH_ALL_RANDOM_CARS_ON()
ENDPROC
#ENDIF
#IF IS_DEBUG_BUILD
PROC UPDATE_UBER_RECORDING()
IF bDrawSpeedVector
OR bShowSetPieceIndices
OR bShowSetPiecePaths
OR bShowRecordingCone
OR bShowSetPieceReRecPath
OR bShowTrafficIndices
OR bShowTrafficCarPaths
OR bShowTriggerCarPath
OR bDrawTrafficProgress
OR bDrawSetpieceProgress
SET_DEBUG_LINES_AND_SPHERES_DRAWING_ACTIVE(TRUE)
ENDIF
SET_PED_DENSITY_MULTIPLIER_THIS_FRAME(0.0)
UPDATE_TRAFFIC_RECORDING()
ENDPROC
#ENDIF
PROC INITIALISE_UBER_PLAYBACK(STRING strNameOfUber, INT iTriggerCarNumber, BOOL bClearCars = TRUE, BOOL bDisableShops = TRUE)
VECTOR pos
strUberName = strNameOfUber
// set any initial flags
bCarsAreOn = TRUE
bRefreshAllCarsAfterSkippingCalled = FALSE
iCurrentNumberOfTrafficPlaybacks = 0
iCurrentNumberOfSetPieceCarPlaybacks = 0
iCurrentNumberOfParkedCars = 0
iTriggerCarRecordingNumber = iTriggerCarNumber
iFirstCarToProcess = 0
iFirstParkedCarToProcess = 0
iFirstSetpieceCarToProcess = 0
//iParkedCarsProcessedThisFrame = 0
iSwitchRoadsIndex = 0
iSwitchRoadsOnIndex = 0
iDontSwitchThisSetpieceRecordingToAI = -1
iDontSwitchThisSetpieceRecordingToAI2 = -1
iLastTrafficCarProcessedForCollisions = 0
iLastTrafficCarProcessedForCreation = 0
fTimeRoadsWereLastSwitchedOff = 0.0
fTimeRoadsWereLastSwitchedOn = 0.0
#IF IS_DEBUG_BUILD
iCurrentNumberOfTrafficRecordings = 0
iTotalNumberOfParkedCarsRecorded = 0
iTotalNumberOfTrafficCarsRecorded = 0
iSetPieceCarRecordingFile = 0
iCarsProcessedThisFrame = 0
iMainCarRecordingFile = 0
iInitialRecordingFileNumber = 1
#ENDIF
fTriggerCarPlaybackTime = 0.0
bCalculatePlaybackSpeedInitialised = FALSE
IF IS_PLAYER_PLAYING(PLAYER_ID())
pos = GET_ENTITY_COORDS(PLAYER_PED_ID())
vRoadsOffAtStartMin.x = pos.x - 100.0
vRoadsOffAtStartMin.y = pos.y - 100.0
vRoadsOffAtStartMin.z = pos.z - 100.0
vRoadsOffAtStartMax.x = pos.x + 100.0
vRoadsOffAtStartMax.y = pos.y + 100.0
vRoadsOffAtStartMax.z = pos.z + 100.0
SET_ROADS_IN_AREA(vRoadsOffAtStartMin, vRoadsOffAtStartMax, FALSE, FALSE)
IF (bClearCars)
CLEAR_AREA_OF_VEHICLES(pos, 500.0)
ENDIF
ENDIF
ADD_RELATIONSHIP_GROUP("rgh_traffic", rgh_traffic)
SWITCH_ALL_RANDOM_CARS_OFF()
#IF IS_DEBUG_BUILD
bAllRandomCarsAreSwitchedOn = FALSE
#ENDIF
IF bDisableShops
SET_ALL_SHOPS_TEMPORARILY_UNAVAILABLE(TRUE)
ENDIF
IF IS_PLAYER_PLAYING(PLAYER_ID())
SET_DISPATCH_COPS_FOR_PLAYER(PLAYER_ID(), FALSE)
SET_CREATE_RANDOM_COPS(FALSE)
ENDIF
FLUSH_ALL_TRAFFIC_DATA()
ENDPROC
PROC SWITCH_ALL_ROADS_BACK_TO_ORIGINAL()
SET_ROADS_BACK_TO_ORIGINAL(vRoadSwitchedOffMin, vRoadSwitchedOffMax)
SET_ROADS_BACK_TO_ORIGINAL(vRoadsOffAtStartMin, vRoadsOffAtStartMax)
ENDPROC
/// PURPOSE:
/// Cleans up all cars for the uber chase and resets ambient traffic.
/// NOTE: This command does nothing if uber playback was not initialised previously.
PROC CLEANUP_UBER_PLAYBACK(BOOL bDeleteAllCars = FALSE, BOOL bTurnShopsBackOn = TRUE)
IF NOT IS_STRING_NULL_OR_EMPTY(strUberName)
bCalculatePlaybackSpeedInitialised = FALSE
SWITCH_ALL_RANDOM_CARS_ON()
#IF IS_DEBUG_BUILD
bAllRandomCarsAreSwitchedOn = TRUE
#ENDIF
REMOVE_RELATIONSHIP_GROUP(rgh_traffic)
//SWITCH_ALL_ROADS_BACK_TO_ORIGINAL()
SET_ROADS_BACK_TO_ORIGINAL(<<-9999.0, -9999.0, -9999.0>>, <<9999.0, 9999.0, 9999.0>>)
IF IS_PLAYER_PLAYING(PLAYER_ID())
SET_AIR_DRAG_MULTIPLIER_FOR_PLAYERS_VEHICLE(PLAYER_ID(), 1.0)
SET_DISPATCH_COPS_FOR_PLAYER(PLAYER_ID(), TRUE)
SET_CREATE_RANDOM_COPS(TRUE)
ENDIF
IF bUberPlaybackRemoveDefaultPedModel
SET_MODEL_AS_NO_LONGER_NEEDED(DEFAULT_PED_MODEL())
ENDIF
SET_MODEL_AS_NO_LONGER_NEEDED(DEFAULT_CAR_MODEL())
SET_MODEL_AS_NO_LONGER_NEEDED(COP_CAR_MODEL())
SET_MODEL_AS_NO_LONGER_NEEDED(COP_PED_MODEL())
IF NOT IS_SCREEN_FADED_OUT()
AND NOT (bDeleteAllCars)
MARK_ALL_TRAFFIC_CARS_AS_NO_LONGER_NEEDED()
MARK_ALL_PARKED_CARS_AS_NO_LONGER_NEEDED()
MARK_ALL_SET_PIECE_CARS_AS_NO_LONGER_NEEDED()
ELSE
DELETE_ALL_CARS_IN_UBER_PLAYBACK()
FLUSH_ALL_TRAFFIC_DATA()
ENDIF
CDEBUG1LN(DEBUG_MISSION, "[traffic.sch] - CLEANUP_UBER_PLAYBACK called.")
IF bTurnShopsBackOn
SET_ALL_SHOPS_TEMPORARILY_UNAVAILABLE(FALSE)
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// New procedure for turning off roads during playback: one part switches off roads at two second intervals in front of the chase, one part switches
/// them back on after the chase has passed.
PROC private_SWITCH_ROADS_OFF_DURING_PLAYBACK(VEHICLE_INDEX vehTrigger, FLOAT fTime)
IF NOT IS_ENTITY_DEAD(vehTrigger)
AND IS_PLAYBACK_GOING_ON_FOR_VEHICLE(vehTrigger)
RECORDING_ID recID
FLOAT fNextSwitchOffTime = fTimeRoadsWereLastSwitchedOff + 2000.0
FLOAT fNextSwitchOnTime = fTimeRoadsWereLastSwitchedOn + 2000.0
FLOAT fTemp
BOOL bJustSwitchedRoadsOff = FALSE
//Switch roads off: go up to 25 seconds ahead of the current playback time.
IF fNextSwitchOffTime < fTime + 25000.0
recID = GET_CURRENT_PLAYBACK_FOR_VEHICLE(vehTrigger)
IF fNextSwitchOffTime <= GET_TOTAL_DURATION_OF_VEHICLE_RECORDING_ID(recID)
IF iSwitchRoadsIndex = 0
vSwitchRoadsTempMin = GET_POSITION_OF_VEHICLE_RECORDING_ID_AT_TIME(recID, fTimeRoadsWereLastSwitchedOff)
iSwitchRoadsIndex++
ELIF iSwitchRoadsIndex = 1
vSwitchRoadsTempMax = GET_POSITION_OF_VEHICLE_RECORDING_ID_AT_TIME(recID, fNextSwitchOffTime)
iSwitchRoadsIndex++
ELSE
IF NOT bCreatedUberPlaybackEntityThisFrame
IF vSwitchRoadsTempMin.x > vSwitchRoadsTempMax.x
fTemp = vSwitchRoadsTempMin.x
vSwitchRoadsTempMin.x = vSwitchRoadsTempMax.x
vSwitchRoadsTempMax.x = fTemp
ENDIF
IF vSwitchRoadsTempMin.y > vSwitchRoadsTempMax.y
fTemp = vSwitchRoadsTempMin.y
vSwitchRoadsTempMin.y = vSwitchRoadsTempMax.y
vSwitchRoadsTempMax.y = fTemp
ENDIF
IF vSwitchRoadsTempMin.z > vSwitchRoadsTempMax.z
fTemp = vSwitchRoadsTempMin.z
vSwitchRoadsTempMin.z = vSwitchRoadsTempMax.z
vSwitchRoadsTempMax.z = fTemp
ENDIF
vSwitchRoadsTempMin -= <<fSwitchOffRoadDist, fSwitchOffRoadDist, fSwitchOffRoadDist>>
vSwitchRoadsTempMax += <<fSwitchOffRoadDist, fSwitchOffRoadDist, fSwitchOffRoadDist>>
SET_ROADS_IN_AREA(vSwitchRoadsTempMin, vSwitchRoadsTempMax, FALSE, FALSE)
fTimeRoadsWereLastSwitchedOff = fNextSwitchOffTime
iSwitchRoadsIndex = 0
#IF IS_DEBUG_BUILD
IF bTrafficDebugOn
PRINTLN("traffic.sch - Switching off roads ", vSwitchRoadsTempMin, " ", vSwitchRoadsTempMax, " ", fNextSwitchOffTime)
ENDIF
#ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
//Switch roads on: wait a few seconds after the current chase time.
IF fNextSwitchOnTime < fTime - 8000.0
recID = GET_CURRENT_PLAYBACK_FOR_VEHICLE(vehTrigger)
IF iSwitchRoadsOnIndex = 0
vSwitchRoadsOnMin = GET_POSITION_OF_VEHICLE_RECORDING_ID_AT_TIME(recID, fTimeRoadsWereLastSwitchedOn)
iSwitchRoadsOnIndex++
ELIF iSwitchRoadsOnIndex = 1
vSwitchRoadsOnMax = GET_POSITION_OF_VEHICLE_RECORDING_ID_AT_TIME(recID, fNextSwitchOnTime)
iSwitchRoadsOnIndex++
ELSE
IF NOT bCreatedUberPlaybackEntityThisFrame
AND NOT bJustSwitchedRoadsOff
IF vSwitchRoadsOnMin.x > vSwitchRoadsOnMax.x
fTemp = vSwitchRoadsOnMin.x
vSwitchRoadsOnMin.x = vSwitchRoadsOnMax.x
vSwitchRoadsOnMax.x = fTemp
ENDIF
IF vSwitchRoadsOnMin.y > vSwitchRoadsOnMax.y
fTemp = vSwitchRoadsOnMin.y
vSwitchRoadsOnMin.y = vSwitchRoadsOnMax.y
vSwitchRoadsOnMax.y = fTemp
ENDIF
IF vSwitchRoadsOnMin.z > vSwitchRoadsOnMax.z
fTemp = vSwitchRoadsOnMin.z
vSwitchRoadsOnMin.z = vSwitchRoadsOnMax.z
vSwitchRoadsOnMax.z = fTemp
ENDIF
vSwitchRoadsOnMin -= <<fSwitchOffRoadDist, fSwitchOffRoadDist, fSwitchOffRoadDist>>
vSwitchRoadsOnMax += <<fSwitchOffRoadDist, fSwitchOffRoadDist, fSwitchOffRoadDist>>
SET_ROADS_BACK_TO_ORIGINAL(vSwitchRoadsOnMin, vSwitchRoadsOnMax)
fTimeRoadsWereLastSwitchedOn = fNextSwitchOnTime
#IF IS_DEBUG_BUILD
IF bTrafficDebugOn
PRINTLN("traffic.sch - Switching on roads ", vSwitchRoadsOnMin, " ", vSwitchRoadsOnMax, " ", fNextSwitchOnTime)
ENDIF
#ENDIF
iSwitchRoadsOnIndex = 0
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Private function for switching off roads around the uber chase route.
/// NOTE: new version of this PROC for bug 299051. Uses much less CPU time.
PROC SWITCH_ROADS_OFF_IN_PLAYBACK(VEHICLE_INDEX TriggerCar, FLOAT fTime)
RECORDING_ID recID
VECTOR pos
IF iSwitchRoadsIndex < 15
IF iSwitchRoadsIndex = 0
vSwitchRoadsTempMin = <<99999.9, 99999.9, 99999.9>>
vSwitchRoadsTempMax = <<-99999.9, -99999.9, -99999.9>>
ENDIF
IF IS_VEHICLE_DRIVEABLE(TriggerCar)
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(TriggerCar)
recID = GET_CURRENT_PLAYBACK_FOR_VEHICLE(TriggerCar)
pos = GET_POSITION_OF_VEHICLE_RECORDING_ID_AT_TIME(recID, fTime + (TO_FLOAT(iSwitchRoadsIndex - 1) * 2000))
// update current min, max values
IF (pos.x < vSwitchRoadsTempMin.x)
vSwitchRoadsTempMin.x = pos.x
ENDIF
IF (pos.y < vSwitchRoadsTempMin.y)
vSwitchRoadsTempMin.y = pos.y
ENDIF
IF (pos.z < vSwitchRoadsTempMin.z)
vSwitchRoadsTempMin.z = pos.z
ENDIF
IF (pos.x > vSwitchRoadsTempMax.x)
vSwitchRoadsTempMax.x = pos.x
ENDIF
IF (pos.y > vSwitchRoadsTempMax.y)
vSwitchRoadsTempMax.y = pos.y
ENDIF
IF (pos.z > vSwitchRoadsTempMax.z)
vSwitchRoadsTempMax.z = pos.z
ENDIF
ENDIF
ENDIF
iSwitchRoadsIndex++
ELSE
IF NOT bCreatedUberPlaybackEntityThisFrame
//Split this call from the next one, as it causes a large peak in usage.
SET_ROADS_BACK_TO_ORIGINAL(<<-9999.9, -9999.9, -9999.9>>, <<9999.9, 9999.9, 9999.9>>)
// add on safety
vSwitchRoadsTempMin += << (fSwitchOffRoadDist * -1.0), (fSwitchOffRoadDist * -1.0), (fSwitchOffRoadDist * -1.0)>>
vSwitchRoadsTempMax += << fSwitchOffRoadDist, fSwitchOffRoadDist, fSwitchOffRoadDist>>
vRoadSwitchedOffMin = vSwitchRoadsTempMin
vRoadSwitchedOffMax = vSwitchRoadsTempMax
SET_ROADS_IN_AREA(vRoadSwitchedOffMin, vRoadSwitchedOffMax, FALSE, FALSE)
iSwitchRoadsIndex = 0
// LINE(vRoadSwitchedOffMin.x, vRoadSwitchedOffMin.y, vRoadSwitchedOffMin.z, vRoadSwitchedOffMax.x, vRoadSwitchedOffMin.y, vRoadSwitchedOffMin.z)
// LINE(vRoadSwitchedOffMin.x, vRoadSwitchedOffMin.y, vRoadSwitchedOffMin.z, vRoadSwitchedOffMin.x, vRoadSwitchedOffMax.y, vRoadSwitchedOffMin.z)
// LINE(vRoadSwitchedOffMax.x, vRoadSwitchedOffMax.y, vRoadSwitchedOffMin.z, vRoadSwitchedOffMax.x, vRoadSwitchedOffMin.y, vRoadSwitchedOffMin.z)
// LINE(vRoadSwitchedOffMax.x, vRoadSwitchedOffMax.y, vRoadSwitchedOffMin.z, vRoadSwitchedOffMin.x, vRoadSwitchedOffMax.y, vRoadSwitchedOffMin.z)
//
// LINE(vRoadSwitchedOffMin.x, vRoadSwitchedOffMin.y, vRoadSwitchedOffMax.z, vRoadSwitchedOffMax.x, vRoadSwitchedOffMin.y, vRoadSwitchedOffMax.z)
// LINE(vRoadSwitchedOffMin.x, vRoadSwitchedOffMin.y, vRoadSwitchedOffMax.z, vRoadSwitchedOffMin.x, vRoadSwitchedOffMax.y, vRoadSwitchedOffMax.z)
// LINE(vRoadSwitchedOffMax.x, vRoadSwitchedOffMax.y, vRoadSwitchedOffMax.z, vRoadSwitchedOffMax.x, vRoadSwitchedOffMin.y, vRoadSwitchedOffMax.z)
// LINE(vRoadSwitchedOffMax.x, vRoadSwitchedOffMax.y, vRoadSwitchedOffMax.z, vRoadSwitchedOffMin.x, vRoadSwitchedOffMax.y, vRoadSwitchedOffMax.z)
//
// LINE(vRoadSwitchedOffMin.x, vRoadSwitchedOffMin.y, vRoadSwitchedOffMin.z, vRoadSwitchedOffMin.x, vRoadSwitchedOffMin.y, vRoadSwitchedOffMax.z)
// LINE(vRoadSwitchedOffMin.x, vRoadSwitchedOffMax.y, vRoadSwitchedOffMin.z, vRoadSwitchedOffMin.x, vRoadSwitchedOffMax.y, vRoadSwitchedOffMax.z)
// LINE(vRoadSwitchedOffMax.x, vRoadSwitchedOffMin.y, vRoadSwitchedOffMin.z, vRoadSwitchedOffMax.x, vRoadSwitchedOffMin.y, vRoadSwitchedOffMax.z)
// LINE(vRoadSwitchedOffMax.x, vRoadSwitchedOffMax.y, vRoadSwitchedOffMin.z, vRoadSwitchedOffMax.x, vRoadSwitchedOffMax.y, vRoadSwitchedOffMax.z)
//
// PRINTSTRING("vRoadSwitchedOffMin = ")
// PRINTFLOAT(vRoadSwitchedOffMin.x)
// PRINTSTRING(", ")
// PRINTFLOAT(vRoadSwitchedOffMin.y)
// PRINTSTRING(", ")
// PRINTFLOAT(vRoadSwitchedOffMin.z)
// PRINTSTRING(", vRoadSwitchedOffMax = ")
// PRINTFLOAT(vRoadSwitchedOffMax.x)
// PRINTSTRING(", ")
// PRINTFLOAT(vRoadSwitchedOffMax.y)
// PRINTSTRING(", ")
// PRINTFLOAT(vRoadSwitchedOffMax.z)
// PRINTSTRING("\n ")
ENDIF
ENDIF
ENDPROC
PROC SAFE_CLEAR_AREA_OF_CARS_IN_PLAYBACK(VEHICLE_INDEX TriggerCar, FLOAT fTime, FLOAT fRadius)
RECORDING_ID recID
VECTOR pos, pos2, vec, vPlayerPos
FLOAT fTemp
IF IS_PLAYER_PLAYING(PLAYER_ID())
vPlayerPos = GET_ENTITY_COORDS(PLAYER_PED_ID())
ENDIF
IF IS_VEHICLE_DRIVEABLE(TriggerCar)
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(TriggerCar)
recID = GET_CURRENT_PLAYBACK_FOR_VEHICLE(TriggerCar)
pos = GET_POSITION_OF_VEHICLE_RECORDING_ID_AT_TIME(recID, fTime)
pos2 = GET_ENTITY_COORDS(TriggerCar)
// make sure we don't clear the area behind the trigger car
vec = pos2 - pos
fTemp = VMAG(vec)
IF (fTemp > fRadius)
fTemp = fRadius
ENDIF
private_SAFE_CLEAR_AREA_OF_VEHICLES(pos, vPlayerPos, fTemp)
ENDIF
ENDIF
ENDPROC
FUNC BOOL HAS_UBER_PLAYBACK_BEEN_SKIPPED_TO_PLAYBACK_TIME(VEHICLE_INDEX &TriggerCar, FLOAT finResetTime)
IF NOT (bRefreshAllCarsAfterSkippingCalled)
bResetPlaybackToTime = TRUE
DELETE_ALL_CARS_IN_UBER_PLAYBACK()
IF IS_VEHICLE_DRIVEABLE(TriggerCar)
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(TriggerCar)
STOP_PLAYBACK_RECORDED_VEHICLE(TriggerCar)
SET_VEHICLE_FIXED(TriggerCar)
ENDIF
IF NOT (iTriggerCarRecordingNumber = -1)
WHILE NOT SET_CAR_AT_PLAYBACK_POSITION(TriggerCar, iTriggerCarRecordingNumber, finResetTime, TRUE, FALSE)
WAIT(0)
ENDWHILE
IF NOT (bReRecordingIsEnabled)
bPausePlayback = TRUE
fPausePlaybackTime = 0.0
iFirstCarToProcess = 0
iFirstSetpieceCarToProcess = 0
iFirstParkedCarToProcess = 0
iCurrentNumberOfTrafficPlaybacks = 0
iCurrentNumberOfSetPieceCarPlaybacks = 0
iCurrentNumberOfParkedCars = 0
iParkedCarsWaitingToCreate = 0
iSetPieceCarsWaitingToCreate = 0
iTrafficCarsWaitingToCreate = 0
ENDIF
ENDIF
ENDIF
bRefreshAllCarsAfterSkippingCalled = TRUE
ELSE
IF IS_VEHICLE_DRIVEABLE(TriggerCar)
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(TriggerCar)
SET_PLAYBACK_SPEED(TriggerCar, (1.0 * fMasterPlaybackSpeed * fPausePlaybackTime))
SET_CAR_AT_PLAYBACK_POSITION(TriggerCar, iTriggerCarRecordingNumber, finResetTime, TRUE, FALSE)
ENDIF
ENDIF
fTriggerCarPlaybackTime = finResetTime
//Reset the road switching variables
iSwitchRoadsIndex = 0
iSwitchRoadsOnIndex = 0
fTimeRoadsWereLastSwitchedOn = 0.0
fTimeRoadsWereLastSwitchedOff = 0.0
UPDATE_SET_PIECE_CARS(TriggerCar, (1.0 * fMasterPlaybackSpeed * fPausePlaybackTime), TRUE)
UPDATE_TRAFFIC_PLAYBACK(TriggerCar, (1.0 * fMasterPlaybackSpeed * fPausePlaybackTime), TRUE)
UPDATE_PARKED_CARS(TriggerCar)
IF (iParkedCarsWaitingToCreate = 0)
AND (iSetPieceCarsWaitingToCreate = 0)
AND (iTrafficCarsWaitingToCreate = 0)
bPausePlayback = FALSE
bResetPlaybackToTime = FALSE
bRefreshAllCarsAfterSkippingCalled = FALSE
RETURN(TRUE)
ENDIF
ENDIF
RETURN(FALSE)
ENDFUNC
PROC SET_UBER_PLAYBACK_TO_TIME_NOW(VEHICLE_INDEX TriggerCar, FLOAT finResetTime)
INT i
FLOAT fSkipTime
BOOL bDelete
IF IS_VEHICLE_DRIVEABLE(TriggerCar)
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(TriggerCar)
CREATE_ALL_WAITING_UBER_CARS()
// set main car back
SET_CAR_AT_PLAYBACK_POSITION(TriggerCar, iTriggerCarRecordingNumber, finResetTime, TRUE, FALSE, TRUE)
fTriggerCarPlaybackTime = finResetTime
// set any set pieces that are currently playing back to the reset time
REPEAT TOTAL_NUMBER_OF_SET_PIECE_CARS i
IF (SetPieceCarProgress[i] > 2)
AND (SetPieceCarProgress[i] < 6)
bDelete = FALSE
IF DOES_ENTITY_EXIST(SetPieceCarID[i])
IF NOT IS_ENTITY_DEAD(SetPieceCarID[i])
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(SetPieceCarID[i])
fSkipTime = finResetTime - SetPieceCarStartime[i]
fSkipTime *= SetPieceCarRecordingSpeed[i]
IF (fSkipTime >= 0.0)
IF (fSkipTime < GET_RECORDING_LENGTH(SetPieceCarRecording[i]))
SET_CAR_AT_PLAYBACK_POSITION(SetPieceCarID[i], SetPieceCarRecording[i], fSkipTime, TRUE, FALSE, TRUE, allow_veh_to_stop_on_PLAYER_impact, allow_veh_to_stop_on_any_veh_impact)
ELSE
bDelete = TRUE
ENDIF
ELSE
bDelete = TRUE
ENDIF
ELSE
bDelete = TRUE
ENDIF
ELSE
bDelete = TRUE
ENDIF
ELSE
bDelete = TRUE
ENDIF
IF (bDelete)
SetPieceCarProgress[i] = 99
iCurrentNumberOfSetPieceCarPlaybacks--
ENDIF
ENDIF
ENDREPEAT
// set any traffic cars that are currently playing back to the reset time
REPEAT TOTAL_NUMBER_OF_TRAFFIC_CARS i
IF (TrafficCarProgress[i] > 2)
AND (TrafficCarProgress[i] < 6)
bDelete = FALSE
IF DOES_ENTITY_EXIST(TrafficCarID[i])
IF NOT IS_ENTITY_DEAD(TrafficCarID[i])
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(TrafficCarID[i])
fSkipTime = finResetTime - TrafficCarStartime[i]
IF (fSkipTime >= 0.0)
IF (fSkipTime < GET_RECORDING_LENGTH(TrafficCarRecording[i]))
SET_CAR_AT_PLAYBACK_POSITION(TrafficCarID[i], TrafficCarRecording[i], fSkipTime, TRUE, FALSE, TRUE, TRUE, allow_veh_to_stop_on_any_veh_impact)
ELSE
bDelete = TRUE
ENDIF
ELSE
bDelete = TRUE
ENDIF
ELSE
bDelete = TRUE
ENDIF
ELSE
bDelete = TRUE
ENDIF
ELSE
bDelete = TRUE
ENDIF
IF (bDelete)
TrafficCarProgress[i] = 99
iCurrentNumberOfTrafficPlaybacks--
ENDIF
ENDIF
ENDREPEAT
// reset first traffic car to process
iFirstCarToProcess = 0
iFirstSetpieceCarToProcess = 0
// recreate any parked cars
REPEAT TOTAL_NUMBER_OF_PARKED_CARS i
IF (ParkedCarProgress[i] > 2)
IF DOES_ENTITY_EXIST(ParkedCarID[i])
IF NOT IS_ENTITY_DEAD(ParkedCarID[i])
SET_ENTITY_AS_MISSION_ENTITY(ParkedCarID[i])
iCurrentNumberOfParkedCars++
ParkedCarProgress[i] = 2
ENDIF
ELSE
ParkedCarProgress[i] = 0
ENDIF
ENDIF
ENDREPEAT
iFirstParkedCarToProcess = 0
//Set the road switching variables to start from the new time
iSwitchRoadsIndex = 0
iSwitchRoadsOnIndex = 0
fTimeRoadsWereLastSwitchedOn = finResetTime
fTimeRoadsWereLastSwitchedOff = finResetTime
VECTOR vTriggerPos = GET_ENTITY_COORDS(TriggerCar)
vRoadsOffAtStartMin = vTriggerPos - <<100.0, 100.0, 100.0>>
vRoadsOffAtStartMax = vTriggerPos + <<100.0, 100.0, 100.0>>
SET_ROADS_IN_AREA(vRoadsOffAtStartMin, vRoadsOffAtStartMax, FALSE, FALSE)
ENDIF
ENDIF
ENDPROC
PROC UPDATE_UBER_PLAYBACK(VEHICLE_INDEX TriggerCar, FLOAT fPlaybackSpeed)
//PRINTSTRING("update uber playback called! \n")
#IF IS_DEBUG_BUILD
PED_INDEX temp_char
IF bDrawSpeedVector
OR bShowSetPieceIndices
OR bShowSetPiecePaths
OR bShowRecordingCone
OR bShowSetPieceReRecPath
OR bShowTrafficIndices
OR bShowTrafficCarPaths
OR bShowTriggerCarPath
OR bDrawTrafficProgress
OR bDrawSetpieceProgress
SET_DEBUG_LINES_AND_SPHERES_DRAWING_ACTIVE(TRUE)
ENDIF
#ENDIF
FLOAT fTemp
VECTOR pos
// VECTOR pos2, vec
BOOL bFlag
fTemp = GET_FRAME_TIME()
// update timers
fTemp *= 1000.0
#IF IS_DEBUG_BUILD
CREATE_TRAFFIC_WIDGET()
// for outputing to the widget
fInputPlaybackSpeed = fPlaybackSpeed
#ENDIF
//Output current vehicle as a parked car to temp_debug
#IF IS_DEBUG_BUILD
IF bOutputParkedCarInfo
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
VEHICLE_INDEX veh = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())
OUTPUT_PARKED_CAR_DATA(veh)
ENDIF
bOutputParkedCarInfo = FALSE
ENDIF
#ENDIF
bCreatedUberPlaybackEntityThisFrame = FALSE
// environment setting for doing set piece recordings
IF NOT (bSetPieceRecordingsHaveBeenActivated)
IF (bSetPieceRecordingsAreActive)
SWITCH_ALL_RANDOM_CARS_OFF()
#IF IS_DEBUG_BUILD
bAllRandomCarsAreSwitchedOn = FALSE
#ENDIF
IF IS_PLAYER_PLAYING(PLAYER_ID())
pos = GET_ENTITY_COORDS(PLAYER_PED_ID())
CLEAR_AREA(pos, 1000.0, TRUE)
ENDIF
bSetPieceRecordingsHaveBeenActivated = TRUE
ENDIF
ELSE
IF NOT (bSetPieceRecordingsAreActive)
SWITCH_ALL_RANDOM_CARS_ON()
#IF IS_DEBUG_BUILD
bAllRandomCarsAreSwitchedOn = TRUE
#ENDIF
bSetPieceRecordingsHaveBeenActivated = FALSE
ENDIF
ENDIF
IF (bSetPieceRecordingsAreActive)
fPlaybackSpeed = 1.0
SET_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME(0.0)
ENDIF
IF NOT (bReRecordingControlHijacked)
// PAUSE AND UNPAUSE THE UBER PLAYBACK
IF (bPausePlayback)
fPausePlaybackTime = 0.0
ELSE
fPausePlaybackTime = 1.0
ENDIF
// UPDATE TRIGGER CAR PLAYBACK
IF IS_VEHICLE_DRIVEABLE(TriggerCar)
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(TriggerCar)
// check if player is ahead of trigger car
IF IS_PLAYER_PLAYING(PLAYER_ID())
IF IS_PED_IN_FRONT_OF_CAR(PLAYER_PED_ID(), TriggerCar)
bPlayerIsAheadOfChase = TRUE
ELSE
bPlayerIsAheadOfChase = FALSE
ENDIF
ENDIF
fTriggerCarPlaybackTime = GET_TIME_POSITION_IN_RECORDING(TriggerCar)
SET_PLAYBACK_SPEED(TriggerCar, (fPlaybackSpeed * fMasterPlaybackSpeed * fPausePlaybackTime))
#IF IS_DEBUG_BUILD
IF (bShowTriggerCarPath)
DISPLAY_PLAYBACK_RECORDED_VEHICLE(TriggerCar, RDM_WHOLELINE)
ELSE
DISPLAY_PLAYBACK_RECORDED_VEHICLE(TriggerCar, RDM_NONE)
ENDIF
#ENDIF // IS_DEBUG_BUILD
IF (bCarsAreOn)
// switch roads off up ahead
//SWITCH_ROADS_OFF_IN_PLAYBACK(TriggerCar, fTriggerCarPlaybackTime)
private_SWITCH_ROADS_OFF_DURING_PLAYBACK(TriggerCar, fTriggerCarPlaybackTime)
UPDATE_CAR_DENSITY_BASED_ON_PLAYERS_DISTANCE_FROM_CAR(TriggerCar, fUberPlaybackDensitySwitchOffRange)
// clear the next few seconds of random traffic (only do every second)
IF (fClearCarTimer > 1000.0)
IF iUberClearCarsIndex = 0
UPDATE_CAR_POPULATION_BUDGET_BASED_ON_PLAYERS_DISTANCE_FROM_CAR(TriggerCar, fUberPlaybackDensitySwitchOffRange)
ENDIF
fTemp = fTriggerCarPlaybackTime + 4000.0 + (TO_FLOAT(iUberClearCarsIndex) * 2000.0)
SAFE_CLEAR_AREA_OF_CARS_IN_PLAYBACK(TriggerCar, fTemp, fClearSurroundingCarsDistance)
iUberClearCarsIndex++
IF iUberClearCarsIndex > 2
fClearCarTimer = 0.0
ENDIF
ELSE
iUberClearCarsIndex = 0
fClearCarTimer += (GET_FRAME_TIME() * 1000.0)
ENDIF
ENDIF
ENDIF
ENDIF
// only call the update functions if...
bFlag = FALSE
IF IS_VEHICLE_DRIVEABLE(TriggerCar)
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(TriggerCar)
bFlag = TRUE
ENDIF
ENDIF
IF (fTriggerCarPlaybackTime = 0)
OR IS_SCREEN_FADED_OUT()
bFlag = TRUE
ENDIF
IF (bFlag)
AND NOT (bDontUpdateUberCars)
// TRAFFIC
IF NOT (bResetPlaybackToTime)
UPDATE_TRAFFIC_PLAYBACK(TriggerCar, (fPlaybackSpeed * fMasterPlaybackSpeed * fPausePlaybackTime))
IF NOT bDontProcessTrafficHornsAndLights
//NOTE: This variable is obsolete but still being used in some missions for V, should be removed in a future project.
ENDIF
bDontProcessTrafficHornsAndLights = FALSE //Ensure command is called every frame
ENDIF
// PARKED CARS
IF (bShowParkedCars)
UPDATE_PARKED_CARS(TriggerCar)
ENDIF
// SET PIECE CARS
IF NOT (bResetPlaybackToTime)
UPDATE_SET_PIECE_CARS(TriggerCar, (fPlaybackSpeed * fMasterPlaybackSpeed * fPausePlaybackTime))
ENDIF
ENDIF
// START RECORDING A NEW SET PIECE CAR
#IF IS_DEBUG_BUILD
// if set piece has been reset, then make sure the current recording stops.
IF (bResetSetPiece)
CDEBUG1LN(DEBUG_MISSION, "[traffic.sch] - Stopped set-piece recording, set-piece has been reset.")
bStartRecordingSetPieceCar = FALSE
ENDIF
IF (bStartRecordingSetPieceCar)
IF (bPausePlayback)
bPausePlayback = FALSE
ENDIF
IF NOT (bSetPieceCarIsRecording)
IF IS_PLAYER_PLAYING(PLAYER_ID())
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
MainRecordingCar = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())
IF NOT IS_ENTITY_DEAD(MainRecordingCar)
CDEBUG1LN(DEBUG_MISSION, "[traffic.sch] - Set-piece recording started.")
// PRINT_NOW("STARTED", 5000, 1)
PRINT_NOW("CRECSTART5", 5000, 1)
START_RECORDING_SET_PIECE_CAR(MainRecordingCar, TriggerCar, bAllowSetPieceRecOverwrite)
bSetPieceCarIsRecording = TRUE
ELSE
CDEBUG1LN(DEBUG_MISSION, "[traffic.sch] - Stopped set-piece recording, current vehicle is dead.")
bStartRecordingSetPieceCar = FALSE
ENDIF
ELSE
CDEBUG1LN(DEBUG_MISSION, "[traffic.sch] - Stopped set-piece recording, player is not in a vehicle.")
bStartRecordingSetPieceCar = FALSE
ENDIF
ELSE
CDEBUG1LN(DEBUG_MISSION, "[traffic.sch] - Stopped set-piece recording, player is not playing.")
bStartRecordingSetPieceCar = FALSE
ENDIF
ELSE
// check if got out car
IF IS_PLAYER_PLAYING(PLAYER_ID())
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
MainRecordingCar = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())
IF IS_ENTITY_DEAD(MainRecordingCar)
CDEBUG1LN(DEBUG_MISSION, "[traffic.sch] - Stopped set-piece recording, current vehicle is dead.")
bStartRecordingSetPieceCar = FALSE
ENDIF
ELSE
CDEBUG1LN(DEBUG_MISSION, "[traffic.sch] - Stopped set-piece recording, player is not in a vehicle.")
bStartRecordingSetPieceCar = FALSE
ENDIF
ELSE
CDEBUG1LN(DEBUG_MISSION, "[traffic.sch] - Stopped set-piece recording, player is not playing.")
bStartRecordingSetPieceCar = FALSE
ENDIF
ENDIF
bSetPieceRecordingsAreActive = TRUE
ELSE
IF (bSetPieceCarIsRecording)
IF IS_VEHICLE_DRIVEABLE(MainRecordingCar)
IF IS_RECORDING_GOING_ON_FOR_VEHICLE(MainRecordingCar)
STOP_RECORDING_VEHICLE(MainRecordingCar)
PRINT_NOW("CRECSTOP5", 5000, 1)
// PRINT_NOW("STOPPED", 5000, 1)
ENDIF
ENDIF
bPausePlayback = TRUE
fPausePlaybackTime = 0.0
bSetPieceCarIsRecording = FALSE
bStartRecordingSetPieceCar = FALSE
ENDIF
ENDIF
#ENDIF
// REGRAB THE SETPIECE CARS START POSITION AND COORDS
IF (bReGrabSetPiecePositionAndQuat)
IF IS_PLAYER_PLAYING(PLAYER_ID())
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
MainRecordingCar = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())
RecordedSetPieceCarPos = GET_ENTITY_COORDS(MainRecordingCar)
GET_ENTITY_QUATERNION(MainRecordingCar, fSetPieceQuatX, fSetPieceQuatY, fSetPieceQuatZ, fSetPieceQuatW)
ENDIF
ENDIF
bReGrabSetPiecePositionAndQuat = FALSE
ENDIF
// RERECORDING - If switched on
#IF IS_DEBUG_BUILD
IF (bEnableReRecording)
IF NOT (bReRecordingIsEnabled)
IF IS_VEHICLE_DRIVEABLE(TriggerCar)
temp_char = GET_PED_IN_VEHICLE_SEAT(TriggerCar)
IF NOT (temp_char = PLAYER_PED_ID())
DELETE_PED(temp_char)
ENDIF
IF IS_PLAYER_PLAYING(PLAYER_ID())
IF NOT IS_PED_IN_VEHICLE(PLAYER_PED_ID(), TriggerCar)
CLEAR_PED_TASKS_IMMEDIATELY(PLAYER_PED_ID())
SET_PED_INTO_VEHICLE(PLAYER_PED_ID(), TriggerCar)
//SET_GAMEPLAY_CAM_RELATIVE_HEADING(GET_ENTITY_HEADING(PLAYER_PED_ID()))
ENDIF
ENDIF
ENDIF
fResetTime = 0.0
bResetPlaybackToTime = TRUE
bReRecordingIsEnabled = TRUE
bStartRecordingPlayersCarWithTraffic = TRUE
ENDIF
ENDIF
#ENDIF
// RESET THE SET PEICE CAR
IF (bResetSetPiece)
IF DOES_ENTITY_EXIST(MainRecordingCar)
MARK_CAR_AS_NO_LONGER_NEEDED_KEEP_ID(SetPieceRecordingCar)
SetPieceRecordingCar = MainRecordingCar
ENDIF
IF IS_VEHICLE_DRIVEABLE(SetPieceRecordingCar)
SET_ENTITY_COORDS(SetPieceRecordingCar, RecordedSetPieceCarPos)
SET_ENTITY_QUATERNION(SetPieceRecordingCar, fSetPieceQuatX, fSetPieceQuatY, fSetPieceQuatZ, fSetPieceQuatW)
ENDIF
fResetTime = fNewSetPieceTriggerTime
bResetPlaybackToTime = TRUE
bResetSetPiece = FALSE
ENDIF
#IF IS_DEBUG_BUILD
//-- Set-piece re-recording controls - Added by Dave W
PED_INDEX pedTemp
IF bReRecSetPieceDataLoaded
//-- Get in here if bLoadSetPieceDataForReRec has been set
//-- Start re-record.
IF bStartSetPieceReRec
IF NOT IS_ENTITY_DEAD(SetPieceCarID[iSetPieceReRecNum])
IF NOT IS_ENTITY_DEAD(vehForSetPieceReRec)
IF fPausePlaybackTime = 1.0 //-- Requeired to get old/new recordings to sync.
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(vehForSetPieceReRec)
UNPAUSE_PLAYBACK_RECORDED_VEHICLE(vehForSetPieceReRec)
ENDIF
ENDIF
bAllowSetPieceRecOverwrite = TRUE
bStartRecordingSetPieceCar = TRUE
bDeleteCarsWhenDone = FALSE
ENDIF
ENDIF
ELSE
bStartRecordingSetPieceCar = FALSE
ENDIF
//-- Start re-record if R2 is pressed
IF bStartReRecOnButtonPress
IF NOT IS_ENTITY_DEAD(vehForSetPieceReRec)
IF IS_BUTTON_PRESSED(PAD1, RIGHTSHOULDER2)
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(vehForSetPieceReRec)
STOP_PLAYBACK_RECORDED_vehicle(vehForSetPieceReRec)
ENDIF
bStartSetPieceReRec = TRUE
ENDIF
ENDIF
ENDIF
//--Stop recording if square is pressed
IF bStopSetPieceReRecOnButtonPress
IF NOT IS_ENTITY_DEAD(vehForSetPieceReRec)
IF IS_CONTROL_PRESSED(player_control, input_jump)
bStartSetPieceReRec = FALSE
bStartRecordingSetPieceCar = FALSE
ENDIF
ENDIF
ENDIF
IF NOT IS_ENTITY_DEAD(SetPieceCarID[iSetPieceReRecNum])
//--Show ghost car
SET_ENTITY_VISIBLE(SetPieceCarID[iSetPieceReRecNum], bShowSetPieceReRecGhost)
pedTemp = GET_PED_IN_VEHICLE_SEAT(SetPieceCarID[iSetPieceReRecNum])
IF pedTemp <> NULL
SET_ENTITY_VISIBLE(pedTemp, bShowSetPieceReRecGhost)
ENDIF
//--Show car rec route
IF IS_PLAYBACK_GOING_ON_FOR_vehicle(SetPieceCarID[iSetPieceReRecNum])
IF (bShowSetPieceReRecPath)
DISPLAY_PLAYBACK_RECORDED_vehicle(SetPieceCarID[iSetPieceReRecNum], RDM_WHOLELINE)
ELSE
DISPLAY_PLAYBACK_RECORDED_vehicle(SetPieceCarID[iSetPieceReRecNum], RDM_NONE)
ENDIF
ENDIF
ENDIF
ENDIF
IF bLoadSetPieceDataForReRec
IF SetPieceCarRecording[iSetPieceReRecNum] > 0
bStartSetPieceReRec = FALSE
WHILE NOT HAS_UBER_PLAYBACK_BEEN_SKIPPED_TO_PLAYBACK_TIME(TriggerCar, SetPieceCarStartime[iSetPieceReRecNum])
WAIT(0)
ENDWHILE
bPausePlayback = TRUE
IF NOT IS_ENTITY_DEAD(SetPieceCarID[iSetPieceReRecNum])
SET_ENTITY_COLLISION(SetPieceCarID[iSetPieceReRecNum], FALSE)
pedTemp = GET_PED_IN_VEHICLE_SEAT(SetPieceCarID[iSetPieceReRecNum])
IF pedTemp <> NULL
SET_ENTITY_COLLISION(pedTemp, FALSE)
SET_ENTITY_VISIBLE(pedTemp, FALSE)
ENDIF
SET_ENTITY_VISIBLE(SetPieceCarID[iSetPieceReRecNum], FALSE)
IF IS_PLAYER_PLAYING(PLAYER_ID())
CLEAR_ped_TASKS_IMMEDIATELY(PLAYER_ped_ID())
ENDIF
IF DOES_ENTITY_EXIST(vehForSetPieceReRec)
SET_VEHICLE_AS_NO_LONGER_NEEDED(vehForSetPieceReRec)
ENDIF
VECTOR vPos = GET_POSITION_OF_vehicle_RECORDING_AT_TIME(SetPieceCarRecording[iSetPieceReRecNum], 0.0, strUberName)
CLEAR_AREA(vPos, 5.0, TRUE)
vehForSetPieceReRec = CREATE_VEHICLE(SetPieceCarModel[iSetPieceReRecNum], vPos, DEFAULT, FALSE, FALSE)
SET_PED_INTO_VEHICLE(PLAYER_PED_ID(), vehForSetPieceReRec)
START_PLAYBACK_RECORDED_VEHICLE(vehForSetPieceReRec, SetPieceCarRecording[iSetPieceReRecNum], strUberName)
PAUSE_PLAYBACK_RECORDED_VEHICLE(vehForSetPieceReRec)
ELSE
SCRIPT_ASSERT("Set piece vehicle is dead!")
ENDIF
bLoadSetPieceDataForReRec = FALSE
bReRecSetPieceDataLoaded = TRUE
ELSE
SCRIPT_ASSERT("Setpiece re-recorder: Invalid setpiece array index!")
ENDIF
ENDIF
#ENDIF
// RESET TO A SPECIFIC TIME IN THE RECORDING
IF (bResetPlaybackToTime)
WHILE NOT HAS_UBER_PLAYBACK_BEEN_SKIPPED_TO_PLAYBACK_TIME(TriggerCar, fResetTime)
WAIT(0)
ENDWHILE
bPausePlayback = TRUE
ENDIF
// RERECORDING - start the rerecording
#IF IS_DEBUG_BUILD
IF (bReRecordingIsEnabled)
IF IS_BUTTON_PRESSED(PAD1, CROSS)
IF IS_VEHICLE_DRIVEABLE(TriggerCar)
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(TriggerCar)
STOP_PLAYBACK_RECORDED_VEHICLE(TriggerCar)
ENDIF
ENDIF
INIT_UBER_RECORDING(strUberName)
PRINT_NOW("HIJACKED", 5000, 1)
bReRecordingControlHijacked = TRUE
ENDIF
UPDATE_UBER_RECORDING()
ENDIF
#ENDIF
IF (bCreateAllWaitingCars)
bCreateAllWaitingCars = FALSE
ENDIF
ELSE
#IF IS_DEBUG_BUILD
UPDATE_UBER_RECORDING()
#ENDIF
ENDIF
// output clean data
#IF IS_DEBUG_BUILD
IF (bOutputCleanedData)
OUTPUT_CLEANED_DATA()
bOutputCleanedData = FALSE
ENDIF
#ENDIF
ENDPROC