1302 lines
45 KiB
Scheme
Executable File
1302 lines
45 KiB
Scheme
Executable File
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
//
|
|
// SCRIPT NAME : SPTT_Racer.sch
|
|
// AUTHOR : Nicholas Zippmann
|
|
// DESCRIPTION : Single Player Races - Racer procs/functions file
|
|
//
|
|
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
|
|
USING "SPTT_Head.sch"
|
|
USING "SPTT_Helpers.sch"
|
|
USING "SPTT_Gate.sch"
|
|
USING "chase_hint_cam.sch"
|
|
USING "stunt_plane_public.sch"
|
|
|
|
// -----------------------------------
|
|
// SETUP PROCS/FUNCTIONS
|
|
// -----------------------------------
|
|
|
|
// bits for dialogue
|
|
INT iMissedGateBits // missed gates
|
|
INT iClearedGateBits // cleared gates
|
|
INT iPerfectGateBits // perfect gates
|
|
INT iInvertedGateBits // inverted gates
|
|
INT iKnifeGateBits // knife gates
|
|
INT iPerfInvGateBits // perfect inverted gates
|
|
INT iPerfKniGateBits // perfect knife gates
|
|
|
|
// tracks how many consecutive gates weve hit
|
|
INT iStuntGateHit
|
|
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(SPTT_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 SPTT_Racer_Init(SPTT_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("SPTT_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 = SPTT_RACER_RESET_WAIT
|
|
Racer.vStartPos = SPTT_Master.vDefRcrPos
|
|
Racer.fStartHead = SPTT_Master.fDefRcrHead
|
|
Racer.eDriverType = SPTT_Master.eDefDrvType
|
|
Racer.eDriverModel = SPTT_Master.eDefDrvModel
|
|
Racer.eVehicleModel = SPTT_Master.eDefVehModel
|
|
ENDPROC
|
|
|
|
PROC SPTT_Racer_Setup_Misc(SPTT_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("SPTT_Racer_Setup_Misc")
|
|
Racer.Blip = NULL
|
|
Racer.iGateCur = -1
|
|
Racer.iRank = 0
|
|
Racer.fClockTime = 0.0
|
|
Racer.eReset = SPTT_RACER_RESET_WAIT
|
|
ENDPROC
|
|
|
|
PROC SPTT_Racer_Setup_Name(SPTT_RACER_STRUCT& Racer, STRING sName)
|
|
//DEBUG_MESSAGE("SPTT_Racer_Setup_Name")
|
|
Racer.szName = sName
|
|
ENDPROC
|
|
|
|
PROC SPTT_Racer_Setup_Entities(SPTT_RACER_STRUCT& Racer, PED_INDEX Driver, VEHICLE_INDEX Vehicle)
|
|
//DEBUG_MESSAGE("SPTT_Racer_Setup_Entities")
|
|
Racer.Driver = Driver
|
|
Racer.Vehicle = Vehicle
|
|
GET_VEHICLE_SETUP( Vehicle, SPTT_Master.vssPlaneSetup )
|
|
ENDPROC
|
|
|
|
PROC SPTT_Racer_Setup_Start(SPTT_RACER_STRUCT& Racer, VECTOR vStartPos, FLOAT fStartHead)
|
|
//DEBUG_MESSAGE("SPTT_Racer_Setup_Start")
|
|
Racer.vStartPos = vStartPos
|
|
Racer.fStartHead = fStartHead
|
|
ENDPROC
|
|
|
|
PROC SPTT_Racer_Setup_Types(SPTT_RACER_STRUCT& Racer, PED_TYPE eDriverType, MODEL_NAMES eDriverModel, MODEL_NAMES eVehicleModel)
|
|
//DEBUG_MESSAGE("SPTT_Racer_Setup_Types")
|
|
Racer.eDriverType = eDriverType
|
|
Racer.eDriverModel = eDriverModel
|
|
Racer.eVehicleModel = eVehicleModel
|
|
ENDPROC
|
|
PROC SPTT_RESET_GATE_DIALOGUE_BITS()
|
|
iMissedGateBits = 0 // missed gates
|
|
iClearedGateBits = 0 // cleared gates
|
|
iPerfectGateBits = 0 // perfect gates
|
|
iInvertedGateBits = 0 // inverted gates
|
|
iKnifeGateBits = 0 // knife gates
|
|
iPerfInvGateBits = 0 // perfect inverted gates
|
|
iPerfKniGateBits = 0 // perfect knife gates
|
|
iStuntGateHit = 0
|
|
ENDPROC
|
|
|
|
|
|
|
|
// -----------------------------------
|
|
// DRIVER CREATION PROCS/FUNCTIONS
|
|
// -----------------------------------
|
|
|
|
PROC SPTT_Racer_Driver_Request(SPTT_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("SPTT_Racer_Driver_Request")
|
|
IF (Racer.eDriverModel = DUMMY_MODEL_FOR_SCRIPT)
|
|
SCRIPT_ASSERT("SPTT_Racer_Driver_Request: Model invalid!")
|
|
EXIT
|
|
ENDIF
|
|
REQUEST_MODEL(Racer.eDriverModel)
|
|
ENDPROC
|
|
|
|
FUNC BOOL SPTT_Racer_Driver_Stream(SPTT_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("SPTT_Racer_Driver_Stream")
|
|
IF (Racer.eDriverModel = DUMMY_MODEL_FOR_SCRIPT)
|
|
SCRIPT_ASSERT("SPTT_Racer_Driver_Stream: Model invalid!")
|
|
RETURN FALSE
|
|
ENDIF
|
|
RETURN HAS_MODEL_LOADED(Racer.eDriverModel)
|
|
ENDFUNC
|
|
|
|
PROC SPTT_Racer_Driver_Evict(SPTT_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("SPTT_Racer_Driver_Evict")
|
|
IF (Racer.eDriverModel = DUMMY_MODEL_FOR_SCRIPT)
|
|
SCRIPT_ASSERT("SPTT_Racer_Driver_Evict: Model invalid!")
|
|
EXIT
|
|
ENDIF
|
|
SET_MODEL_AS_NO_LONGER_NEEDED(Racer.eDriverModel)
|
|
ENDPROC
|
|
|
|
FUNC BOOL SPTT_Racer_Driver_Create(SPTT_RACER_STRUCT& Racer)
|
|
PRINTLN("[SPTT_Racer_Driver_Create] Function called.")
|
|
|
|
// Check if driver model is valid before continuing.
|
|
IF (Racer.eDriverModel = DUMMY_MODEL_FOR_SCRIPT)
|
|
SCRIPT_ASSERT("[SPTT_Racer_Driver_Create] Model invalid!")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// Check if driver already exists.
|
|
IF NOT IS_ENTITY_DEAD(Racer.Driver)
|
|
PRINTLN("[SPTT_Racer_Driver_Create] Player is ALIVE.")
|
|
|
|
SET_ENTITY_HEALTH(Racer.Driver, 1000)
|
|
|
|
// If vehicle also exists, put driver in it, if needed.
|
|
IF NOT IS_ENTITY_DEAD(Racer.Vehicle)
|
|
PRINTLN("[SPTT_Racer_Driver_Create] Placing player in stunt plane.")
|
|
IF NOT IS_PED_SITTING_IN_VEHICLE(Racer.Driver, Racer.Vehicle)
|
|
SET_PED_INTO_VEHICLE(Racer.Driver, Racer.Vehicle)
|
|
ENDIF
|
|
ELSE
|
|
PRINTLN("[SPTT_Racer_Driver_Create] Warp the player to the start position.")
|
|
SET_ENTITY_COORDS(Racer.Driver, Racer.vStartPos)
|
|
SET_ENTITY_HEADING(Racer.Driver, Racer.fStartHead)
|
|
ENDIF
|
|
|
|
// The driver does not exist, but the vehicle is dead, so create driver inside it and check for validity.
|
|
ELIF NOT IS_ENTITY_DEAD(Racer.Vehicle)
|
|
PRINTLN("[SPTT_Racer_Driver_Create] Player is DEAD, but stunt plane is ALIVE. Create the player inside the vehicle.")
|
|
|
|
Racer.Driver = CREATE_PED_INSIDE_VEHICLE(Racer.Vehicle, Racer.eDriverType, Racer.eDriverModel)
|
|
IF IS_ENTITY_DEAD(Racer.Driver)
|
|
PRINTLN("[SPTT_Racer_Driver_Create] Failed to create the player in the stunt plane.")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// The driver nor the vehicle exist.
|
|
ELSE
|
|
PRINTLN("[SPTT_Racer_Driver_Create] Player and stunt plane are BOTH DEAD. Create the player on foot.")
|
|
Racer.Driver = CREATE_PED(Racer.eDriverType, Racer.eDriverModel, Racer.vStartPos, Racer.fStartHead)
|
|
IF IS_ENTITY_DEAD(Racer.Driver)
|
|
PRINTLN("[SPTT_Racer_Driver_Create] Failed to create the player on foot.")
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// Check if driver type is player. NOTE: This may not be needed.
|
|
IF (Racer.eDriverType > PEDTYPE_PLAYER_UNUSED)
|
|
// 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
|
|
|
|
// Racer driver successfully created.
|
|
PRINTLN("[SPTT_Racer_Driver_Create] Player successfully created and/or set.")
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
PROC SPTT_Racer_Driver_Freeze(SPTT_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("SPTT_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 SPTT_Racer_Driver_UnFreeze(SPTT_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("SPTT_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 SPTT_Racer_Driver_Release(SPTT_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("SPTT_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 SPTT_Racer_Driver_Destroy(SPTT_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("SPTT_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 SPTT_Racer_Vehicle_Request(SPTT_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("SPTT_Racer_Vehicle_Request")
|
|
IF (Racer.eVehicleModel = DUMMY_MODEL_FOR_SCRIPT)
|
|
DEBUG_MESSAGE("SPTT_Racer_Vehicle_Request: Model invalid!")
|
|
EXIT
|
|
ENDIF
|
|
REQUEST_MODEL(Racer.eVehicleModel)
|
|
ENDPROC
|
|
|
|
FUNC BOOL SPTT_Racer_Vehicle_Stream(SPTT_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("SPTT_Racer_Vehicle_Stream")
|
|
IF (Racer.eVehicleModel = DUMMY_MODEL_FOR_SCRIPT)
|
|
DEBUG_MESSAGE("SPTT_Racer_Vehicle_Stream: Model invalid!")
|
|
RETURN TRUE
|
|
ENDIF
|
|
RETURN HAS_MODEL_LOADED(Racer.eVehicleModel)
|
|
ENDFUNC
|
|
|
|
PROC SPTT_Racer_Vehicle_Evict(SPTT_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("SPTT_Racer_Vehicle_Evict")
|
|
IF (Racer.eVehicleModel = DUMMY_MODEL_FOR_SCRIPT)
|
|
DEBUG_MESSAGE("SPTT_Racer_Vehicle_Evict: Model invalid!")
|
|
EXIT
|
|
ENDIF
|
|
SET_MODEL_AS_NO_LONGER_NEEDED(Racer.eVehicleModel)
|
|
ENDPROC
|
|
|
|
|
|
FUNC BOOL SPTT_Racer_Vehicle_Create(SPTT_RACER_STRUCT& Racer, BOOL bForceCreate)
|
|
PRINTLN("[SPTT_Racer_Vehicle_Create] Function called.")
|
|
|
|
// If forced to create a new stunt plane and one already exists, destroy it!
|
|
IF bForceCreate
|
|
PRINTLN("[SPTT_Racer_Vehicle_Create] Force-creating the stunt plane was passed as TRUE.")
|
|
IF DOES_ENTITY_EXIST(Racer.Vehicle)
|
|
PRINTLN("[SPTT_Racer_Vehicle_Create] The stunt plane still exists.")
|
|
IF NOT IS_ENTITY_DEAD(Racer.Vehicle)
|
|
OR NOT IS_VEHICLE_DRIVEABLE(Racer.Vehicle)
|
|
PRINTLN("[SPTT_Racer_Vehicle_Create] The stunt plane is not dead, but it's not driveable.")
|
|
IF IS_PED_IN_VEHICLE(Racer.Driver, Racer.Vehicle)
|
|
PRINTLN("[SPTT_Racer_Vehicle_Create] The player is inside the stunt plane. Clear his tasks and delete the stunt plane.")
|
|
CLEAR_PED_TASKS_IMMEDIATELY(Racer.Driver)
|
|
SET_ENTITY_AS_MISSION_ENTITY(Racer.Vehicle, TRUE, TRUE)
|
|
DELETE_VEHICLE(Racer.Vehicle)
|
|
ENDIF
|
|
ELSE
|
|
IF IS_PED_IN_VEHICLE(Racer.Driver, Racer.Vehicle)
|
|
PRINTLN("[SPTT_Racer_Vehicle_Create] Warping the player out of the stunt plane.")
|
|
SET_ENTITY_COORDS(Racer.Driver, Racer.vStartPos)
|
|
ENDIF
|
|
IF IS_PED_IN_VEHICLE(Racer.Driver, Racer.Vehicle)
|
|
PRINTLN("[SPTT_Racer_Vehicle_Create] The player is still in the stunt plane.")
|
|
ELSE
|
|
PRINTLN("[SPTT_Racer_Vehicle_Create] The player is no longer in the stunt plane. Delete the stunt plane.")
|
|
SET_ENTITY_AS_MISSION_ENTITY(Racer.Vehicle, TRUE, TRUE)
|
|
DELETE_VEHICLE(Racer.Vehicle)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// If vehicle already exists, set health to max and teleport it.
|
|
IF NOT IS_ENTITY_DEAD(Racer.Vehicle)
|
|
PRINTLN("[SPTT_Racer_Vehicle_Create] A vehicle exists, so fix it. We should never reach here if we're forced to create a new stunt plane.")
|
|
|
|
// Fix vehicle.
|
|
SET_ENTITY_HEALTH(Racer.Vehicle, 1000)
|
|
SET_VEHICLE_FIXED(Racer.Vehicle)
|
|
SET_VEHICLE_ENGINE_HEALTH(Racer.Vehicle, 1000.0)
|
|
|
|
// Position and orient the vehicle.
|
|
SET_ENTITY_COORDS(Racer.Vehicle, Racer.vStartPos)
|
|
SET_ENTITY_HEADING(Racer.Vehicle, Racer.fStartHead)
|
|
|
|
SET_VEHICLE_ON_GROUND_PROPERLY( Racer.Vehicle )
|
|
ELSE
|
|
PRINTLN("[SPTT_Racer_Vehicle_Create] A vehicle exists, so fix it.")
|
|
|
|
IF (Racer.eVehicleModel = DUMMY_MODEL_FOR_SCRIPT)
|
|
PRINTLN("[SPTT_Racer_Vehicle_Create] ERROR: Cannot create vehicle. No model name stored for vehicle. Returning TRUE.")
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
// Create the stunt plane with strong axles.
|
|
Racer.Vehicle = CREATE_VEHICLE(STUNT, Racer.vStartPos, Racer.fStartHead)
|
|
|
|
IF IS_ENTITY_DEAD(Racer.Vehicle)
|
|
PRINTLN("[SPTT_Racer_Vehicle_Create] ERROR: Vehicle not created.")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
|
|
SET_VEHICLE_DOORS_LOCKED(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), VEHICLELOCK_LOCKED_PLAYER_INSIDE)
|
|
ENDIF
|
|
|
|
SET_VEHICLE_HAS_STRONG_AXLES(Racer.Vehicle, TRUE)
|
|
SET_VEHICLE_SETUP( Racer.Vehicle, SPTT_Master.vssPlaneSetup )
|
|
ENDIF
|
|
|
|
ENABLE_STALL_WARNING_SOUNDS(Racer.Vehicle, FALSE)
|
|
SET_VEHICLE_ENGINE_ON(Racer.Vehicle, TRUE, TRUE)
|
|
SET_HELI_BLADES_FULL_SPEED(Racer.Vehicle)
|
|
|
|
// 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)
|
|
PRINTLN("[SPTT_Racer_Vehicle_Create] Setting the player inside the stunt plane.")
|
|
SET_PED_INTO_VEHICLE(Racer.Driver, Racer.Vehicle)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// Set vehicle as mission entity.
|
|
IF NOT IS_ENTITY_A_MISSION_ENTITY(Racer.Vehicle)
|
|
PRINTLN("[SPTT_Racer_Vehicle_Create] Set plane as mission entity.")
|
|
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)
|
|
PRINTLN("[SPTT_Racer_Vehicle_Create] Store the vehicle in the system, and set vehicle to maintain speed when in autopilot.")
|
|
|
|
SET_VEHICLE_LIMIT_SPEED_WHEN_PLAYER_INACTIVE(Racer.Vehicle, FALSE)
|
|
SPTT_Master.PlayerVeh = Racer.Vehicle
|
|
ENDIF
|
|
|
|
// Racer vehicle successfully created.
|
|
PRINTLN("[SPTT_Racer_Vehicle_Create] Stunt plane has been successfully created!")
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
PROC SPTT_Racer_Vehicle_Freeze(SPTT_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("SPTT_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 SPTT_Racer_Vehicle_UnFreeze(SPTT_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("SPTT_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 SPTT_Racer_Vehicle_Release(SPTT_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("SPTT_Racer_Vehicle_Release")
|
|
IF DOES_ENTITY_EXIST(Racer.Vehicle)
|
|
// TODO: Decide if this player check is even needed...
|
|
IF (Racer.Vehicle <> SPTT_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 SPTT_Racer_Vehicle_Destroy(SPTT_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("SPTT_Racer_Vehicle_Destroy")
|
|
IF DOES_ENTITY_EXIST(Racer.Vehicle)
|
|
// TODO: Decide if this player check is even needed...
|
|
IF (Racer.Vehicle <> SPTT_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 SPTT_Racer_Request(SPTT_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("SPTT_Racer_Request")
|
|
SPTT_Racer_Driver_Request(Racer)
|
|
SPTT_Racer_Vehicle_Request(Racer)
|
|
ENDPROC
|
|
|
|
FUNC BOOL SPTT_Racer_Stream(SPTT_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("SPTT_Racer_Stream")
|
|
IF NOT SPTT_Racer_Driver_Stream(Racer)
|
|
OR NOT SPTT_Racer_Vehicle_Stream(Racer)
|
|
RETURN FALSE
|
|
ENDIF
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
PROC SPTT_Racer_Evict(SPTT_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("SPTT_Racer_Evict")
|
|
SPTT_Racer_Driver_Evict(Racer)
|
|
SPTT_Racer_Vehicle_Evict(Racer)
|
|
ENDPROC
|
|
|
|
FUNC BOOL SPTT_Racer_Blip_Create(SPTT_RACER_STRUCT& Racer, BOOL bFriendly = TRUE, FLOAT fScale = 1.0)
|
|
//DEBUG_MESSAGE("SPTT_Racer_Blip_Create")
|
|
/* SAVE: Just bliping the driver now, since they will be in the vehicle that we are bliping.
|
|
IF IS_ENTITY_DEAD(Racer.Vehicle)
|
|
IF (Racer.Driver <> PLAYER_PED_ID())
|
|
IF NOT SPTT_Blip_Entity_Create(Racer.Blip, Racer.Driver, bFriendly, fScale, Racer.szName)
|
|
DEBUG_MESSAGE("SPTT_Racer_Blip_Create: Failed to create racer driver blip!")
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
ELIF (Racer.Driver <> PLAYER_PED_ID())
|
|
OR NOT IS_PED_SITTING_IN_VEHICLE(Racer.Driver, Racer.Vehicle)
|
|
IF NOT SPTT_Blip_Entity_Create(Racer.Blip, Racer.Vehicle, bFriendly, fScale, Racer.szName)
|
|
DEBUG_MESSAGE("SPTT_Racer_Blip_Create: Failed to create racer vehicle blip!")
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF*/
|
|
IF (Racer.Driver <> PLAYER_PED_ID())
|
|
IF NOT SPTT_Blip_Entity_Create(Racer.Blip, Racer.Driver, bFriendly, fScale, Racer.szName)
|
|
DEBUG_MESSAGE("SPTT_Racer_Blip_Create: Failed to create racer driver blip!")
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
PROC SPTT_Racer_Blip_Destroy(SPTT_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("SPTT_Racer_Blip_Destroy")
|
|
SPTT_Blip_Destroy(Racer.Blip)
|
|
ENDPROC
|
|
|
|
FUNC BOOL SPTT_Racer_Create(SPTT_RACER_STRUCT& Racer, BOOL bForceCreate)
|
|
PRINTLN("[SPTT_Racer_Create] Function called.")
|
|
|
|
IF NOT SPTT_Racer_Vehicle_Create(Racer, bForceCreate)
|
|
OR NOT SPTT_Racer_Driver_Create(Racer)
|
|
PRINTLN("[SPTT_Racer_Create] Vehicle and driver both NOT yet created.")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
PRINTLN("[SPTT_Racer_Create] Vehicle and driver BOTH created.")
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
PROC SPTT_Racer_Freeze(SPTT_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("SPTT_Racer_Freeze")
|
|
SPTT_Racer_Driver_Freeze(Racer)
|
|
SPTT_Racer_Vehicle_Freeze(Racer)
|
|
ENDPROC
|
|
|
|
PROC SPTT_Racer_UnFreeze(SPTT_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("SPTT_Racer_UnFreeze")
|
|
SPTT_Racer_Driver_UnFreeze(Racer)
|
|
SPTT_Racer_Vehicle_UnFreeze(Racer)
|
|
ENDPROC
|
|
|
|
PROC SPTT_Racer_Release(SPTT_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("SPTT_Racer_Release")
|
|
SPTT_Racer_Blip_Destroy(Racer)
|
|
SPTT_Racer_Driver_Release(Racer)
|
|
SPTT_Racer_Vehicle_Release(Racer)
|
|
ENDPROC
|
|
|
|
PROC SPTT_Racer_Destroy(SPTT_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("SPTT_Racer_Destroy")
|
|
SPTT_Racer_Blip_Destroy(Racer)
|
|
SPTT_Racer_Driver_Destroy(Racer)
|
|
SPTT_Racer_Vehicle_Destroy(Racer)
|
|
ENDPROC
|
|
|
|
|
|
|
|
|
|
// -----------------------------------
|
|
// HELPER PROCS/FUNCTIONS
|
|
// -----------------------------------
|
|
|
|
FUNC BOOL SPTT_IS_PLANE_KNIFING(ENTITY_INDEX entKnifing)
|
|
VECTOR vFront, vSide, vUp, vPos
|
|
IF IS_ENTITY_DEAD(entKnifing)
|
|
RETURN FALSE
|
|
ENDIF
|
|
GET_ENTITY_MATRIX(entKnifing, vFront, vSide, vUp, vPos)
|
|
IF ABSF(vUp.z) > STUNT_PLANE_KNIFE_THRESHOLD
|
|
RETURN FALSE
|
|
ENDIF
|
|
RETURN vSide.z <> 0.0
|
|
ENDFUNC
|
|
|
|
FUNC BOOL SPTT_IS_PLANE_KNIFING_LEFT(ENTITY_INDEX entKnifing)
|
|
VECTOR vFront, vSide, vUp, vPos
|
|
IF IS_ENTITY_DEAD(entKnifing)
|
|
RETURN FALSE
|
|
ENDIF
|
|
GET_ENTITY_MATRIX(entKnifing, vFront, vSide, vUp, vPos)
|
|
IF ABSF(vUp.z) > STUNT_PLANE_KNIFE_THRESHOLD
|
|
RETURN FALSE
|
|
ENDIF
|
|
RETURN vSide.z > 0.0
|
|
ENDFUNC
|
|
|
|
FUNC BOOL SPTT_IS_PLANE_KNIFING_RIGHT(ENTITY_INDEX entKnifing)
|
|
VECTOR vFront, vSide, vUp, vPos
|
|
IF IS_ENTITY_DEAD(entKnifing)
|
|
RETURN FALSE
|
|
ENDIF
|
|
GET_ENTITY_MATRIX(entKnifing, vFront, vSide, vUp, vPos)
|
|
IF ABSF(vUp.z) > STUNT_PLANE_KNIFE_THRESHOLD
|
|
RETURN FALSE
|
|
ENDIF
|
|
RETURN vSide.z < 0.0
|
|
ENDFUNC
|
|
|
|
PROC SPTT_Racer_Teleport(SPTT_RACER_STRUCT& Racer, VECTOR vPos, FLOAT fHeading, FLOAT fSpeed)
|
|
PRINTLN("[SPTT_Racer_Teleport] Procedure started.")
|
|
|
|
SET_ENTITY_COORDS(Racer.Vehicle, vPos)
|
|
SET_ENTITY_HEADING(Racer.Vehicle, fHeading)
|
|
SET_VEHICLE_FORWARD_SPEED(Racer.Vehicle, fSpeed)
|
|
ENDPROC
|
|
|
|
PROC SPTT_Racer_Start(SPTT_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("SPTT_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, SPTT_VEH_STUCK_MIN_MOVE, SPTT_VEH_STUCK_CHK_TIME)
|
|
//ENDIF
|
|
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
PROC SPTT_Racer_Finish(SPTT_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("SPTT_Racer_Finish")
|
|
|
|
// Check if racer vehicle is alive.
|
|
IF NOT IS_ENTITY_DEAD(Racer.Vehicle)
|
|
IF SPTT_Master.eRaceType <> SPTT_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 SPTT_Racer_Stuck_Check(SPTT_RACER_STRUCT& Racer)
|
|
//DEBUG_MESSAGE("SPTT_Racer_Crash_Check")
|
|
IF (Racer.eVehicleModel <> DUMMY_MODEL_FOR_SCRIPT)
|
|
// 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, SPTT_VEH_STUCK_PLANE_ROOF_TIME)
|
|
DEBUG_MESSAGE("SPTT_Racer_Crash_Check: Vehicle stuck (roof)!")
|
|
RETURN TRUE
|
|
ENDIF
|
|
IF IS_VEHICLE_STUCK_TIMER_UP(Racer.Vehicle, VEH_STUCK_ON_SIDE, SPTT_VEH_STUCK_PLANE_SIDE_TIME)
|
|
DEBUG_MESSAGE("SPTT_Racer_Crash_Check: Vehicle stuck (side)!")
|
|
RETURN TRUE
|
|
ENDIF
|
|
IF IS_VEHICLE_STUCK_TIMER_UP(Racer.Vehicle, VEH_STUCK_HUNG_UP, SPTT_VEH_STUCK_PLANE_HUNG_TIME)
|
|
DEBUG_MESSAGE("SPTT_Racer_Crash_Check: Vehicle stuck (hung)!")
|
|
RETURN TRUE
|
|
ENDIF
|
|
IF IS_VEHICLE_STUCK_TIMER_UP(Racer.Vehicle, VEH_STUCK_JAMMED, SPTT_VEH_STUCK_PLANE_JAM_TIME)
|
|
DEBUG_MESSAGE("SPTT_Racer_Crash_Check: Vehicle stuck (jam)!")
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
//ENDIF
|
|
ENDIF
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
FUNC SPTT_RACE_GATE_STATUS SPTT_Racer_Gate_Check(SPTT_RACE_STRUCT& Race, SPTT_GATE_STRUCT& GateCur, SPTT_GATE_STRUCT& GateNxt, PED_INDEX pedDriver)
|
|
VECTOR vFront, vSide, vUp, vPos
|
|
|
|
#IF NOT DEFINED(bAudioPlayedLastGate)
|
|
BOOL bAudioPlayedLastGate
|
|
bAudioPlayedLastGate = bAudioPlayedLastGate
|
|
#ENDIF
|
|
|
|
IF IS_ENTITY_DEAD(Race.Racer[0].Vehicle)
|
|
RETURN SPTT_RACE_GATE_STATUS_INVALID
|
|
ENDIF
|
|
|
|
SPTT_RACE_GATE_STATUS status = SPTT_Gate_Check_Pass(GateCur, pedDriver)
|
|
|
|
IF (SPTT_Master.eRaceType = SPTT_RACE_TYPE_PLANE)
|
|
|
|
IF (status <> SPTT_RACE_GATE_STATUS_INCOMPLETE)
|
|
// INNER (PERFECT) RING CHECKS
|
|
IF (status = SPTT_RACE_GATE_STATUS_PASS_INNER)
|
|
// left roll
|
|
IF SPTT_IS_PLANE_KNIFING_LEFT(Race.Racer[0].Vehicle)
|
|
// Check if its a stunt gate
|
|
IF GateCur.eStuntType <> SPTT_RACE_STUNT_GATE_NORMAL
|
|
// check if its a KNIFE LEFT stunt gate
|
|
IF GateCur.eStuntType = SPTT_RACE_STUNT_GATE_SIDE_LEFT
|
|
// if left stunt gate, return successfull stunt
|
|
status = SPTT_RACE_GATE_STATUS_STUNT_KL
|
|
RETURN status
|
|
ENDIF
|
|
// check if its a KNIFE RIGHT stunt gate
|
|
IF GateCur.eStuntType = SPTT_RACE_STUNT_GATE_SIDE_RIGHT
|
|
// if right stunt gate, return hit
|
|
status = SPTT_RACE_GATE_STATUS_STUNT_KR_HIT
|
|
RETURN status
|
|
ENDIF
|
|
// check if its a INVERTED stunt gate
|
|
IF GateCur.eStuntType = SPTT_RACE_STUNT_GATE_INVERTED
|
|
// if inverted gate, return hit
|
|
status = SPTT_RACE_GATE_STATUS_STUNT_INV_HIT
|
|
RETURN status
|
|
ENDIF
|
|
ELSE
|
|
// check bits
|
|
status = SPTT_RACE_GATE_STATUS_KNIFE_INNER
|
|
// new perfect Knife
|
|
IF NOT IS_BITMASK_AS_ENUM_SET(iStuntGateHit, P_Knife_Once)
|
|
// play audio
|
|
Play_Gate_Audio("Gate_PK", iPerfKniGateBits)
|
|
// clear then set audio tracking bit (done on all first hits to reset consecutives for all audio bits)
|
|
iStuntGateHit = 0
|
|
SET_BITMASK_AS_ENUM(iStuntGateHit, P_Knife_Once)
|
|
RETURN status
|
|
ELSE
|
|
// hit 2 perfect Knife in a row
|
|
IF NOT IS_BITMASK_AS_ENUM_SET(iStuntGateHit, P_Knife_Twice)
|
|
// consecutive audio
|
|
Play_Gate_Audio("Con_PK", iPerfKniGateBits)
|
|
SET_BITMASK_AS_ENUM(iStuntGateHit, P_Knife_Twice)
|
|
RETURN status
|
|
ELSE
|
|
// hit 3 perfect Knife in a row
|
|
IF NOT IS_BITMASK_AS_ENUM_SET(iStuntGateHit, P_Knife_Third)
|
|
// consecutive audio
|
|
Play_Gate_Audio("Con_PK", iPerfKniGateBits)
|
|
SET_BITMASK_AS_ENUM(iStuntGateHit, P_Knife_Third)
|
|
RETURN status
|
|
ELSE // 4 or more perfect Knife in a row
|
|
// consecutive audio
|
|
Play_Gate_Audio("Con_PK", iPerfKniGateBits)
|
|
RETURN status
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
// right roll
|
|
ELIF SPTT_IS_PLANE_KNIFING_RIGHT(Race.Racer[0].Vehicle)
|
|
PRINTLN("SPTT_Racer_Gate_Check: plane is rolled right")
|
|
// Check if its a stunt gate
|
|
IF GateCur.eStuntType <> SPTT_RACE_STUNT_GATE_NORMAL
|
|
// check if its a KNIFE RIGHT stunt gate
|
|
IF GateCur.eStuntType = SPTT_RACE_STUNT_GATE_SIDE_RIGHT
|
|
// if right stunt gate, return successfull stunt
|
|
status = SPTT_RACE_GATE_STATUS_STUNT_KR
|
|
RETURN status
|
|
ENDIF
|
|
// check if its a KNIFE LEFT stunt gate
|
|
IF GateCur.eStuntType = SPTT_RACE_STUNT_GATE_SIDE_LEFT
|
|
// if left stunt gate, return hit
|
|
status = SPTT_RACE_GATE_STATUS_STUNT_KL_HIT
|
|
RETURN status
|
|
ENDIF
|
|
// check if its a INVERTED stunt gate
|
|
IF GateCur.eStuntType = SPTT_RACE_STUNT_GATE_INVERTED
|
|
// if inverted gate, return hit
|
|
status = SPTT_RACE_GATE_STATUS_STUNT_INV_HIT
|
|
RETURN status
|
|
ENDIF
|
|
ELSE
|
|
status = SPTT_RACE_GATE_STATUS_KNIFE_INNER
|
|
// new perfect Knife
|
|
IF NOT IS_BITMASK_AS_ENUM_SET(iStuntGateHit, P_Knife_Once)
|
|
// play audio
|
|
Play_Gate_Audio("Gate_PK", iPerfKniGateBits)
|
|
// clear then set audio tracking bit (done on all first hits to reset consecutives for all audio bits)
|
|
iStuntGateHit = 0
|
|
SET_BITMASK_AS_ENUM(iStuntGateHit, P_Knife_Once)
|
|
RETURN status
|
|
ELSE
|
|
// hit 2 perfect Knife in a row
|
|
IF NOT IS_BITMASK_AS_ENUM_SET(iStuntGateHit, P_Knife_Twice)
|
|
// consecutive audio
|
|
Play_Gate_Audio("Con_PK", iPerfKniGateBits)
|
|
SET_BITMASK_AS_ENUM(iStuntGateHit, P_Knife_Twice)
|
|
RETURN status
|
|
ELSE
|
|
// hit 3 perfect Knife in a row
|
|
IF NOT IS_BITMASK_AS_ENUM_SET(iStuntGateHit, P_Knife_Third)
|
|
// consecutive audio
|
|
Play_Gate_Audio("Con_PK", iPerfKniGateBits)
|
|
SET_BITMASK_AS_ENUM(iStuntGateHit, P_Knife_Third)
|
|
RETURN status
|
|
ELSE
|
|
// 4 or more perfect Knife in a row
|
|
// consecutive audio
|
|
Play_Gate_Audio("Con_PK", iPerfKniGateBits)
|
|
RETURN status
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
// Inverted
|
|
ELSE
|
|
GET_ENTITY_MATRIX(Race.Racer[0].Vehicle, vFront, vSide, vUp, vPos)
|
|
IF vUp.z <= SPTT_STUNT_INVERT_THRESHOLD
|
|
// Check if its a stunt gate
|
|
IF GateCur.eStuntType <> SPTT_RACE_STUNT_GATE_NORMAL
|
|
// check if its a INVERTED stunt gate
|
|
IF GateCur.eStuntType = SPTT_RACE_STUNT_GATE_INVERTED
|
|
// if inverted stunt gate, return successfull stunt
|
|
status = SPTT_RACE_GATE_STATUS_STUNT_INV
|
|
RETURN status
|
|
ENDIF
|
|
// check if its a KNIFE LEFT stunt gate
|
|
IF GateCur.eStuntType = SPTT_RACE_STUNT_GATE_SIDE_LEFT
|
|
// if left stunt gate, return hit
|
|
status = SPTT_RACE_GATE_STATUS_STUNT_KL_HIT
|
|
RETURN status
|
|
ENDIF
|
|
// check if its a KNIFE RIGHT stunt gate
|
|
IF GateCur.eStuntType = SPTT_RACE_STUNT_GATE_SIDE_RIGHT
|
|
// if right stunt gate, return hit
|
|
status = SPTT_RACE_GATE_STATUS_STUNT_KR_HIT
|
|
RETURN status
|
|
ENDIF
|
|
ELSE
|
|
// check bits
|
|
status = SPTT_RACE_GATE_STATUS_INVERT_INNER
|
|
// new perfect Inverted
|
|
IF NOT IS_BITMASK_AS_ENUM_SET(iStuntGateHit, P_Inverted_Once)
|
|
// play audio
|
|
Play_Gate_Audio("Gate_PI", iPerfInvGateBits)
|
|
// clear then set audio tracking bit (done on all first hits to reset consecutives for all audio bits)
|
|
iStuntGateHit = 0
|
|
SET_BITMASK_AS_ENUM(iStuntGateHit, P_Inverted_Once)
|
|
RETURN status
|
|
ELSE
|
|
// hit 2 perfect Inverted in a row
|
|
IF NOT IS_BITMASK_AS_ENUM_SET(iStuntGateHit, P_Inverted_Twice)
|
|
// consecutive audio
|
|
Play_Gate_Audio("Con_PI", iPerfInvGateBits)
|
|
SET_BITMASK_AS_ENUM(iStuntGateHit, P_Inverted_Twice)
|
|
RETURN status
|
|
ELSE
|
|
// hit 3 perfect Inverted in a row
|
|
IF NOT IS_BITMASK_AS_ENUM_SET(iStuntGateHit, P_Inverted_Third)
|
|
// consecutive audio
|
|
Play_Gate_Audio("Con_PI", iPerfInvGateBits)
|
|
SET_BITMASK_AS_ENUM(iStuntGateHit, P_Inverted_Third)
|
|
RETURN status
|
|
ELSE
|
|
// 4 or more perfect Inverted in a row
|
|
// consecutive audio
|
|
Play_Gate_Audio("Con_PI", iPerfInvGateBits)
|
|
RETURN status
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ELSE // Flew through gate normally
|
|
// if its a stunt gate
|
|
IF GateCur.eStuntType <> SPTT_RACE_STUNT_GATE_NORMAL
|
|
IF GateCur.eStuntType = SPTT_RACE_STUNT_GATE_SIDE_LEFT
|
|
status = SPTT_RACE_GATE_STATUS_STUNT_KL_HIT
|
|
RETURN status
|
|
ELIF GateCur.eStuntType = SPTT_RACE_STUNT_GATE_SIDE_RIGHT
|
|
status = SPTT_RACE_GATE_STATUS_STUNT_KR_HIT
|
|
RETURN status
|
|
ELIF GateCur.eStuntType = SPTT_RACE_STUNT_GATE_INVERTED
|
|
status = SPTT_RACE_GATE_STATUS_STUNT_INV_HIT
|
|
RETURN status
|
|
ENDIF
|
|
ELSE
|
|
status = SPTT_RACE_GATE_STATUS_PASS_INNER
|
|
// new perfect Knife
|
|
IF NOT IS_BITMASK_AS_ENUM_SET(iStuntGateHit, Perfect_Once)
|
|
// play audio
|
|
Play_Gate_Audio("Get_Perf", iPerfectGateBits)
|
|
// clear then set audio tracking bit (done on all first hits to reset consecutives for all audio bits)
|
|
iStuntGateHit = 0
|
|
SET_BITMASK_AS_ENUM(iStuntGateHit, Perfect_Once)
|
|
RETURN status
|
|
ELSE
|
|
// hit 2 perfect in a row
|
|
IF NOT IS_BITMASK_AS_ENUM_SET(iStuntGateHit, Perfect_Twice)
|
|
// consecutive audio
|
|
Play_Gate_Audio("Con_Perf", iPerfectGateBits)
|
|
SET_BITMASK_AS_ENUM(iStuntGateHit, Perfect_Twice)
|
|
RETURN status
|
|
ELSE
|
|
// hit 3 perfect in a row
|
|
IF NOT IS_BITMASK_AS_ENUM_SET(iStuntGateHit, Perfect_Third)
|
|
// consecutive audio
|
|
Play_Gate_Audio("Con_Perf", iPerfectGateBits)
|
|
SET_BITMASK_AS_ENUM(iStuntGateHit, Perfect_Third)
|
|
RETURN status
|
|
ELSE
|
|
// 4 or more perfect in a row
|
|
// consecutive audio
|
|
Play_Gate_Audio("Con_Perf", iPerfectGateBits)
|
|
RETURN status
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
// OUTTER RING CHECKS
|
|
IF (status = SPTT_RACE_GATE_STATUS_PASS_OUTTER)
|
|
// knife left check
|
|
IF SPTT_IS_PLANE_KNIFING_LEFT(Race.Racer[0].Vehicle)
|
|
// Check if its a stunt gate
|
|
IF GateCur.eStuntType <> SPTT_RACE_STUNT_GATE_NORMAL
|
|
// check if its a KNIFE LEFT stunt gate
|
|
IF GateCur.eStuntType = SPTT_RACE_STUNT_GATE_SIDE_LEFT
|
|
// if left stunt gate, return successfull stunt
|
|
status = SPTT_RACE_GATE_STATUS_STUNT_KL
|
|
RETURN status
|
|
ENDIF
|
|
// check if its a KNIFE RIGHT stunt gate
|
|
IF GateCur.eStuntType = SPTT_RACE_STUNT_GATE_SIDE_RIGHT
|
|
// if right stunt gate, return hit
|
|
status = SPTT_RACE_GATE_STATUS_STUNT_KR_HIT
|
|
RETURN status
|
|
ENDIF
|
|
// check if its a INVERTED stunt gate
|
|
IF GateCur.eStuntType = SPTT_RACE_STUNT_GATE_INVERTED
|
|
// if inverted gate, return hit
|
|
status = SPTT_RACE_GATE_STATUS_STUNT_INV_HIT
|
|
RETURN status
|
|
ENDIF
|
|
ELSE
|
|
// check bits
|
|
status = SPTT_RACE_GATE_STATUS_KNIFE_OUTTER
|
|
// new knife
|
|
IF NOT IS_BITMASK_AS_ENUM_SET(iStuntGateHit, Knife_Once)
|
|
// play audio
|
|
Play_Gate_Audio("Gate_Kni", iKnifeGateBits)
|
|
// clear then set audio tracking bit (done on all first hits to reset consecutives for all audio bits)
|
|
iStuntGateHit = 0
|
|
SET_BITMASK_AS_ENUM(iStuntGateHit, Knife_Once)
|
|
RETURN status
|
|
ELSE
|
|
// hit 2 Knife in a row
|
|
IF NOT IS_BITMASK_AS_ENUM_SET(iStuntGateHit, Knife_Twice)
|
|
// consecutive audio
|
|
Play_Gate_Audio("Con_Kni", iKnifeGateBits)
|
|
SET_BITMASK_AS_ENUM(iStuntGateHit, Knife_Twice)
|
|
RETURN status
|
|
ELSE
|
|
// hit 3 Knife in a row
|
|
IF NOT IS_BITMASK_AS_ENUM_SET(iStuntGateHit, Knife_Third)
|
|
// consecutive audio
|
|
Play_Gate_Audio("Con_Kni", iKnifeGateBits)
|
|
SET_BITMASK_AS_ENUM(iStuntGateHit, Knife_Third)
|
|
RETURN status
|
|
ELSE
|
|
// 4 or more Knife in a row
|
|
// consecutive audio
|
|
Play_Gate_Audio("Con_Kni", iKnifeGateBits)
|
|
RETURN status
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ELIF SPTT_IS_PLANE_KNIFING_RIGHT(Race.Racer[0].Vehicle)
|
|
// Check if its a stunt gate
|
|
IF GateCur.eStuntType <> SPTT_RACE_STUNT_GATE_NORMAL
|
|
// check if its a KNIFE RIGHT stunt gate
|
|
IF GateCur.eStuntType = SPTT_RACE_STUNT_GATE_SIDE_RIGHT
|
|
// if right stunt gate, return successfull stunt
|
|
status = SPTT_RACE_GATE_STATUS_STUNT_KR
|
|
RETURN status
|
|
ENDIF
|
|
// check if its a KNIFE LEFT stunt gate
|
|
IF GateCur.eStuntType = SPTT_RACE_STUNT_GATE_SIDE_LEFT
|
|
// if left stunt gate, return hit
|
|
status = SPTT_RACE_GATE_STATUS_STUNT_KL_HIT
|
|
RETURN status
|
|
ENDIF
|
|
// check if its a INVERTED stunt gate
|
|
IF GateCur.eStuntType = SPTT_RACE_STUNT_GATE_INVERTED
|
|
// if inverted gate, return hit
|
|
status = SPTT_RACE_GATE_STATUS_STUNT_INV_HIT
|
|
RETURN status
|
|
ENDIF
|
|
ELSE
|
|
// check bits
|
|
status = SPTT_RACE_GATE_STATUS_KNIFE_OUTTER
|
|
// new knife
|
|
IF NOT IS_BITMASK_AS_ENUM_SET(iStuntGateHit, Knife_Once)
|
|
// play audio
|
|
Play_Gate_Audio("Gate_Kni", iKnifeGateBits)
|
|
// clear then set audio tracking bit (done on all first hits to reset consecutives for all audio bits)
|
|
iStuntGateHit = 0
|
|
SET_BITMASK_AS_ENUM(iStuntGateHit, Knife_Once)
|
|
RETURN status
|
|
ELSE
|
|
// hit 2 Knife in a row
|
|
IF NOT IS_BITMASK_AS_ENUM_SET(iStuntGateHit, Knife_Twice)
|
|
// consecutive audio
|
|
Play_Gate_Audio("Con_Kni", iKnifeGateBits)
|
|
SET_BITMASK_AS_ENUM(iStuntGateHit, Knife_Twice)
|
|
RETURN status
|
|
ELSE
|
|
// hit 3 Knife in a row
|
|
IF NOT IS_BITMASK_AS_ENUM_SET(iStuntGateHit, Knife_Third)
|
|
// consecutive audio
|
|
Play_Gate_Audio("Con_Kni", iKnifeGateBits)
|
|
SET_BITMASK_AS_ENUM(iStuntGateHit, Knife_Third)
|
|
RETURN status
|
|
ELSE
|
|
// 4 or more Knife in a row
|
|
// consecutive audio
|
|
Play_Gate_Audio("Con_Kni", iKnifeGateBits)
|
|
RETURN status
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
GET_ENTITY_MATRIX(Race.Racer[0].Vehicle, vFront, vSide, vUp, vPos)
|
|
IF vUp.z <= SPTT_STUNT_INVERT_THRESHOLD
|
|
// Check if its a stunt gate
|
|
IF GateCur.eStuntType <> SPTT_RACE_STUNT_GATE_NORMAL
|
|
// check if its a INVERTED stunt gate
|
|
IF GateCur.eStuntType = SPTT_RACE_STUNT_GATE_INVERTED
|
|
// if inverted gate, return successful stunt
|
|
status = SPTT_RACE_GATE_STATUS_STUNT_INV
|
|
RETURN status
|
|
ENDIF
|
|
// check if its a KNIFE LEFT stunt gate
|
|
IF GateCur.eStuntType = SPTT_RACE_STUNT_GATE_SIDE_LEFT
|
|
// if left stunt gate, return successfull stunt
|
|
status = SPTT_RACE_GATE_STATUS_STUNT_KL
|
|
RETURN status
|
|
ENDIF
|
|
// check if its a KNIFE RIGHT stunt gate
|
|
IF GateCur.eStuntType = SPTT_RACE_STUNT_GATE_SIDE_RIGHT
|
|
// if right stunt gate, return hit
|
|
status = SPTT_RACE_GATE_STATUS_STUNT_KR_HIT
|
|
RETURN status
|
|
ENDIF
|
|
ELSE
|
|
// check bits
|
|
status = SPTT_RACE_GATE_STATUS_INVERT_OUTTER
|
|
// new Inverted
|
|
IF NOT IS_BITMASK_AS_ENUM_SET(iStuntGateHit, Inverted_Once)
|
|
// play audio
|
|
Play_Gate_Audio("Gate_Inv", iInvertedGateBits)
|
|
// clear then set audio tracking bit (done on all first hits to reset consecutives for all audio bits)
|
|
iStuntGateHit = 0
|
|
SET_BITMASK_AS_ENUM(iStuntGateHit, Inverted_Once)
|
|
RETURN status
|
|
ELSE
|
|
// hit 2 Inverted in a row
|
|
IF NOT IS_BITMASK_AS_ENUM_SET(iStuntGateHit, Inverted_Twice)
|
|
// consecutive audio
|
|
Play_Gate_Audio("Con_Inv", iInvertedGateBits)
|
|
// set audio tracking bit
|
|
SET_BITMASK_AS_ENUM(iStuntGateHit, Inverted_Twice)
|
|
RETURN status
|
|
ELSE
|
|
// Hit 3 Inverted in a row
|
|
IF NOT IS_BITMASK_AS_ENUM_SET(iStuntGateHit, Inverted_Third)
|
|
// consecutive audio
|
|
Play_Gate_Audio("Con_Inv", iInvertedGateBits)
|
|
SET_BITMASK_AS_ENUM(iStuntGateHit, Inverted_Third)
|
|
RETURN status
|
|
ELSE
|
|
// hit 4 or more Inverted in a row
|
|
// consecutive audio
|
|
Play_Gate_Audio("Con_Inv", iInvertedGateBits)
|
|
RETURN status
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ELSE
|
|
// if its a stunt gate
|
|
IF GateCur.eStuntType <> SPTT_RACE_STUNT_GATE_NORMAL
|
|
IF GateCur.eStuntType = SPTT_RACE_STUNT_GATE_SIDE_LEFT
|
|
status = SPTT_RACE_GATE_STATUS_STUNT_KL_HIT
|
|
RETURN status
|
|
ELIF GateCur.eStuntType = SPTT_RACE_STUNT_GATE_SIDE_RIGHT
|
|
status = SPTT_RACE_GATE_STATUS_STUNT_KR_HIT
|
|
RETURN status
|
|
ELIF GateCur.eStuntType = SPTT_RACE_STUNT_GATE_INVERTED
|
|
status = SPTT_RACE_GATE_STATUS_STUNT_INV_HIT
|
|
RETURN status
|
|
ENDIF
|
|
ELSE
|
|
// check bits
|
|
status = SPTT_RACE_GATE_STATUS_PASS_OUTTER
|
|
// New Gate Hit
|
|
IF NOT IS_BITMASK_AS_ENUM_SET(iStuntGateHit, Hit_Once)
|
|
// play audio
|
|
Play_Gate_Audio("Gate_Hit", iClearedGateBits)
|
|
// clear then set audio tracking bit (done on all first hits to reset consecutives for all audio bits)
|
|
iStuntGateHit = 0
|
|
SET_BITMASK_AS_ENUM(iStuntGateHit, Hit_Once)
|
|
RETURN status
|
|
ELSE
|
|
// hit 2 Gates in a row
|
|
IF NOT IS_BITMASK_AS_ENUM_SET(iStuntGateHit, Hit_Twice)
|
|
// consecutive audio
|
|
Play_Gate_Audio("Con_Hit", iClearedGateBits)
|
|
SET_BITMASK_AS_ENUM(iStuntGateHit, Hit_Twice)
|
|
RETURN status
|
|
ELSE
|
|
// hit 3 Gates in a row
|
|
IF NOT IS_BITMASK_AS_ENUM_SET(iStuntGateHit, Hit_Third)
|
|
// consecutive audio
|
|
Play_Gate_Audio("Con_Hit", iClearedGateBits)
|
|
SET_BITMASK_AS_ENUM(iStuntGateHit, Hit_Third)
|
|
RETURN status
|
|
ELSE
|
|
// Hit 4 or more Gates in a row
|
|
// consecutive audio
|
|
Play_Gate_Audio("Con_Hit", iClearedGateBits)
|
|
RETURN status
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
IF SPTT_Gate_Check_Miss(GateCur, GateNxt, pedDriver)
|
|
// Check if its a stunt gate
|
|
IF GateCur.eStuntType <> SPTT_RACE_STUNT_GATE_NORMAL
|
|
// check if its a knife left stunt gate
|
|
IF GateCur.eStuntType = SPTT_RACE_STUNT_GATE_SIDE_LEFT
|
|
// missed the knife left stunt gate
|
|
status = SPTT_RACE_GATE_STATUS_STUNT_KL_MISS
|
|
RETURN status
|
|
ENDIF
|
|
// check if its a knife right stunt gate
|
|
IF GateCur.eStuntType = SPTT_RACE_STUNT_GATE_SIDE_RIGHT
|
|
// missed the knife right stunt gate
|
|
status = SPTT_RACE_GATE_STATUS_STUNT_KR_MISS
|
|
RETURN status
|
|
ENDIF
|
|
// check if its a INVERTED stunt gate
|
|
IF GateCur.eStuntType = SPTT_RACE_STUNT_GATE_INVERTED
|
|
// if inverted stunt gate, return successfull stunt
|
|
status = SPTT_RACE_GATE_STATUS_STUNT_INV_MISS
|
|
RETURN status
|
|
ENDIF
|
|
ELSE
|
|
status = SPTT_RACE_GATE_STATUS_MISSED_GATE
|
|
// new Missed Gate
|
|
IF NOT IS_BITMASK_AS_ENUM_SET(iStuntGateHit, Missed_Once)
|
|
// play audio
|
|
Play_Gate_Audio("Gate_Miss", iMissedGateBits)
|
|
// clear then set audio tracking bit (done on all first hits to reset consecutives for all audio bits)
|
|
iStuntGateHit = 0
|
|
SET_BITMASK_AS_ENUM(iStuntGateHit, Missed_Once)
|
|
RETURN status
|
|
ELSE
|
|
// Missed 2 Gates in a row
|
|
IF NOT IS_BITMASK_AS_ENUM_SET(iStuntGateHit, Missed_Twice)
|
|
// consecutive audio
|
|
Play_Gate_Audio("Con_Miss", iMissedGateBits)
|
|
SET_BITMASK_AS_ENUM(iStuntGateHit, Missed_Twice)
|
|
RETURN status
|
|
ELSE
|
|
// Missed 3 Gates in a row
|
|
IF NOT IS_BITMASK_AS_ENUM_SET(iStuntGateHit, Missed_Third)
|
|
// consecutive audio
|
|
Play_Gate_Audio("Con_Miss", iMissedGateBits)
|
|
SET_BITMASK_AS_ENUM(iStuntGateHit, Missed_Third)
|
|
RETURN status
|
|
ELSE
|
|
// Missed 4 or more Gates in a row
|
|
// consecutive audio
|
|
Play_Gate_Audio("Con_Miss", iMissedGateBits)
|
|
RETURN status
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
RETURN status
|
|
ENDIF
|
|
IF SPTT_Gate_Check_Miss(GateCur, GateNxt, pedDriver)
|
|
// Check if its a stunt gate
|
|
IF GateCur.eStuntType <> SPTT_RACE_STUNT_GATE_NORMAL
|
|
// check if its a knife left stunt gate
|
|
IF GateCur.eStuntType = SPTT_RACE_STUNT_GATE_SIDE_LEFT
|
|
// missed the knife left stunt gate
|
|
status = SPTT_RACE_GATE_STATUS_STUNT_KL_MISS
|
|
RETURN status
|
|
ENDIF
|
|
// check if its a knife right stunt gate
|
|
IF GateCur.eStuntType = SPTT_RACE_STUNT_GATE_SIDE_RIGHT
|
|
// missed the knife right stunt gate
|
|
status = SPTT_RACE_GATE_STATUS_STUNT_KR_MISS
|
|
RETURN status
|
|
ENDIF
|
|
// check if its a INVERTED stunt gate
|
|
IF GateCur.eStuntType = SPTT_RACE_STUNT_GATE_INVERTED
|
|
// if inverted stunt gate, return successfull stunt
|
|
status = SPTT_RACE_GATE_STATUS_STUNT_INV_MISS
|
|
RETURN status
|
|
ENDIF
|
|
ELSE
|
|
// check bits
|
|
status = SPTT_RACE_GATE_STATUS_MISSED_GATE
|
|
// new Missed Gate
|
|
IF NOT IS_BITMASK_AS_ENUM_SET(iStuntGateHit, Missed_Once)
|
|
// play audio
|
|
Play_Gate_Audio("Gate_Miss", iMissedGateBits)
|
|
// clear then set audio tracking bit (done on all first hits to reset consecutives for all audio bits)
|
|
iStuntGateHit = 0
|
|
SET_BITMASK_AS_ENUM(iStuntGateHit, Missed_Once)
|
|
RETURN status
|
|
ELSE
|
|
// Missed 2 Gates in a row
|
|
IF NOT IS_BITMASK_AS_ENUM_SET(iStuntGateHit, Missed_Twice)
|
|
// consecutive audio
|
|
Play_Gate_Audio("Con_Miss", iMissedGateBits)
|
|
SET_BITMASK_AS_ENUM(iStuntGateHit, Missed_Twice)
|
|
RETURN status
|
|
ELSE
|
|
// Missed 3 Gates in a row
|
|
IF NOT IS_BITMASK_AS_ENUM_SET(iStuntGateHit, Missed_Third)
|
|
// consecutive audio
|
|
Play_Gate_Audio("Con_Miss", iMissedGateBits)
|
|
SET_BITMASK_AS_ENUM(iStuntGateHit, Missed_Third)
|
|
RETURN status
|
|
ELSE
|
|
// Missed 4 or more Gates in a row
|
|
// consecutive audio
|
|
Play_Gate_Audio("Con_Miss", iMissedGateBits)
|
|
RETURN status
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
RETURN status
|
|
ENDIF
|
|
ELIF status != SPTT_RACE_GATE_STATUS_INCOMPLETE
|
|
RETURN status
|
|
ENDIF
|
|
|
|
RETURN SPTT_RACE_GATE_STATUS_INVALID
|
|
ENDFUNC
|
|
|
|
|
|
// END OF FILE! DO NOT ADD ANYTHING BELOW THIS LINE!
|