372 lines
11 KiB
Scheme
Executable File
372 lines
11 KiB
Scheme
Executable File
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
//
|
|
// FILE NAME : rc_leadin_public.sch
|
|
// AUTHOR : Aaron Gandaa
|
|
// DESCRIPTION : Helper Stuff for leadins
|
|
//
|
|
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
|
|
//----------------------
|
|
// INCLUDES
|
|
//----------------------
|
|
USING "rgeneral_include.sch"
|
|
USING "RC_Helper_Functions.sch"
|
|
|
|
//----------------------
|
|
// STRUCTS
|
|
//----------------------
|
|
STRUCT LEADIN_HANDLER
|
|
VECTOR vSyncScenePos
|
|
VECTOR vSyncSceneRot
|
|
|
|
STRING sLeadInDictionary
|
|
STRING sLeadInAnims[4]
|
|
STRING sIdleAnim
|
|
|
|
INT iCurrentLeadIn
|
|
INT iMaxLeadIn // total # of lead in lines
|
|
|
|
INT iAnimsPlayed // number of lines played
|
|
INT iLeadsInPlayedFlag // bit set telling us which ones have been chosen
|
|
|
|
INT iWaitTimer
|
|
INT iMinWaitTime = 0
|
|
INT iMaxWaitTime = 0
|
|
INT iState
|
|
|
|
INT iSyncSceneID = -1
|
|
FLOAT fCloseBreakOutDist = 0.0
|
|
ENDSTRUCT
|
|
|
|
//----------------------
|
|
// FUNCTIONS
|
|
//----------------------
|
|
|
|
|
|
PROC RESET_LEADIN_HANDLER(LEADIN_HANDLER &lead)
|
|
INT i
|
|
|
|
REPEAT COUNT_OF(lead.sLeadInAnims) i
|
|
lead.sLeadInAnims[i] = NULL
|
|
ENDREPEAT
|
|
|
|
lead.iMaxLeadIn = 0
|
|
lead.iCurrentLeadIn = -1
|
|
lead.sLeadInDictionary = NULL
|
|
|
|
lead.iAnimsPlayed = 0
|
|
lead.iLeadsInPlayedFlag = 0
|
|
lead.vSyncScenePos = <<0, 0, 0>>
|
|
lead.vSyncSceneRot = <<0, 0, 0>>
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Add Lead in Anim to list
|
|
/// PARAMS:
|
|
/// lead - lead in handler
|
|
/// str - anim name
|
|
PROC ADD_LEADIN_ANIM(LEADIN_HANDLER &lead, STRING str)
|
|
IF (lead.iMaxLeadIn >= COUNT_OF(lead.sLeadInAnims))
|
|
SCRIPT_ASSERT("YOU NEED TO INCREASE sLeadInAnims in LEADIN_HANDLER")
|
|
ENDIF
|
|
|
|
|
|
IF IS_STRING_NULL_OR_EMPTY(str)
|
|
EXIT
|
|
ENDIF
|
|
lead.sLeadInAnims[lead.iMaxLeadIn] = str
|
|
lead.iMaxLeadIn ++
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Restarts the lead in
|
|
/// PARAMS:
|
|
/// lead - lead in handler
|
|
PROC RESTART_LEAD_IN(LEADIN_HANDLER &lead)
|
|
lead.iCurrentLeadIn = -1
|
|
lead.iAnimsPlayed = 0
|
|
lead.iLeadsInPlayedFlag = 0
|
|
lead.iState = 0
|
|
lead.iSyncSceneID = -1
|
|
|
|
IF NOT IS_VECTOR_ZERO(lead.vSyncScenePos)
|
|
lead.iSyncSceneID = CREATE_SYNCHRONIZED_SCENE(lead.vSyncScenePos, lead.vSyncSceneRot)
|
|
CPRINTLN(DEBUG_MISSION, "LEADIN - SYNCHRONIZED SCENE CREATED")
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Sets Anim Idle Of Lead In
|
|
/// PARAMS:
|
|
/// lead - lead in handler
|
|
/// str - anim name
|
|
/// idleMinWait - min time to do idle
|
|
/// idleMaxWait - max time to do idle
|
|
PROC SET_LEADIN_IDLE_ANIM(LEADIN_HANDLER &lead, STRING str, INT idleMinWait = 0, INT idleMaxWait = 0)
|
|
IF IS_STRING_NULL_OR_EMPTY(str)
|
|
EXIT
|
|
ENDIF
|
|
lead.sIdleAnim = str
|
|
lead.iMinWaitTime = idleMinWait
|
|
lead.iMaxWaitTime = idleMaxWait
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Sets position and rotation of lead in sync scene
|
|
/// PARAMS:
|
|
/// lead - lead in handler
|
|
/// vp - position of scene
|
|
/// vs - rotation of scene
|
|
PROC SET_LEADIN_SYNC_SCENE_COORDS(LEADIN_HANDLER &lead, VECTOR vp, VECTOR vs)
|
|
lead.vSyncScenePos = vp
|
|
lead.vSyncSceneRot = vs
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Loads the lead anim dict
|
|
/// PARAMS:
|
|
/// lead - lead in handler
|
|
/// str - anim dictionaru
|
|
/// RETURNS:
|
|
/// returns false if it timesout or str is null
|
|
FUNC BOOL LOAD_LEADIN_ANIMDICT(LEADIN_HANDLER &lead, STRING str)
|
|
INT iTimer = GET_GAME_TIMER() + 10000
|
|
|
|
IF IS_STRING_NULL_OR_EMPTY(str)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
REQUEST_ANIM_DICT(str)
|
|
WHILE NOT HAS_ANIM_DICT_LOADED(str)
|
|
IF (GET_GAME_TIMER() > iTimer)
|
|
CPRINTLN(DEBUG_MISSION, "LEADIN ANIMDICT LOAD FAILED:", str, " TIME OUT")
|
|
RETURN FALSE
|
|
ENDIF
|
|
WAIT(0)
|
|
ENDWHILE
|
|
|
|
lead.sLeadInDictionary = str
|
|
CPRINTLN(DEBUG_MISSION, "LEADIN ANIMDICT LOAD SUCCESS:", str)
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Unloads the current lead in anim
|
|
/// PARAMS:
|
|
/// lead - lead in handler
|
|
PROC UNLOAD_LEADIN_ANIMDICT(LEADIN_HANDLER &lead)
|
|
IF IS_STRING_NULL_OR_EMPTY(lead.sLeadInDictionary)
|
|
EXIT
|
|
ENDIF
|
|
|
|
IF HAS_ANIM_DICT_LOADED(lead.sLeadInDictionary)
|
|
CPRINTLN(DEBUG_MISSION, "LEADIN ANIMDICT UNLOADED:", lead.sLeadInDictionary)
|
|
REMOVE_ANIM_DICT(lead.sLeadInDictionary)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Checks to see if a ped can play the leadin
|
|
/// PARAMS:
|
|
/// ped - ped playing the leading
|
|
/// lead - lead in handler
|
|
/// dist - distance from player before leadin kicks in
|
|
/// angle - angle that player has to be to ped before leadin kicks in
|
|
/// RETURNS:
|
|
///
|
|
FUNC BOOL CAN_PED_PLAY_LEADIN(PED_INDEX ped, LEADIN_HANDLER &lead, FLOAT dist = 30.0, FLOAT angle = 0.0)
|
|
IF NOT DOES_ENTITY_EXIST(ped)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF IS_ENTITY_DEAD(ped)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF IS_STRING_NULL_OR_EMPTY(lead.sLeadInDictionary)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF (dist > 0.0)
|
|
IF (GET_DISTANCE_BETWEEN_ENTITIES(ped, PLAYER_PED_ID()) > dist)
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF (angle > 0.0)
|
|
ENDIF
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Starts plays the next lead idle
|
|
/// PARAMS:
|
|
/// lead - lead in handler
|
|
/// ped - ped playing the leading
|
|
PROC PLAY_LEAD_IN_IDLE(LEADIN_HANDLER &lead, PED_INDEX ped)
|
|
IF IS_STRING_NULL_OR_EMPTY(lead.sIdleAnim)
|
|
EXIT
|
|
ENDIF
|
|
|
|
IF (lead.iSyncSceneID <> -1)
|
|
IF NOT IS_SYNCHRONIZED_SCENE_RUNNING(lead.iSyncSceneID)
|
|
lead.iSyncSceneID = CREATE_SYNCHRONIZED_SCENE(lead.vSyncScenePos, lead.vSyncSceneRot)
|
|
ENDIF
|
|
|
|
TASK_SYNCHRONIZED_SCENE(ped, lead.iSyncSceneID, lead.sLeadInDictionary, lead.sIdleAnim, NORMAL_BLEND_IN, NORMAL_BLEND_OUT)
|
|
SET_SYNCHRONIZED_SCENE_LOOPED(lead.iSyncSceneID, TRUE)
|
|
SET_SYNCHRONIZED_SCENE_HOLD_LAST_FRAME(lead.iSyncSceneID, FALSE)
|
|
CPRINTLN(DEBUG_MISSION, "PLAYING SYNCHED LEAD IN IDLE:", lead.sIdleAnim, " GAME TIME:", GET_GAME_TIMER())
|
|
ELSE
|
|
TASK_PLAY_ANIM(ped, lead.sLeadInDictionary, lead.sIdleAnim, NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_LOOPING)
|
|
CPRINTLN(DEBUG_MISSION, "PLAYING LEAD IN IDLE:", lead.sIdleAnim, " GAME TIME:", GET_GAME_TIMER())
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Starts playing the next lead in
|
|
/// PARAMS:
|
|
/// lead - lead in handler
|
|
/// ped - ped playing the leading
|
|
PROC PLAY_NEXT_LEAD_IN(LEADIN_HANDLER &lead, PED_INDEX ped)
|
|
|
|
// currently only handles sequential lead ins at the moment
|
|
lead.iCurrentLeadIn ++
|
|
IF (lead.iCurrentLeadIn >= lead.iMaxLeadIn)
|
|
lead.ICurrentLeadIn = 0
|
|
ENDIF
|
|
|
|
SET_BIT(lead.iLeadsInPlayedFlag, lead.iCurrentLeadIn)
|
|
lead.iAnimsPlayed ++
|
|
|
|
IF NOT IS_STRING_NULL_OR_EMPTY(lead.sLeadInAnims[lead.iCurrentLeadIn])
|
|
IF (lead.iSyncSceneID <> -1)
|
|
IF NOT IS_SYNCHRONIZED_SCENE_RUNNING(lead.iSyncSceneID)
|
|
lead.iSyncSceneID = CREATE_SYNCHRONIZED_SCENE(lead.vSyncScenePos, lead.vSyncSceneRot)
|
|
ENDIF
|
|
|
|
TASK_SYNCHRONIZED_SCENE(ped, lead.iSyncSceneID, lead.sLeadInDictionary, lead.sLeadInAnims[lead.iCurrentLeadIn], NORMAL_BLEND_IN, NORMAL_BLEND_OUT)
|
|
SET_SYNCHRONIZED_SCENE_LOOPED(lead.iSyncSceneID, FALSE)
|
|
SET_SYNCHRONIZED_SCENE_HOLD_LAST_FRAME(lead.iSyncSceneID, TRUE)
|
|
CPRINTLN(DEBUG_MISSION, "PLAYING SYNCHED LEADIN:", lead.sLeadInAnims[lead.iCurrentLeadIn], " GAME TIME:", GET_GAME_TIMER())
|
|
EXIT
|
|
ELSE
|
|
TASK_PLAY_ANIM(ped, lead.sLeadInDictionary, lead.sLeadInAnims[lead.iCurrentLeadIn], NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_HOLD_LAST_FRAME)
|
|
CPRINTLN(DEBUG_MISSION, "PLAYING LEADIN:", lead.sLeadInAnims[lead.iCurrentLeadIn], " GAME TIME:", GET_GAME_TIMER())
|
|
EXIT
|
|
ENDIF
|
|
ENDIF
|
|
|
|
CPRINTLN(DEBUG_MISSION, "LEADIN PLAYING:", lead.sLeadInAnims[lead.iCurrentLeadIn], " GAME TIME:", GET_GAME_TIMER())
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Checks if the current anim is finished
|
|
/// PARAMS:
|
|
/// lead - lead in handler
|
|
/// ped - ped playing the leading
|
|
/// RETURNS:
|
|
/// Returns true if so
|
|
FUNC BOOL IS_CURRENT_LEADIN_ANIM_FINISHED(LEADIN_HANDLER &lead, PED_INDEX ped)
|
|
IF IS_STRING_NULL_OR_EMPTY(lead.sLeadInAnims[lead.ICurrentLeadIn])
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF NOT IS_ENTITY_PLAYING_ANIM(ped, lead.sLeadInDictionary, lead.sLeadInAnims[lead.ICurrentLeadIn])
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF HAS_ENTITY_ANIM_FINISHED(ped, lead.sLeadInDictionary, lead.sLeadInAnims[lead.ICurrentLeadIn])
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF (lead.iSyncSceneID = -1)
|
|
IF (GET_ENTITY_ANIM_CURRENT_TIME(ped, lead.sLeadInDictionary, lead.sLeadInAnims[lead.ICurrentLeadIn]) >= 1.0)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ELSE
|
|
IF (GET_SYNCHRONIZED_SCENE_PHASE(lead.iSyncSceneID) >= 0.999)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Updates the Lead In
|
|
/// PARAMS:
|
|
/// lead - lead in handler
|
|
/// ped - ped playing the leading
|
|
/// dist - distance before leadin kicks in
|
|
/// angle - angle that player has to be to ped before leadin kicks in
|
|
/// bLockPlayer - if this is set use trigger lock in
|
|
/// RETURNS:
|
|
/// Returns true if the lead in is finished or it has been aborted
|
|
FUNC BOOL UPDATE_LEAD_IN(LEADIN_HANDLER &lead, PED_INDEX ped, FLOAT dist = 0.0, FLOAT angle = 0.0, BOOL bLockPlayer = TRUE)
|
|
IF (bLockPlayer = TRUE)
|
|
RC_PLAYER_TRIGGER_SCENE_LOCK_IN()
|
|
ENDIF
|
|
|
|
IF NOT IS_ENTITY_OK(ped)
|
|
CPRINTLN(DEBUG_MISSION, "ABORT - PED IS DEAD!!")
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF (GET_DISTANCE_BETWEEN_ENTITIES(ped, PLAYER_PED_ID()) < lead.fCloseBreakOutDist) AND (lead.fCloseBreakOutDist > 0.0)
|
|
CPRINTLN(DEBUG_MISSION, "ABORT - EMERGENCY BREAK OUT - WE'RE TOO CLOSE")
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
//CPRINTLN(DEBUG_MISSION, " PHASE:", GET_SYNCHRONIZED_SCENE_PHASE(lead.iSyncSceneID))
|
|
|
|
SWITCH (lead.iState)
|
|
CASE 0
|
|
PLAY_LEAD_IN_IDLE(lead, ped)
|
|
lead.iState ++
|
|
BREAK
|
|
CASE 1
|
|
IF CAN_PED_PLAY_LEADIN(ped, lead, dist, angle)
|
|
CPRINTLN(DEBUG_MISSION, "WE CAN START THE LEAD IN")
|
|
lead.iState ++
|
|
ENDIF
|
|
BREAK
|
|
CASE 2 // selecting a line
|
|
PLAY_NEXT_LEAD_IN(lead, ped)
|
|
lead.iState ++
|
|
BREAK
|
|
CASE 3 // wait till line has finished
|
|
IF NOT IS_CURRENT_LEADIN_ANIM_FINISHED(lead, ped)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
CPRINTLN(DEBUG_MISSION, "LEADIN FINISHED:", lead.sLeadInAnims[lead.ICurrentLeadIn])
|
|
IF (lead.iCurrentLeadIn = (lead.iMaxLeadIn - 1))
|
|
CPRINTLN(DEBUG_MISSION, "ALL LEADINS FINISHED")
|
|
lead.iState = 5
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF (lead.iMinWaitTime > 0) AND (lead.iMaxWaitTime > 0)
|
|
PLAY_LEAD_IN_IDLE(lead, ped)
|
|
lead.iWaitTimer = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(lead.iMinWaitTime, lead.iMaxWaitTime)
|
|
lead.iState ++
|
|
ELSE
|
|
lead.iState = 1
|
|
ENDIF
|
|
BREAK
|
|
CASE 4 // wait delay before playing the next line
|
|
IF (GET_GAME_TIMER() > lead.iWaitTimer)
|
|
lead.iState = 1
|
|
ENDIF
|
|
BREAK
|
|
CASE 5 // null state
|
|
RETURN TRUE
|
|
ENDSWITCH
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|