903 lines
30 KiB
Scheme
Executable File
903 lines
30 KiB
Scheme
Executable File
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
//
|
|
// SCRIPT NAME : TRI_Racer.sch
|
|
// AUTHOR : Nicholas Zippmann
|
|
// DESCRIPTION : Single Player Races - Racer procs/functions file
|
|
//
|
|
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
|
|
USING "TRI_Head.sch"
|
|
USING "TRI_Helpers.sch"
|
|
USING "TRI_Gate.sch"
|
|
USING "chase_hint_cam.sch"
|
|
USING "stunt_plane_public.sch"
|
|
|
|
// -----------------------------------
|
|
// SETUP PROCS/FUNCTIONS
|
|
// -----------------------------------
|
|
|
|
// bits for dialogue
|
|
|
|
// tracks how many consecutive gates weve hit
|
|
ENUM GateStuntBits
|
|
Missed_Once = BIT0,
|
|
Missed_Twice = BIT1,
|
|
Missed_Third = BIT2,
|
|
Hit_Once = BIT3,
|
|
Hit_Twice = BIT4,
|
|
Hit_Third = BIT5,
|
|
Knife_Once = BIT6,
|
|
Knife_Twice = BIT7,
|
|
Knife_Third = BIT8,
|
|
Inverted_Once = BIT9,
|
|
Inverted_Twice = BIT10,
|
|
Inverted_Third = BIT11,
|
|
Perfect_Once = BIT12,
|
|
Perfect_Twice = BIT13,
|
|
Perfect_Third = BIT14,
|
|
P_Inverted_Once = BIT15,
|
|
P_Inverted_Twice = BIT16,
|
|
P_Inverted_Third = BIT17,
|
|
P_Knife_Once = BIT18,
|
|
P_Knife_Twice = BIT19,
|
|
P_Knife_Third = BIT20
|
|
ENDENUM
|
|
|
|
#IF NOT DEFINED(OFFROAD_RACE_VEHICLE_CHECK)
|
|
FUNC INT OFFROAD_RACE_VEHICLE_CHECK(TRI_RACER_STRUCT& Racer, INT& iMesaTop)
|
|
DEBUG_MESSAGE("Printing stuff inside of empty OFFROAD_RACE_VEHICLE_CHECK")
|
|
iMesaTop = -1
|
|
PRINTFLOAT(Racer.fClockTime)
|
|
PRINTNL()
|
|
RETURN -1
|
|
ENDFUNC
|
|
#ENDIF
|
|
|
|
#IF NOT DEFINED(UnfreezePlayerVehicle)
|
|
PROC UnfreezePlayerVehicle()
|
|
DEBUG_MESSAGE("Printing stuff inside of empty UnfreezePlayerVehicle")
|
|
ENDPROC
|
|
#ENDIF
|
|
|
|
#IF NOT DEFINED(Play_Gate_Audio)
|
|
PROC Play_Gate_Audio(STRING sLine, INT iBitmaskInt)
|
|
PRINTINT(iBitmaskInt)
|
|
PRINTNL()
|
|
PRINTSTRING(sLine)
|
|
PRINTNL()
|
|
ENDPROC
|
|
#ENDIF
|
|
|
|
PROC TRI_Racer_Init(TRI_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("TRI_Racer_Init")
|
|
Racer.szName = "Racer"
|
|
Racer.Driver = NULL
|
|
Racer.Vehicle = NULL
|
|
Racer.Blip = NULL
|
|
Racer.iGateCur = -1
|
|
Racer.iRank = 0
|
|
Racer.fClockTime = 0.0
|
|
Racer.fPlsMnsLst = 0.0
|
|
Racer.fPlsMnsTot = 0.0
|
|
Racer.eReset = TRI_RACER_RESET_WAIT
|
|
Racer.vStartPos = TRI_Master.vDefRcrPos
|
|
Racer.fStartHead = TRI_Master.fDefRcrHead
|
|
Racer.eDriverType = TRI_Master.eDefDrvType
|
|
Racer.eDriverModel = TRI_Master.eDefDrvModel
|
|
Racer.eVehicleModel = TRI_Master.eDefVehModel
|
|
ENDPROC
|
|
|
|
PROC TRI_Racer_Setup_Misc(TRI_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("TRI_Racer_Setup_Misc")
|
|
Racer.Blip = NULL
|
|
Racer.iGateCur = -1
|
|
Racer.iRank = 0
|
|
Racer.fClockTime = 0.0
|
|
Racer.eReset = TRI_RACER_RESET_WAIT
|
|
ENDPROC
|
|
|
|
PROC TRI_Racer_Setup_Name(TRI_RACER_STRUCT& Racer, STRING sName)
|
|
//DEBUG_MESSAGE("TRI_Racer_Setup_Name")
|
|
Racer.szName = sName
|
|
ENDPROC
|
|
|
|
PROC TRI_Racer_Setup_Entities(TRI_RACER_STRUCT& Racer, PED_INDEX Driver, VEHICLE_INDEX Vehicle)
|
|
//DEBUG_MESSAGE("TRI_Racer_Setup_Entities")
|
|
Racer.Driver = Driver
|
|
Racer.Vehicle = Vehicle
|
|
ENDPROC
|
|
|
|
PROC TRI_Racer_Setup_Start(TRI_RACER_STRUCT& Racer, VECTOR vStartPos, FLOAT fStartHead)
|
|
//DEBUG_MESSAGE("TRI_Racer_Setup_Start")
|
|
Racer.vStartPos = vStartPos
|
|
Racer.fStartHead = fStartHead
|
|
ENDPROC
|
|
|
|
PROC TRI_Racer_Setup_Types(TRI_RACER_STRUCT& Racer, PED_TYPE eDriverType, MODEL_NAMES eDriverModel, MODEL_NAMES eVehicleModel)
|
|
//DEBUG_MESSAGE("TRI_Racer_Setup_Types")
|
|
Racer.eDriverType = eDriverType
|
|
Racer.eDriverModel = eDriverModel
|
|
Racer.eVehicleModel = eVehicleModel
|
|
ENDPROC
|
|
|
|
|
|
|
|
// -----------------------------------
|
|
// DRIVER CREATION PROCS/FUNCTIONS
|
|
// -----------------------------------
|
|
|
|
PROC TRI_Racer_Driver_Request(TRI_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("TRI_Racer_Driver_Request")
|
|
IF (Racer.eDriverModel = DUMMY_MODEL_FOR_SCRIPT)
|
|
SCRIPT_ASSERT("TRI_Racer_Driver_Request: Model invalid!")
|
|
EXIT
|
|
ENDIF
|
|
REQUEST_MODEL(Racer.eDriverModel)
|
|
ENDPROC
|
|
|
|
FUNC BOOL TRI_Racer_Driver_Stream(TRI_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("TRI_Racer_Driver_Stream")
|
|
IF (Racer.eDriverModel = DUMMY_MODEL_FOR_SCRIPT)
|
|
SCRIPT_ASSERT("TRI_Racer_Driver_Stream: Model invalid!")
|
|
RETURN FALSE
|
|
ENDIF
|
|
RETURN HAS_MODEL_LOADED(Racer.eDriverModel)
|
|
ENDFUNC
|
|
|
|
PROC TRI_Racer_Driver_Evict(TRI_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("TRI_Racer_Driver_Evict")
|
|
IF (Racer.eDriverModel = DUMMY_MODEL_FOR_SCRIPT)
|
|
SCRIPT_ASSERT("TRI_Racer_Driver_Evict: Model invalid!")
|
|
EXIT
|
|
ENDIF
|
|
SET_MODEL_AS_NO_LONGER_NEEDED(Racer.eDriverModel)
|
|
ENDPROC
|
|
|
|
FUNC BOOL TRI_Racer_Driver_Create(TRI_RACER_STRUCT& Racer)
|
|
DEBUG_MESSAGE("TRI_Racer_Driver_Create")
|
|
|
|
// Check if driver model is valid before continuing.
|
|
IF (Racer.eDriverModel = DUMMY_MODEL_FOR_SCRIPT)
|
|
SCRIPT_ASSERT("TRI_Racer_Driver_Create: Model invalid!")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// Check if driver already exists.
|
|
IF NOT IS_ENTITY_DEAD(Racer.Driver)
|
|
|
|
// Set driver health to max.
|
|
SET_ENTITY_HEALTH(Racer.Driver, 1000)
|
|
|
|
// If vehicle also exists, put driver in it, if needed.
|
|
IF NOT IS_ENTITY_DEAD(Racer.Vehicle)
|
|
//DEBUG_MESSAGE("TRI_Racer_Driver_Create: Tele Veh")
|
|
IF NOT IS_PED_SITTING_IN_VEHICLE(Racer.Driver, Racer.Vehicle)
|
|
SET_PED_INTO_VEHICLE(Racer.Driver, Racer.Vehicle)
|
|
ENDIF
|
|
// Otherwise, vehicle doesn't exist, teleport driver to start.
|
|
ELSE
|
|
//DEBUG_MESSAGE("TRI_Racer_Driver_Create: Teleport")
|
|
SET_ENTITY_COORDS(Racer.Driver, Racer.vStartPos)
|
|
SET_ENTITY_HEADING(Racer.Driver, Racer.fStartHead)
|
|
ENDIF
|
|
|
|
// Otherwise, if vehicle exists, create driver inside it and check for validity.
|
|
ELIF NOT IS_ENTITY_DEAD(Racer.Vehicle)
|
|
//DEBUG_MESSAGE("TRI_Racer_Driver_Create: Create In Vehicle")
|
|
Racer.Driver = CREATE_PED_INSIDE_VEHICLE(Racer.Vehicle, Racer.eDriverType, Racer.eDriverModel)
|
|
IF IS_ENTITY_DEAD(Racer.Driver)
|
|
DEBUG_MESSAGE("TRI_Racer_Driver_Create: Failed to create driver in vehicle!")
|
|
RETURN FALSE
|
|
ENDIF
|
|
// Otherwise, vehicle doesn't exist, just create driver normally and check for validity.
|
|
ELSE
|
|
//DEBUG_MESSAGE("TRI_Racer_Driver_Create: Create On Foot")
|
|
Racer.Driver = CREATE_PED(Racer.eDriverType, Racer.eDriverModel, Racer.vStartPos, Racer.fStartHead)
|
|
IF IS_ENTITY_DEAD(Racer.Driver)
|
|
DEBUG_MESSAGE("TRI_Racer_Driver_Create: Failed to create driver on foot!")
|
|
RETURN FALSE
|
|
ENDIF
|
|
SET_PED_LEG_IK_MODE(Racer.Driver, LEG_IK_PARTIAL)
|
|
SET_PED_STEERS_AROUND_OBJECTS(Racer.Driver, FALSE)
|
|
CPRINTLN(DEBUG_TRIATHLON, "SET_PED_LEG_IK_MODE(Racer.Driver, LEG_IK_PARTIAL) called")
|
|
ENDIF
|
|
|
|
// Check if driver type is player.
|
|
IF (Racer.eDriverType <= PEDTYPE_PLAYER_UNUSED)
|
|
|
|
// TODO: Put player driver logic here...
|
|
|
|
// Otherwise, driver type isn't player.
|
|
ELSE
|
|
|
|
// Set driver as mission entity.
|
|
IF NOT IS_ENTITY_A_MISSION_ENTITY(Racer.Driver)
|
|
SET_ENTITY_AS_MISSION_ENTITY(Racer.Driver)
|
|
ENDIF
|
|
|
|
// Set driver debug name.
|
|
TEXT_LABEL szDebugName = Racer.szName
|
|
szDebugName += "_Drv"
|
|
SET_PED_NAME_DEBUG(Racer.Driver, szDebugName)
|
|
|
|
ENDIF
|
|
|
|
IF NOT IS_ENTITY_DEAD(Racer.Driver)
|
|
IF ORR_DOES_RACE_REQUIRE_MOTORCYCLE()
|
|
SET_PED_HELMET(Racer.Driver, TRUE)
|
|
GIVE_PED_HELMET(Racer.Driver, TRUE)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// Racer driver successfully created.
|
|
RETURN TRUE
|
|
|
|
ENDFUNC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// In Triathlon, reset the player's health.
|
|
PROC TRI_Racer_TriRacer_Create(TRI_RACER_STRUCT& Racer)
|
|
CPRINTLN(DEBUG_TRIATHLON, "[TRI_Racer.sch->TRI_Racer_TriRacer_Create] Procedure started.")
|
|
|
|
// Check if driver already exists.
|
|
IF NOT IS_ENTITY_DEAD(Racer.Driver)
|
|
CPRINTLN(DEBUG_TRIATHLON, "[TRI_Racer.sch->TRI_Racer_TriRacer_Create] Setting driver to full health.")
|
|
SET_ENTITY_HEALTH(Racer.Driver, 1000)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// In Triathlon, place the recreated player after resetting.
|
|
PROC TRI_Racer_TriRacer_Place(TRI_RACE_STRUCT& Race, TRI_RACER_STRUCT& Racer)
|
|
|
|
VECTOR vFwd
|
|
|
|
// Check if the current gate is the first one.
|
|
IF Racer.iGateCur > 0
|
|
VECTOR vProbeStartPosition //10m above the gate so we can probe
|
|
VECTOR vProbeEndPosition //10m below the gate so we can probe
|
|
VECTOR vNewPlayerPosition //the pos we'll be setting the player to
|
|
|
|
// If not, warp the bike to the start of the checkpoint previous to the current.
|
|
PRINTLN("Gate position is... ", Race.sGate[Racer.iGateCur - 1].vPos)
|
|
|
|
//Setup our test vectors, and the player coords
|
|
vProbeStartPosition = Race.sGate[Racer.iGateCur - 1].vPos
|
|
vProbeEndPosition = Race.sGate[Racer.iGateCur - 1].vPos
|
|
vNewPlayerPosition = Race.sGate[Racer.iGateCur - 1].vPos
|
|
vProbeStartPosition.z += 10
|
|
vProbeEndPosition.z -= 10
|
|
|
|
PRINTLN("Adding 10 to the z for the start probe... ", vProbeStartPosition)
|
|
PRINTLN("Subtracting 10 to the z for the end probe... ", vProbeEndPosition)
|
|
PRINTLN("Probing for water... ")
|
|
IF TEST_PROBE_AGAINST_WATER(vProbeStartPosition, vProbeEndPosition, vNewPlayerPosition)
|
|
PRINTLN("Found a water intersection! Setting new player position... ", vNewPlayerPosition)
|
|
vNewPlayerPosition.z += TRI_WATER_RESET_OFFSET
|
|
SET_ENTITY_COORDS(Racer.Driver, vNewPlayerPosition)
|
|
ELSE
|
|
PRINTLN("No water detected. Probing ground...")
|
|
IF GET_GROUND_Z_FOR_3D_COORD(vProbeStartPosition, vNewPlayerPosition.z)
|
|
PRINTLN("Found a ground z so setting the player here...", vNewPlayerPosition)
|
|
SET_ENTITY_COORDS(Racer.Driver, vNewPlayerPosition)
|
|
ELSE
|
|
PRINTLN("No ground coord so setting player here...", vNewPlayerPosition)
|
|
SET_ENTITY_COORDS(Racer.Driver, vNewPlayerPosition)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// Get the vector between the previous and current checkpoint, to use as the driver's heading.
|
|
vFwd = Race.sGate[Racer.iGateCur].vPos - Race.sGate[Racer.iGateCur - 1].vPos
|
|
ELSE
|
|
// Warp the player to the start position.
|
|
SET_ENTITY_COORDS(Racer.Driver, Racer.vStartPos)
|
|
|
|
// Get the vector between the starting position, and the current checkpoint, to use as the driver's heading.
|
|
vFwd = Race.sGate[Racer.iGateCur].vPos - Racer.vStartPos
|
|
ENDIF
|
|
|
|
// Set its heading towards the current checkpoint.
|
|
IF NOT IS_ENTITY_DEAD(Racer.Driver)
|
|
FLOAT fPlayerHeading
|
|
fPlayerHeading = GET_HEADING_FROM_VECTOR_2D(vFwd.x, vFwd.y)
|
|
SET_ENTITY_HEADING(Racer.Driver, fPlayerHeading)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC TRI_Racer_Driver_Freeze(TRI_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("TRI_Racer_Driver_Freeze")
|
|
IF NOT IS_ENTITY_DEAD(Racer.Driver)
|
|
IF NOT IS_PED_IN_ANY_VEHICLE(Racer.Driver)
|
|
FREEZE_ENTITY_POSITION(Racer.Driver, TRUE)
|
|
SET_ENTITY_COLLISION(Racer.Driver, FALSE)
|
|
ENDIF
|
|
SET_ENTITY_INVINCIBLE(Racer.Driver, TRUE)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC TRI_Racer_Driver_UnFreeze(TRI_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("TRI_Racer_Driver_UnFreeze")
|
|
IF NOT IS_ENTITY_DEAD(Racer.Driver)
|
|
IF NOT IS_PED_IN_ANY_VEHICLE(Racer.Driver)
|
|
FREEZE_ENTITY_POSITION(Racer.Driver, FALSE)
|
|
SET_ENTITY_COLLISION(Racer.Driver, TRUE)
|
|
ENDIF
|
|
SET_ENTITY_INVINCIBLE(Racer.Driver, FALSE)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC TRI_Racer_Driver_Release(TRI_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("TRI_Racer_Driver_Release")
|
|
IF DOES_ENTITY_EXIST(Racer.Driver)
|
|
// TODO: Decide if this player check is even needed...
|
|
IF (Racer.Driver <> PLAYER_PED_ID())
|
|
SET_PED_AS_NO_LONGER_NEEDED(Racer.Driver)
|
|
ENDIF
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC TRI_Racer_Driver_Destroy(TRI_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("TRI_Racer_Driver_Destroy")
|
|
IF DOES_ENTITY_EXIST(Racer.Driver)
|
|
// TODO: Decide if this player check is even needed...
|
|
IF (Racer.Driver <> PLAYER_PED_ID())
|
|
DELETE_PED(Racer.Driver)
|
|
ENDIF
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
|
|
|
|
|
|
// -----------------------------------
|
|
// VEHICLE CREATION PROCS/FUNCTIONS
|
|
// -----------------------------------
|
|
|
|
PROC TRI_Racer_Vehicle_Request(TRI_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("TRI_Racer_Vehicle_Request")
|
|
IF (Racer.eVehicleModel = DUMMY_MODEL_FOR_SCRIPT)
|
|
DEBUG_MESSAGE("TRI_Racer_Vehicle_Request: Model invalid!")
|
|
EXIT
|
|
ENDIF
|
|
REQUEST_MODEL(Racer.eVehicleModel)
|
|
ENDPROC
|
|
|
|
FUNC BOOL TRI_Racer_Vehicle_Stream(TRI_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("TRI_Racer_Vehicle_Stream")
|
|
IF (Racer.eVehicleModel = DUMMY_MODEL_FOR_SCRIPT)
|
|
DEBUG_MESSAGE("TRI_Racer_Vehicle_Stream: Model invalid!")
|
|
RETURN TRUE
|
|
ENDIF
|
|
RETURN HAS_MODEL_LOADED(Racer.eVehicleModel)
|
|
ENDFUNC
|
|
|
|
PROC TRI_Racer_Vehicle_Evict(TRI_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("TRI_Racer_Vehicle_Evict")
|
|
IF (Racer.eVehicleModel = DUMMY_MODEL_FOR_SCRIPT)
|
|
DEBUG_MESSAGE("TRI_Racer_Vehicle_Evict: Model invalid!")
|
|
EXIT
|
|
ENDIF
|
|
SET_MODEL_AS_NO_LONGER_NEEDED(Racer.eVehicleModel)
|
|
ENDPROC
|
|
|
|
|
|
FUNC BOOL TRI_Racer_Vehicle_Create(TRI_RACER_STRUCT& Racer, BOOL bForceCreate)
|
|
|
|
DEBUG_MESSAGE("TRI_Racer_Vehicle_Create called.")
|
|
|
|
// If forcing a create and vehicle already exists, destroy it.
|
|
IF bForceCreate
|
|
DEBUG_MESSAGE("Inside force create vehicle")
|
|
IF TRI_Master.eRaceType = TRI_RACE_TYPE_PLANE
|
|
IF DOES_ENTITY_EXIST(Racer.Vehicle)
|
|
IF NOT IS_ENTITY_DEAD(Racer.Vehicle)
|
|
OR NOT IS_VEHICLE_DRIVEABLE(Racer.Vehicle)
|
|
IF IS_PED_IN_VEHICLE(Racer.Driver, Racer.Vehicle)
|
|
CLEAR_PED_TASKS_IMMEDIATELY(Racer.Driver)
|
|
DELETE_VEHICLE(Racer.Vehicle)
|
|
DEBUG_MESSAGE("TRI_Racer_Vehicle_Create: Force deleted Stunt plane")
|
|
ENDIF
|
|
ELSE
|
|
IF IS_PED_IN_VEHICLE(Racer.Driver, Racer.Vehicle)
|
|
SET_ENTITY_COORDS(Racer.Driver, Racer.vStartPos)
|
|
ENDIF
|
|
IF IS_PED_IN_VEHICLE(Racer.Driver, Racer.Vehicle)
|
|
DEBUG_MESSAGE("TRI_Racer_Vehicle_Create: Driver still in Vehicle, not deleting vehicle")
|
|
ELSE
|
|
DELETE_VEHICLE(Racer.Vehicle)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
IF DOES_ENTITY_EXIST(Racer.Vehicle)
|
|
IF NOT IS_ENTITY_DEAD(Racer.Driver)
|
|
AND NOT IS_ENTITY_DEAD(Racer.Vehicle)
|
|
IF IS_PED_IN_VEHICLE(Racer.Driver, Racer.Vehicle)
|
|
CLEAR_PED_TASKS_IMMEDIATELY(Racer.Driver)
|
|
ENDIF
|
|
ENDIF
|
|
IF IS_PED_IN_ANY_VEHICLE(Racer.Driver)
|
|
VEHICLE_INDEX iVehicle = GET_VEHICLE_PED_IS_IN(Racer.Driver)
|
|
IF IS_ENTITY_A_MISSION_ENTITY(iVehicle)
|
|
DELETE_VEHICLE(iVehicle)
|
|
DEBUG_MESSAGE("Deleted the Racer.Vehicle inside force create vehicle")
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// If vehicle already exists, set health to max and teleport it.
|
|
IF NOT IS_ENTITY_DEAD(Racer.Vehicle)
|
|
//IF (TRI_Master.eRaceType = TRI_RACE_TYPE_PLANE) - removing for 162891
|
|
DEBUG_MESSAGE("TRI_Racer_Vehicle_Create: Teleport")
|
|
SET_ENTITY_HEALTH(Racer.Vehicle, 1000)
|
|
SET_VEHICLE_FIXED(Racer.Vehicle)
|
|
SET_VEHICLE_ENGINE_HEALTH(Racer.Vehicle, 1000.0)
|
|
SET_ENTITY_COORDS(Racer.Vehicle, Racer.vStartPos) //Racer.vStartPos)
|
|
SET_ENTITY_HEADING(Racer.Vehicle, Racer.fStartHead)
|
|
IF (TRI_Master.eRaceType = TRI_RACE_TYPE_PLANE)
|
|
SET_VEHICLE_ENGINE_ON(Racer.Vehicle, TRUE, TRUE)
|
|
SET_HELI_BLADES_FULL_SPEED(Racer.Vehicle)
|
|
ENDIF
|
|
//ENDIF
|
|
// Otherwise, vehicle doesn't exist, create it and check for validity.
|
|
ELSE
|
|
DEBUG_MESSAGE("TRI_Racer_Vehicle_Create: Create New Vehicle")
|
|
IF (Racer.eVehicleModel = DUMMY_MODEL_FOR_SCRIPT)
|
|
DEBUG_MESSAGE("TRI_Racer_Create: No vehicle to create!")
|
|
RETURN TRUE
|
|
ENDIF
|
|
IF IS_ENTITY_DEAD(Racer.Vehicle)
|
|
DEBUG_MESSAGE("TRI_Racer_Create: Failed to create vehicle!")
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF (TRI_Master.eRaceType <> TRI_RACE_TYPE_PLANE)
|
|
IF (GET_ENTITY_HEIGHT_ABOVE_GROUND(Racer.Vehicle) <= TRI_ON_GROUND_DIST)
|
|
SET_VEHICLE_ON_GROUND_PROPERLY(Racer.Vehicle)
|
|
IF (GET_ENTITY_HEIGHT_ABOVE_GROUND(Racer.Vehicle) > 1.5)
|
|
VECTOR vEntityCoords = GET_ENTITY_COORDS(Racer.Vehicle)
|
|
vEntityCoords.z -= GET_ENTITY_HEIGHT_ABOVE_GROUND(Racer.Vehicle) + 1.5
|
|
SET_ENTITY_COORDS(Racer.Vehicle, vEntityCoords, TRUE)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
SET_VEHICLE_ENGINE_ON(Racer.Vehicle, TRUE, TRUE)
|
|
IF TRI_Master.eRaceType = TRI_RACE_TYPE_PLANE
|
|
SET_HELI_BLADES_FULL_SPEED(Racer.Vehicle)
|
|
ENDIF
|
|
|
|
// If driver exists, put them in vehicle, if needed.
|
|
IF NOT IS_ENTITY_DEAD(Racer.Driver)
|
|
IF NOT IS_PED_SITTING_IN_VEHICLE(Racer.Driver, Racer.Vehicle)
|
|
SET_PED_INTO_VEHICLE(Racer.Driver, Racer.Vehicle)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// Set vehicle as mission entity.
|
|
IF NOT IS_ENTITY_A_MISSION_ENTITY(Racer.Vehicle)
|
|
SET_ENTITY_AS_MISSION_ENTITY(Racer.Vehicle)
|
|
ENDIF
|
|
|
|
// Set vehicle debug name.
|
|
TEXT_LABEL szDebugName = Racer.szName
|
|
szDebugName += "_Veh"
|
|
SET_VEHICLE_NAME_DEBUG(Racer.Vehicle, szDebugName)
|
|
|
|
// Check if driver type is player.
|
|
IF (Racer.eDriverType <= PEDTYPE_PLAYER_UNUSED)
|
|
|
|
// Store player vehicle in master struct.
|
|
TRI_Master.PlayerVeh = Racer.Vehicle
|
|
|
|
// Allow player to maintain speed during autopilot.
|
|
SET_VEHICLE_LIMIT_SPEED_WHEN_PLAYER_INACTIVE(Racer.Vehicle, FALSE)
|
|
|
|
// Otherwise, driver type isn't player.
|
|
ELSE
|
|
|
|
// TODO: Put ai driver logic here...
|
|
|
|
ENDIF
|
|
|
|
// Racer vehicle successfully created.
|
|
RETURN TRUE
|
|
|
|
ENDFUNC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// In Triathlon, recreate the player's bike after being reset.
|
|
PROC TRI_Racer_Tribike_Create(TRI_RACER_STRUCT& Racer)
|
|
CPRINTLN(DEBUG_TRIATHLON, "[TRI_Racer.sch->TRI_Racer_Tribike_Create] Procedure started.")
|
|
|
|
IF DOES_ENTITY_EXIST(Racer.Vehicle)
|
|
IF NOT IS_ENTITY_DEAD(Racer.Vehicle)
|
|
CPRINTLN(DEBUG_TRIATHLON, "[TRI_Racer.sch->TRI_Racer_Tribike_Create] Player bike is NOT DEAD. Fixing bike.")
|
|
|
|
// Fix up the bike.
|
|
SET_ENTITY_HEALTH(Racer.Vehicle, 1000)
|
|
SET_VEHICLE_ENGINE_HEALTH(Racer.Vehicle, 1000.0)
|
|
ELSE
|
|
CPRINTLN(DEBUG_TRIATHLON, "[TRI_Racer.sch->TRI_Racer_Tribike_Create] Player bike IS DEAD. Creating new bike.")
|
|
IF NOT IS_ENTITY_DEAD(Racer.Driver)
|
|
// If bike is dead, create a new one away from the water.
|
|
VECTOR vCreateBikeHere = GET_ENTITY_COORDS(Racer.Driver)
|
|
vCreateBikeHere.Z += 3.0
|
|
Racer.Vehicle = CREATE_VEHICLE(TRIBIKE, vCreateBikeHere, GET_ENTITY_HEADING(Racer.Driver))
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF NOT IS_ENTITY_DEAD(Racer.Driver)
|
|
// Heal the player, just in case.
|
|
SET_ENTITY_HEALTH(Racer.Driver, 1000)
|
|
ENDIF
|
|
|
|
// Teleport the player to be on the bike.
|
|
IF NOT IS_PED_IN_ANY_VEHICLE(Racer.Driver)
|
|
IF NOT IS_ENTITY_DEAD(Racer.Driver)
|
|
IF NOT IS_ENTITY_DEAD(Racer.Vehicle)
|
|
CPRINTLN(DEBUG_TRIATHLON, "[TRI_Racer.sch->TRI_Racer_Tribike_Create] Player is NOT ON BIKE. Setting player on bike.")
|
|
SET_PED_INTO_VEHICLE(Racer.Driver, Racer.Vehicle)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF NOT IS_PED_IN_ANY_VEHICLE(Racer.Driver)
|
|
CPRINTLN(DEBUG_TRIATHLON, "[TRI_Racer.sch->TRI_Racer_Tribike_Create] Player STILL NOT ON BIKE!")
|
|
ELSE
|
|
CPRINTLN(DEBUG_TRIATHLON, "[TRI_Racer.sch->TRI_Racer_Tribike_Create] Player successfully put ON BIKE!")
|
|
ENDIF
|
|
ELSE
|
|
CPRINTLN(DEBUG_TRIATHLON, "[TRI_Racer.sch->TRI_Racer_Tribike_Create] Player bike DOES NOT EXIST!")
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// In Triathlon, place the recreated player's bike in the correct position.
|
|
PROC TRI_Racer_Tribike_Place(TRI_RACE_STRUCT& Race, TRI_RACER_STRUCT& Racer)
|
|
VECTOR vForwardPreviousToCurrentGate
|
|
|
|
// Check if the current gate is the first one.
|
|
IF Racer.iGateCur > 0
|
|
IF NOT IS_PED_IN_ANY_VEHICLE(Racer.Driver)
|
|
IF NOT IS_ENTITY_DEAD(Racer.Driver)
|
|
IF NOT IS_ENTITY_DEAD(Racer.Vehicle)
|
|
CPRINTLN(DEBUG_TRIATHLON, "[TRI_Racer.sch->TRI_Racer_Tribike_Place] Player is NOT IN BIKE. Setting player in bike.")
|
|
SET_PED_INTO_VEHICLE(Racer.Driver, Racer.Vehicle)
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
CPRINTLN(DEBUG_TRIATHLON, "[TRI_Racer.sch->TRI_Racer_Tribike_Place] Player ALREADY ON BIKE..")
|
|
ENDIF
|
|
|
|
// If not, warp the bike to the start of the checkpoint previous to the current.
|
|
//SET_ENTITY_COORDS(Racer.Vehicle, Race.sGate[Racer.iGateCur - 1].vPos)
|
|
|
|
// Teleport the player and his bike to the last gate cleared.
|
|
CPRINTLN(DEBUG_TRIATHLON, "[TRI_Racer.sch->TRI_Racer_Tribike_Place] Teleporting player with bike.")
|
|
SET_PED_COORDS_KEEP_VEHICLE(Racer.Driver, Race.sGate[Racer.iGateCur - 1].vPos)
|
|
|
|
// Get the vector between the previous and current checkpoint, to use as the bike's heading.
|
|
vForwardPreviousToCurrentGate = Race.sGate[Racer.iGateCur].vPos - Race.sGate[Racer.iGateCur - 1].vPos
|
|
|
|
// We should never get here, but just in case.
|
|
ELSE
|
|
CPRINTLN(DEBUG_TRIATHLON, "[TRI_Racer.sch->TRI_Racer_Tribike_Place] ERROR: This should not be called if gate is 0! The first gate is always a water gate!")
|
|
ENDIF
|
|
|
|
// Set its heading towards the current checkpoint.
|
|
IF NOT IS_ENTITY_DEAD(Racer.Vehicle)
|
|
FLOAT fBikeHeading
|
|
fBikeHeading = GET_HEADING_FROM_VECTOR_2D(vForwardPreviousToCurrentGate.x, vForwardPreviousToCurrentGate.y)
|
|
SET_ENTITY_HEADING(Racer.Vehicle, fBikeHeading)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC TRI_Racer_Vehicle_Freeze(TRI_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("TRI_Racer_Vehicle_Freeze")
|
|
IF NOT IS_ENTITY_DEAD(Racer.Vehicle)
|
|
FREEZE_ENTITY_POSITION(Racer.Vehicle, TRUE)
|
|
SET_ENTITY_COLLISION(Racer.Vehicle, FALSE)
|
|
SET_ENTITY_INVINCIBLE(Racer.Vehicle, TRUE)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC TRI_Racer_Vehicle_UnFreeze(TRI_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("TRI_Racer_Vehicle_UnFreeze")
|
|
IF NOT IS_ENTITY_DEAD(Racer.Vehicle)
|
|
FREEZE_ENTITY_POSITION(Racer.Vehicle, FALSE)
|
|
SET_ENTITY_COLLISION(Racer.Vehicle, TRUE)
|
|
SET_ENTITY_INVINCIBLE(Racer.Vehicle, FALSE)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC TRI_Racer_Vehicle_Release(TRI_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("TRI_Racer_Vehicle_Release")
|
|
IF DOES_ENTITY_EXIST(Racer.Vehicle)
|
|
// TODO: Decide if this player check is even needed...
|
|
IF (Racer.Vehicle <> TRI_Master.PlayerVeh)
|
|
IF NOT IS_ENTITY_DEAD(Racer.Driver)
|
|
IF IS_PED_IN_VEHICLE(Racer.Driver, Racer.Vehicle)
|
|
TASK_LEAVE_ANY_VEHICLE(Racer.Driver)
|
|
ENDIF
|
|
ENDIF
|
|
SET_VEHICLE_AS_NO_LONGER_NEEDED(Racer.Vehicle)
|
|
ENDIF
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC TRI_Racer_Vehicle_Destroy(TRI_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("TRI_Racer_Vehicle_Destroy")
|
|
IF DOES_ENTITY_EXIST(Racer.Vehicle)
|
|
// TODO: Decide if this player check is even needed...
|
|
IF (Racer.Vehicle <> TRI_Master.PlayerVeh)
|
|
IF NOT ( IS_ENTITY_DEAD(Racer.Driver) OR IS_ENTITY_DEAD(Racer.Vehicle) )
|
|
IF IS_PED_IN_VEHICLE(Racer.Driver, Racer.Vehicle)
|
|
CLEAR_PED_TASKS_IMMEDIATELY(Racer.Driver)
|
|
ENDIF
|
|
ENDIF
|
|
DELETE_VEHICLE(Racer.Vehicle)
|
|
ENDIF
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
|
|
|
|
|
|
// -----------------------------------
|
|
// MAIN CREATION PROCS/FUNCTIONS
|
|
// -----------------------------------
|
|
|
|
PROC TRI_Racer_Request(TRI_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("TRI_Racer_Request")
|
|
TRI_Racer_Driver_Request(Racer)
|
|
TRI_Racer_Vehicle_Request(Racer)
|
|
ENDPROC
|
|
|
|
FUNC BOOL TRI_Racer_Stream(TRI_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("TRI_Racer_Stream")
|
|
IF NOT TRI_Racer_Driver_Stream(Racer)
|
|
OR NOT TRI_Racer_Vehicle_Stream(Racer)
|
|
RETURN FALSE
|
|
ENDIF
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
PROC TRI_Racer_Evict(TRI_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("TRI_Racer_Evict")
|
|
TRI_Racer_Driver_Evict(Racer)
|
|
TRI_Racer_Vehicle_Evict(Racer)
|
|
ENDPROC
|
|
|
|
FUNC BOOL TRI_Racer_Blip_Create(TRI_RACER_STRUCT& Racer, FLOAT fScale = 1.0)
|
|
IF (Racer.Driver <> PLAYER_PED_ID())
|
|
IF NOT TRI_Blip_Entity_Create(Racer.Blip, Racer.Driver, fScale)
|
|
DEBUG_MESSAGE("TRI_Racer_Blip_Create: Failed to create racer driver blip!")
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
PROC TRI_Racer_Blip_Destroy(TRI_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("TRI_Racer_Blip_Destroy")
|
|
TRI_Blip_Destroy(Racer.Blip)
|
|
ENDPROC
|
|
|
|
FUNC BOOL TRI_Racer_Create(TRI_RACER_STRUCT& Racer, BOOL bForceCreate)
|
|
DEBUG_MESSAGE("TRI_Racer_Create")
|
|
IF NOT TRI_Racer_Vehicle_Create(Racer, bForceCreate)
|
|
OR NOT TRI_Racer_Driver_Create(Racer)
|
|
RETURN FALSE
|
|
ENDIF
|
|
// TODO: Should this be done in every case?
|
|
// BUG : 86339 - they don't want racers blipped any more.
|
|
//TRI_Racer_Blip_Create(Racer)
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
PROC TRI_Racer_Freeze(TRI_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("TRI_Racer_Freeze")
|
|
TRI_Racer_Driver_Freeze(Racer)
|
|
TRI_Racer_Vehicle_Freeze(Racer)
|
|
ENDPROC
|
|
|
|
PROC TRI_Racer_UnFreeze(TRI_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("TRI_Racer_UnFreeze")
|
|
TRI_Racer_Driver_UnFreeze(Racer)
|
|
TRI_Racer_Vehicle_UnFreeze(Racer)
|
|
ENDPROC
|
|
|
|
PROC TRI_Racer_Release(TRI_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("TRI_Racer_Release")
|
|
TRI_Racer_Blip_Destroy(Racer)
|
|
TRI_Racer_Driver_Release(Racer)
|
|
TRI_Racer_Vehicle_Release(Racer)
|
|
ENDPROC
|
|
|
|
PROC TRI_Racer_Destroy(TRI_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("TRI_Racer_Destroy")
|
|
TRI_Racer_Blip_Destroy(Racer)
|
|
TRI_Racer_Driver_Destroy(Racer)
|
|
TRI_Racer_Vehicle_Destroy(Racer)
|
|
ENDPROC
|
|
|
|
|
|
|
|
|
|
// -----------------------------------
|
|
// HELPER PROCS/FUNCTIONS
|
|
// -----------------------------------
|
|
|
|
PROC TRI_Racer_Teleport(TRI_RACER_STRUCT& Racer, VECTOR vPos, FLOAT fHeading, FLOAT fSpeed)
|
|
//DEBUG_MESSAGE("TRI_Racer_Teleport")
|
|
CPRINTLN(DEBUG_TRIATHLON, "TRI_Racer_Teleport, Racer=", Racer.szName)
|
|
IF IS_ENTITY_DEAD(Racer.Vehicle) OR NOT IS_PED_IN_VEHICLE(Racer.Driver, Racer.Vehicle)
|
|
SET_ENTITY_COORDS(Racer.Driver, vPos)
|
|
SET_ENTITY_HEADING(Racer.Driver, fHeading)
|
|
ELSE
|
|
SET_ENTITY_COORDS(Racer.Vehicle, vPos)
|
|
SET_ENTITY_HEADING(Racer.Vehicle, fHeading)
|
|
SET_VEHICLE_FORWARD_SPEED(Racer.Vehicle, fSpeed)
|
|
|
|
// In Tri, this code causes the player's bike to sometimes teleport below the ground.
|
|
IF (TRI_Master.eRaceType <> TRI_RACE_TYPE_PLANE) AND (TRI_Master.eRaceType <> TRI_RACE_TYPE_TRIATHLON)
|
|
SET_VEHICLE_ON_GROUND_PROPERLY(Racer.Vehicle)
|
|
WAIT(0)
|
|
IF NOT IS_ENTITY_DEAD(Racer.Vehicle)
|
|
IF (GET_ENTITY_HEIGHT_ABOVE_GROUND(Racer.Vehicle) > 1.5)
|
|
VECTOR vEntityCoords = GET_ENTITY_COORDS(Racer.Vehicle)
|
|
vEntityCoords.z -= GET_ENTITY_HEIGHT_ABOVE_GROUND(Racer.Vehicle) + 1.5
|
|
SET_ENTITY_COORDS(Racer.Vehicle, vEntityCoords, TRUE)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC TRI_Racer_Start(TRI_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("TRI_Racer_Start")
|
|
|
|
IF NOT IS_ENTITY_DEAD(Racer.Vehicle)
|
|
IF NOT IS_ENTITY_DEAD(Racer.Driver)
|
|
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(Racer.Vehicle)
|
|
STOP_PLAYBACK_RECORDED_VEHICLE(Racer.Vehicle)
|
|
ENDIF
|
|
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(Racer.Driver, TRUE)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// Reset racer current gate.
|
|
Racer.iGateCur = 0
|
|
|
|
// Check if racer vehicle is alive.
|
|
IF NOT IS_ENTITY_DEAD(Racer.Vehicle)
|
|
|
|
// Start racer vehicle engine, if needed.
|
|
IF NOT IS_THIS_MODEL_A_BIKE(Racer.eVehicleModel)
|
|
SET_VEHICLE_ENGINE_ON(Racer.Vehicle, TRUE, TRUE)
|
|
ENDIF
|
|
|
|
// Add stuck check for racer vehicle, if needed.
|
|
// TODO: Make sure this isn't needed at all for stuck checks.
|
|
//IF NOT DOES_VEHICLE_HAVE_STUCK_VEHICLE_CHECK(Racer.Vehicle)
|
|
// ADD_VEHICLE_STUCK_CHECK(Racer.Vehicle, TRI_VEH_STUCK_MIN_MOVE, TRI_VEH_STUCK_CHK_TIME)
|
|
//ENDIF
|
|
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
PROC TRI_Racer_Finish(TRI_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("TRI_Racer_Finish")
|
|
|
|
// Check if racer vehicle is alive.
|
|
IF NOT IS_ENTITY_DEAD(Racer.Vehicle)
|
|
IF TRI_Master.eRaceType <> TRI_RACE_TYPE_PLANE
|
|
UnfreezePlayerVehicle()
|
|
DEBUG_MESSAGE("Unfreezing Players pre-race vehicle")
|
|
ENDIF
|
|
// Remove stuck check for racer vehicle, if needed.
|
|
// TODO: Make sure this isn't needed at all for stuck checks.
|
|
//IF DOES_VEHICLE_HAVE_STUCK_VEHICLE_CHECK(Racer.Vehicle)
|
|
// REMOVE_VEHICLE_STUCK_CHECK(Racer.Vehicle)
|
|
//ENDIF
|
|
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
FUNC BOOL TRI_Racer_Crash_Check(TRI_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("TRI_Racer_Crash_Check")
|
|
IF (Racer.eVehicleModel <> DUMMY_MODEL_FOR_SCRIPT)
|
|
IF Racer.Driver = PLAYER_PED_ID() //special cases for player in off-road, as player can get out of vehicle...spaghetti-o'd - SiM
|
|
AND TRI_Master.eRaceType = TRI_RACE_TYPE_OFFROAD
|
|
IF IS_PED_IN_VEHICLE(Racer.Driver, Racer.Vehicle)
|
|
IF IS_ENTITY_DEAD(Racer.Vehicle)
|
|
DEBUG_MESSAGE("TRI_Racer_Crash_Check: Vehicle dead!")
|
|
RETURN TRUE
|
|
ENDIF
|
|
IF NOT IS_VEHICLE_DRIVEABLE(Racer.Vehicle)
|
|
DEBUG_MESSAGE("TRI_Racer_Crash_Check: Vehicle undrivable!")
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
IF IS_ENTITY_DEAD(Racer.Vehicle)
|
|
DEBUG_MESSAGE("TRI_Racer_Crash_Check: Vehicle dead!")
|
|
RETURN TRUE
|
|
ENDIF
|
|
IF NOT IS_VEHICLE_DRIVEABLE(Racer.Vehicle)
|
|
DEBUG_MESSAGE("TRI_Racer_Crash_Check: Vehicle undrivable!")
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
// TODO: Make sure this isn't needed at all for stuck checks.
|
|
//IF DOES_VEHICLE_HAVE_STUCK_VEHICLE_CHECK(Racer.Vehicle)
|
|
IF NOT IS_PLAYER_DEAD(PLAYER_ID())
|
|
IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), Racer.Vehicle)
|
|
IF (GET_ENTITY_SPEED(Racer.Vehicle) <= 15.0)
|
|
IF Racer.eVehicleModel = STUNT
|
|
IF GET_ENTITY_HEIGHT_ABOVE_GROUND(Racer.Vehicle) < 3.0
|
|
OR HAS_ENTITY_COLLIDED_WITH_ANYTHING(Racer.Vehicle)
|
|
IF IS_ENTITY_UPSIDEDOWN(Racer.Vehicle) AND GET_ENTITY_HEIGHT_ABOVE_GROUND(Racer.Vehicle) < 1.0
|
|
DEBUG_MESSAGE("we on the roof!")
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF IS_VEHICLE_STUCK_TIMER_UP(Racer.Vehicle, VEH_STUCK_ON_ROOF, TRI_VEH_STUCK_PLANE_ROOF_TIME)
|
|
DEBUG_MESSAGE("TRI_Racer_Crash_Check: Vehicle stuck (roof)!")
|
|
RETURN TRUE
|
|
ENDIF
|
|
IF IS_VEHICLE_STUCK_TIMER_UP(Racer.Vehicle, VEH_STUCK_ON_SIDE, TRI_VEH_STUCK_PLANE_SIDE_TIME)
|
|
DEBUG_MESSAGE("TRI_Racer_Crash_Check: Vehicle stuck (side)!")
|
|
RETURN TRUE
|
|
ENDIF
|
|
IF IS_VEHICLE_STUCK_TIMER_UP(Racer.Vehicle, VEH_STUCK_HUNG_UP, TRI_VEH_STUCK_PLANE_HUNG_TIME)
|
|
DEBUG_MESSAGE("TRI_Racer_Crash_Check: Vehicle stuck (hung)!")
|
|
RETURN TRUE
|
|
ENDIF
|
|
IF IS_VEHICLE_STUCK_TIMER_UP(Racer.Vehicle, VEH_STUCK_JAMMED, TRI_VEH_STUCK_PLANE_JAM_TIME)
|
|
DEBUG_MESSAGE("TRI_Racer_Crash_Check: Vehicle stuck (jam)!")
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
IF IS_VEHICLE_STUCK_TIMER_UP(Racer.Vehicle, VEH_STUCK_ON_ROOF, TRI_VEH_STUCK_BIKE_ROOF_TIME)
|
|
DEBUG_MESSAGE("TRI_Racer_Crash_Check: Vehicle stuck (roof)!")
|
|
RETURN TRUE
|
|
ENDIF
|
|
IF IS_VEHICLE_STUCK_TIMER_UP(Racer.Vehicle, VEH_STUCK_ON_SIDE, TRI_VEH_STUCK_BIKE_SIDE_TIME)
|
|
DEBUG_MESSAGE("TRI_Racer_Crash_Check: Vehicle stuck (side)!")
|
|
RETURN TRUE
|
|
ENDIF
|
|
IF IS_VEHICLE_STUCK_TIMER_UP(Racer.Vehicle, VEH_STUCK_HUNG_UP, TRI_VEH_STUCK_BIKE_HUNG_TIME)
|
|
DEBUG_MESSAGE("TRI_Racer_Crash_Check: Vehicle stuck (hung)!")
|
|
RETURN TRUE
|
|
ENDIF
|
|
IF IS_VEHICLE_STUCK_TIMER_UP(Racer.Vehicle, VEH_STUCK_JAMMED, TRI_VEH_STUCK_BIKE_JAM_TIME)
|
|
DEBUG_MESSAGE("TRI_Racer_Crash_Check: Vehicle stuck (jam)!")
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
//ENDIF
|
|
ENDIF
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
// END OF FILE! DO NOT ADD ANYTHING BELOW THIS LINE!
|