// ***************************************************************************************** // ***************************************************************************************** // // 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