USING "rage_builtins.sch" USING "globals.sch" USING "commands_streaming.sch" USING "commands_pad.sch" USING "commands_script.sch" USING "drunkNoticeboard_private.sch" USING "drunk_public.sch" //KGMTAXI USING "taxi_functions.sch" USING "respawnCutscene_private.sch" USING "player_scene_schedule.sch" #IF IS_DEBUG_BUILD USING "drunk_debug.sch" #ENDIF // ***************************************************************************************** // ***************************************************************************************** // ***************************************************************************************** // // MISSION NAME : drunk.sc // AUTHOR : Keith / Alwyn // DESCRIPTION : Controls one drunken ped or player. // // NOTES : Peds need to return to SWITCH_ON_RAGDOLL state rather than IDLE. // // ***************************************************************************************** // ***************************************************************************************** // ***************************************************************************************** CONST_FLOAT WALKING_LEAN_VALUE 0.49 CONST_FLOAT MAX_DISTANCE_FROM_VEHICLE_m 7.0 CONST_FLOAT SPEED_CLASSED_AS_STOPPED 0.04 CONST_INT FAILSAFE_SHUFFLE_TIMEOUT_msec 1000 CONST_INT FAILSAFE_WARP_TIMEOUT_msec 500 CONST_INT STEERING_BIAS_PED_TIMEOUT_msec 2000 CONST_INT STEERING_BIAS_TIMEOUT_msec 1000 CONST_INT NO_AVAILABLE_SEAT -1 STRUCT m_sTimers INT ragdolling // Length of time (in msec) that the ped should ragdoll INT overall // Overall length of time (in msec) that any drunk effects should last INT activity // Temporary timer for any short-term activities INT failsafe // Temporary timer for any activity that needs a failsafe timer INT steeringTime // Time until Steering Bias needs to change again ENDSTRUCT // Used to control the drunk ped. The Overall status could be 'walk to car' but this could be interrupted // by an Immediate status like 'get up off the floor'. STRUCT m_sStatus g_eDrunkStatus shortTerm // The immediate (short-term) objective status g_eDrunkStatus longTerm // The overall (long-term) objective status STRING moveClip // ENDSTRUCT g_sDrunkRequests m_rawDetails INT m_myUniqueID = NO_UNIQUE_DRUNK_PED_ID INT m_leaderUniqueID = NO_UNIQUE_DRUNK_PED_ID BOOL m_thisIsPlayer = FALSE BOOL m_ragdollOn = FALSE FLOAT m_lastKnownHeadHeight = 1.7 // Set Get_Head_Coordinates() for explanation FLOAT m_steeringBias = 0.0 STRING m_transitionClip = "" m_sTimers m_timing m_sStatus m_status INT m_wantedLevel = -1 INT m_myPedsArrayIndex = 0 BOOL m_bPlayerDrinkingInMP = FALSE #IF IS_DEBUG_BUILD // ----------------------------------------------------------------------------------------- // Debug // ----------------------------------------------------------------------------------------- // PURPOSE: Convert an MSEC value to seconds // // INPUT PARAMS: paramMsec Number of milliseconds // RETURN VALUE: INT Number of seconds, with a floor of 0 FUNC INT MSEC_TO_SEC(INT paramMsec) IF (paramMsec <= 0) RETURN 0 ENDIF RETURN ((paramMsec / 1000) + 1) ENDFUNC // PURPOSE: Ensure that the value has a floor of 0 // // INPUT PARAMS: paramValue Value to have negative values returned as 0 // RETURN VALUE: INT The value returned as-is except negative values are returned as 0 FUNC INT FLOOR_0(INT paramValue) IF (paramValue <= 0) RETURN 0 ENDIF RETURN paramValue ENDFUNC // PURPOSE: Update 'drunk' debug widgets PROC Update_Drunk_Debug_Variables() IF (m_myPedsArrayIndex = UNKNOWN_DRUNK_ARRAY_INDEX) EXIT ENDIF g_widgetLongTermStatusAsInt[m_myPedsArrayIndex] = ENUM_TO_INT(m_status.longTerm) g_widgetShortTermStatusAsInt[m_myPedsArrayIndex] = ENUM_TO_INT(m_status.shortTerm) g_widgetDrunkLevelAsInt[m_myPedsArrayIndex] = ENUM_TO_INT(g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel) g_widgetTimerA[m_myPedsArrayIndex] = MSEC_TO_SEC(TIMERA()) g_widgetRagdolling[m_myPedsArrayIndex] = MSEC_TO_SEC(m_timing.ragdolling - TIMERA()) g_widgetOverall[m_myPedsArrayIndex] = MSEC_TO_SEC(m_timing.overall - TIMERA()) g_widgetActivity[m_myPedsArrayIndex] = FLOOR_0(m_timing.activity - TIMERA()) g_widgetFailsafe[m_myPedsArrayIndex] = FLOOR_0(m_timing.failsafe - TIMERA()) g_widgetSteering[m_myPedsArrayIndex] = FLOOR_0(m_timing.steeringTime - TIMERA()) g_widgetAlcoholHitCount[m_myPedsArrayIndex] = g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit g_widgetWeedHitCount[m_myPedsArrayIndex] = g_drunkPeds[m_myPedsArrayIndex].iWeedHit ENDPROC PROC Draw_Debug_Drink_Info() TEXT_LABEL_63 str VECTOR xyzDraw = GET_ENTITY_COORDS(m_rawDetails.ped) IF IS_PED_IN_ANY_VEHICLE(m_rawDetails.ped) VEHICLE_INDEX vehIndex = GET_VEHICLE_PED_IS_IN(m_rawDetails.ped) IF GET_PED_IN_VEHICLE_SEAT(vehIndex, VS_DRIVER) = m_rawDetails.ped xyzDraw = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(vehIndex, <<-0.5, 0.5, 0.0>>) ELIF GET_PED_IN_VEHICLE_SEAT(vehIndex, VS_FRONT_RIGHT) = m_rawDetails.ped xyzDraw = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(vehIndex, << 0.5, 0.5, 0.0>>) ELIF GET_PED_IN_VEHICLE_SEAT(vehIndex, VS_BACK_LEFT) = m_rawDetails.ped xyzDraw = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(vehIndex, <<-0.5,-0.5, 0.0>>) ELIF GET_PED_IN_VEHICLE_SEAT(vehIndex, VS_BACK_RIGHT) = m_rawDetails.ped xyzDraw = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(vehIndex, << 0.5,-0.5, 0.0>>) ENDIF ENDIF CONST_INT iTestXY 10 CONST_INT iTestOff -1 str = "longTerm: " str += Get_String_From_DrunkStatus(m_status.longTerm) DrawDebugDrunkTextWithOffset(str, xyzDraw, 0, iTestXY*(iTestOff+1+-1), 0, 0, 0, 255) str = "shortTerm: " str += Get_String_From_DrunkStatus(m_status.shortTerm) DrawDebugDrunkTextWithOffset(str, xyzDraw, 0, iTestXY*(iTestOff+1+0), 0, 0, 255, 255) str = "level: " str += Get_String_From_DrunkLevel(g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel) DrawDebugDrunkTextWithOffset(str, xyzDraw, 0, iTestXY*(iTestOff+1+1), 0, 0, 255, 255) str = "TimerA: " str += g_widgetTimerA[m_myPedsArrayIndex] DrawDebugDrunkTextWithOffset(str, xyzDraw, 0, iTestXY*(iTestOff+1+2), 0, 255, 0, 255) str = "Ragdolling: " str += g_widgetRagdolling[m_myPedsArrayIndex] DrawDebugDrunkTextWithOffset(str, xyzDraw, 0, iTestXY*(iTestOff+1+3), 0, 255, 255, 255) str = "Overall: " str += g_widgetOverall[m_myPedsArrayIndex] DrawDebugDrunkTextWithOffset(str, xyzDraw, 0, iTestXY*(iTestOff+1+4), 255, 0, 0, 255) str = "Activity: " str += g_widgetActivity[m_myPedsArrayIndex] DrawDebugDrunkTextWithOffset(str, xyzDraw, 0, iTestXY*(iTestOff+1+5), 255, 0, 255, 255) str = "Failsafe: " str += g_widgetFailsafe[m_myPedsArrayIndex] DrawDebugDrunkTextWithOffset(str, xyzDraw, 0, iTestXY*(iTestOff+1+6), 255, 255, 0, 255) str = "Steering: " str += g_widgetSteering[m_myPedsArrayIndex] DrawDebugDrunkTextWithOffset(str, xyzDraw, 0, iTestXY*(iTestOff+1+7), 255, 255, 255, 255) str = "moveClip: \"" str += m_status.moveClip str += "\"" IF NOT IS_STRING_NULL_OR_EMPTY(m_status.moveClip) IF NOT HAS_CLIP_SET_LOADED(m_status.moveClip) str += " - NOT LOADED" ENDIF ENDIF DrawDebugDrunkTextWithOffset(str, xyzDraw, 0, iTestXY*(iTestOff+1+8), 0, 0, 0, 255) str = "HitCount: " str += g_widgetAlcoholHitCount[m_myPedsArrayIndex] str += ", " str += g_widgetWeedHitCount[m_myPedsArrayIndex] DrawDebugDrunkTextWithOffset(str, xyzDraw, 0, iTestXY*(iTestOff+1+9), 0, 0, 255, 255) ENDPROC #ENDIF // ----------------------------------------------------------------------------------------- // Status Changes // ----------------------------------------------------------------------------------------- // PURPOSE: Update the short-term status to be 'In Vehicle' and inform all followers PROC Change_ShortTerm_Status_To_In_Vehicle() IF (m_status.shortTerm = DSST_IN_VEHICLE) EXIT ENDIF m_status.shortTerm = DSST_IN_VEHICLE IF (m_myUniqueID = NO_UNIQUE_DRUNK_PED_ID) EXIT ENDIF // Send a message to all followers Post_Drunk_Notice(m_myUniqueID, UNIQUE_ID_ALL_FOLLOWERS, DNID_IN_VEHICLE) // Set up the initial Steering Bias timeout m_timing.steeringTime = TIMERA() m_steeringBias = 0.0 ENDPROC // ----------------------------------------------------------------------------------------- // Clipset "drunk" // ----------------------------------------------------------------------------------------- FUNC BOOL Is_Ped_At_This_Drunk_Level(PED_INDEX PedIndex) //, g_eDrunkLevel thisDrunkLevel) g_eDrunkLevel eDrunkLevel = Get_Peds_Drunk_Level(PedIndex) STRING sDrunkLevelMoveClip = Get_Drunk_Level_Moveclip(eDrunkLevel) IF IS_STRING_NULL_OR_EMPTY(m_status.moveClip) IF IS_STRING_NULL_OR_EMPTY(sDrunkLevelMoveClip) RETURN TRUE ELSE RETURN FALSE ENDIF ENDIF RETURN ARE_STRINGS_EQUAL(m_status.moveClip, sDrunkLevelMoveClip) ENDFUNC // ----------------------------------------------------------------------------------------- // Ragdolling // ----------------------------------------------------------------------------------------- // PURPOSE: Work out how long the ped should ragdoll for. // NM can only handle ragdolling in 65535 msec chunks. // // RETURN VALUE: INT Number of msec to setup the ragdoll to activate for FUNC INT Generate_Number_Of_MSec_Of_Active_Ragdolling() IF (m_timing.ragdolling = INACTIVE_DRUNK_TIMER) RETURN INACTIVE_DRUNK_TIMER ENDIF IF (m_timing.ragdolling = DRUNK_LEVEL_CONSTANT) RETURN DRUNK_LEVEL_CONSTANT ENDIF INT remainingMsec = m_timing.ragdolling - TIMERA() IF (remainingMsec < 0) RETURN INACTIVE_DRUNK_TIMER ENDIF // Ensure it returns a maximum number of msec less than the maximum accepted by NM CONST_INT MAX_RAGDOLLING_ACTIVATION_msec 65534 IF (remainingMsec > MAX_RAGDOLLING_ACTIVATION_msec) remainingMsec = MAX_RAGDOLLING_ACTIVATION_msec ENDIF RETURN remainingMsec ENDFUNC // PURPOSE: Stop the ped ragdolling. // This does not affect any timers, etc. It can be used to pause the ragdolling and restart again later. PROC Stop_Ragdolling() IF NOT (DOES_ENTITY_EXIST(m_rawDetails.ped)) //#381369 EXIT ENDIF // //#652851 & #733764 // IF (IS_PED_INJURED(m_rawDetails.ped)) //#515995 // EXIT // ENDIF // IF NOT (IS_PED_INJURED(m_rawDetails.ped)) //#515995 // IF NOT (Is_Ped_At_This_Drunk_Level(m_rawDetails.ped, g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel)) // // // // #IF IS_DEBUG_BUILD // CPRINTLN(DEBUG_DRUNK, " This Unique Drunk Ped ID failed the Is_Ped_At_This_Drunk_Level check: ", m_myUniqueID) // PRINTNL() // #ENDIF // // // EXIT // ENDIF // ENDIF #IF IS_DEBUG_BUILD CPRINTLN(DEBUG_DRUNK, " This Unique Drunk Ped ID has been told to stop ragdolling: ", m_myUniqueID) #ENDIF IF NOT (IS_PED_INJURED(m_rawDetails.ped)) RESET_PED_MOVEMENT_CLIPSET(m_rawDetails.ped) RESET_PED_STRAFE_CLIPSET(m_rawDetails.ped) CLEAR_PED_ALTERNATE_MOVEMENT_ANIM(m_rawDetails.ped, AAT_IDLE) m_status.moveClip = "" CLEAR_FACIAL_IDLE_ANIM_OVERRIDE(m_rawDetails.ped) SET_PED_RESET_FLAG(m_rawDetails.ped, PRF_DisableActionMode, FALSE) SET_PED_RESET_FLAG(m_rawDetails.ped, PRF_DisablePlayerJumping, FALSE) SET_PED_CAN_PLAY_AMBIENT_ANIMS(m_rawDetails.ped, TRUE) SET_PED_FLEE_ATTRIBUTES(m_rawDetails.ped, FA_DISABLE_AMBIENT_CLIPS, FALSE) SET_PED_IS_DRUNK(m_rawDetails.ped, FALSE) ENDIF IF NOT (m_ragdollOn) EXIT ENDIF m_ragdollOn = FALSE ENDPROC // FUNC BOOL Safe_To_Play_Transition_Animation(PED_INDEX thePed) IF IS_PED_IN_ANY_VEHICLE(thePed, TRUE) OR IS_PED_GETTING_INTO_A_VEHICLE(thePed) CPRINTLN(DEBUG_DRUNK, " don't play transition: in a vehicle") RETURN FALSE ENDIF IF (GET_SCRIPT_TASK_STATUS(thePed, SCRIPT_TASK_PLAY_ANIM) <> FINISHED_TASK) CPRINTLN(DEBUG_DRUNK, " don't play transition: playing an animation") RETURN FALSE ENDIF IF (GET_SCRIPT_TASK_STATUS(thePed, SCRIPT_TASK_SYNCHRONIZED_SCENE) <> FINISHED_TASK) CPRINTLN(DEBUG_DRUNK, " don't play transition: playing a synch scene") RETURN FALSE ENDIF IF IS_PED_SHOOTING(thePed) CPRINTLN(DEBUG_DRUNK, " don't play transition: ped is shooting") RETURN FALSE ENDIF IF IS_ENTITY_IN_AIR(thePed) CPRINTLN(DEBUG_DRUNK, " don't play transition: ped is in air") RETURN FALSE ENDIF IF IS_PED_RAGDOLL(thePed) CPRINTLN(DEBUG_DRUNK, " don't play transition: ped is ragdoll") RETURN FALSE ENDIF IF IS_PED_CLIMBING(thePed) CPRINTLN(DEBUG_DRUNK, " don't play transition: ped is climbing") RETURN FALSE ENDIF IF g_bBrowserVisible CPRINTLN(DEBUG_DRUNK, " don't play transition: browser visible") RETURN FALSE ENDIF IF IS_CUSTOM_MENU_ON_SCREEN() CPRINTLN(DEBUG_DRUNK, " don't play transition: menu on screen") RETURN FALSE ENDIF IF (thePed = PLAYER_PED_ID()) IF NOT IS_PLAYER_FREE_FOR_AMBIENT_TASK(PLAYER_ID()) CPRINTLN(DEBUG_DRUNK, " don't play transition: not free of ambient tasks") RETURN FALSE ENDIF IF NOT IS_PLAYER_CONTROL_ON(PLAYER_ID()) CPRINTLN(DEBUG_DRUNK, " don't play transition: controll off") RETURN FALSE ENDIF IF IS_PLAYER_FREE_AIMING(PLAYER_ID()) OR IS_PLAYER_TARGETTING_ANYTHING(PLAYER_ID()) CPRINTLN(DEBUG_DRUNK, " don't play transition: player is aiming") RETURN FALSE ENDIF IF IS_PLAYER_BROWSING_ITEMS_IN_ANY_SHOP() CPRINTLN(DEBUG_DRUNK, " don't play transition: player is browsing") RETURN FALSE ENDIF ENDIF VECTOR vClosestPedVelocity vClosestPedVelocity = GET_ENTITY_VELOCITY(thePed) IF (VMAG2(vClosestPedVelocity) >= (1.0*1.0)) CPRINTLN(DEBUG_DRUNK, " don't play transition: velocity too high") RETURN FALSE ENDIF CPRINTLN(DEBUG_DRUNK, " play transition animation!!!") RETURN TRUE ENDFUNC // PURPOSE: Start the ped ragdolling. // // RETURN VALUE: BOOL TRUE if the ped successfully started ragdolling, otherwise FALSE FUNC BOOL Start_Ragdolling(g_eDrunkLevel thisDrunkLevel) INT ragdollingActivationTime = Generate_Number_Of_MSec_Of_Active_Ragdolling() IF (ragdollingActivationTime = INACTIVE_DRUNK_TIMER) RETURN FALSE ENDIF IF (IS_PED_INJURED(m_rawDetails.ped)) //#652851 & #733764 IF (IS_PED_IN_ANY_VEHICLE(m_rawDetails.ped)) OR (IS_PED_GETTING_INTO_A_VEHICLE(m_rawDetails.ped)) RETURN FALSE ENDIF IF (IS_ENTITY_WAITING_FOR_WORLD_COLLISION(m_rawDetails.ped)) RETURN FALSE ENDIF // Extra test, just in case - this can happen on odd occasions IF (Is_Ped_At_This_Drunk_Level(m_rawDetails.ped)) //, thisDrunkLevel)) RETURN FALSE ENDIF ENDIF IF (g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit < 3) AND (g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit <> 0) AND (g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit > g_drunkPeds[m_myPedsArrayIndex].iWeedHit) // ...failed to activate walking - not drunk enough #IF IS_DEBUG_BUILD CDEBUG3LN(DEBUG_DRUNK, " failed to activate walking - not drunk enough! iAlcoholHit: ", g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit, ", iWeedHit: ", g_drunkPeds[m_myPedsArrayIndex].iWeedHit, ", thisDrunkLevel: ", Get_String_From_DrunkLevel(thisDrunkLevel)) #ENDIF RETURN FALSE ENDIF IF (g_drunkPeds[m_myPedsArrayIndex].iWeedHit < 9) AND (g_drunkPeds[m_myPedsArrayIndex].iWeedHit <> 0) AND (g_drunkPeds[m_myPedsArrayIndex].iWeedHit > g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit) // ...failed to activate walking #IF IS_DEBUG_BUILD CDEBUG3LN(DEBUG_DRUNK, " failed to activate walking - not stoned enough! iWeedHit: ", g_drunkPeds[m_myPedsArrayIndex].iWeedHit, ", iAlcoholHit: ", g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit, ", thisDrunkLevel: ", Get_String_From_DrunkLevel(thisDrunkLevel)) #ENDIF RETURN FALSE ENDIF #IF IS_DEBUG_BUILD CDEBUG1LN(DEBUG_DRUNK, " iAlcoholHit: ", g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit, ", iWeedHit: ", g_drunkPeds[m_myPedsArrayIndex].iWeedHit, ", thisDrunkLevel: ", Get_String_From_DrunkLevel(thisDrunkLevel)) #ENDIF STRING m_movementClip = Get_Drunk_Level_Moveclip(thisDrunkLevel) IF IS_STRING_NULL_OR_EMPTY(m_movementClip) #IF IS_DEBUG_BUILD // // // // // // // // // // // // // // // // Ignore duplicate requests INT drunkPedUniqueID = Get_Peds_Unique_Drunk_Ped_ID(m_rawDetails.ped) INT arrayIndex = Get_Peds_Drunk_Ped_Array_Index(drunkPedUniqueID) IF (arrayIndex = UNKNOWN_DRUNK_ARRAY_INDEX) CPRINTLN(DEBUG_DRUNK, "IS_STRING_NULL_OR_EMPTY \"", m_movementClip, "\" // ", Get_String_From_DrunkLevel(thisDrunkLevel), " DL_NO_LEVEL") ELSE CPRINTLN(DEBUG_DRUNK, "IS_STRING_NULL_OR_EMPTY \"", m_movementClip, "\" // ", Get_String_From_DrunkLevel(thisDrunkLevel), " g_drunkPeds[", arrayIndex, "].eDrunkLevel: ", Get_String_From_DrunkLevel(g_drunkPeds[arrayIndex].eDrunkLevel)) ENDIF // // // // // // // // // // // // // // // PRINTNL() #ENDIF RETURN FALSE ENDIF IF Is_Ped_At_This_Drunk_Level(m_rawDetails.ped) #IF IS_DEBUG_BUILD CPRINTLN(DEBUG_DRUNK, "Is_Ped_At_This_Drunk_Level \"", m_movementClip, "\" // ", Get_String_From_DrunkLevel(thisDrunkLevel)) #ENDIF RETURN FALSE ENDIF REQUEST_CLIP_SET(m_movementClip) // // // // // // // // // // // // // // // // // IF Safe_To_Play_Transition_Animation(m_rawDetails.ped) STRING sTransitionDict = "MOVE_M@DRUNK@TRANSITIONS" STRING sTransitionClip = "" SWITCH thisDrunkLevel CASE DL_verydrunk sTransitionClip = "" BREAK CASE DL_moderatedrunk sTransitionClip = "VERY_TO_MODERATE" BREAK CASE DL_slightlydrunk sTransitionClip = "MODERATE_TO_SLIGHTLY" // "SLIGHTLY_TO_IDLE" BREAK DEFAULT SCRIPT_ASSERT(Get_String_From_DrunkLevel(thisDrunkLevel)) BREAK ENDSWITCH IF NOT IS_STRING_NULL_OR_EMPTY(sTransitionDict) AND NOT IS_STRING_NULL_OR_EMPTY(sTransitionClip) REQUEST_ANIM_DICT(sTransitionDict) WHILE NOT HAS_ANIM_DICT_LOADED(sTransitionDict) // WAIT(0) ENDWHILE // IF NOT (IS_PED_INJURED(m_rawDetails.ped)) TASK_PLAY_ANIM(m_rawDetails.ped, sTransitionDict, sTransitionClip, WALK_BLEND_IN, WALK_BLEND_OUT, -1, AF_SECONDARY|AF_UPPERBODY) m_transitionClip = sTransitionClip ENDIF ENDIF ENDIF // // // // // // // // // // // // // // // // // IF NOT HAS_CLIP_SET_LOADED(m_movementClip) #IF IS_DEBUG_BUILD CPRINTLN(DEBUG_DRUNK, "NOT HAS_CLIP_SET_LOADED \"", m_movementClip, "\" // ", Get_String_From_DrunkLevel(thisDrunkLevel)) #ENDIF RETURN FALSE ENDIF #IF IS_DEBUG_BUILD CPRINTLN(DEBUG_DRUNK, " This Unique Drunk Ped ID has been told to start ragdolling: ", m_myUniqueID, " \"", m_movementClip, "\"") DEBUG_PRINTCALLSTACK() #ENDIF CONST_FLOAT blendDelta 2.0 //8.0 //#1351462 IF (IS_PED_INJURED(m_rawDetails.ped)) RETURN FALSE ENDIF SET_PED_MOVEMENT_CLIPSET(m_rawDetails.ped, m_movementClip, 0.75) IF (GET_FOLLOW_PED_CAM_VIEW_MODE() = CAM_VIEW_MODE_FIRST_PERSON) SET_PED_STRAFE_CLIPSET(m_rawDetails.ped, "move_ped_strafing_firstperson@drunk") ENDIF SET_PED_ALTERNATE_MOVEMENT_ANIM(m_rawDetails.ped, AAT_IDLE, m_movementClip, "idle", blendDelta) m_status.moveClip = m_movementClip m_ragdollOn = TRUE STRING pOverrideIdleClipName = NULL SWITCH GET_PLAYER_PED_ENUM(m_rawDetails.ped) CASE CHAR_MICHAEL pOverrideIdleClipName = "FACIALS@P_M_ZERO@BASE" BREAK CASE CHAR_FRANKLIN pOverrideIdleClipName = "FACIALS@P_M_ONE@BASE" BREAK CASE CHAR_TREVOR pOverrideIdleClipName = "FACIALS@P_M_TWO@BASE" BREAK DEFAULT IF IS_PED_A_PLAYER(m_rawDetails.ped) IF !IS_PLAYER_FEMALE() pOverrideIdleClipName = "FACIALS@GEN_MALE@BASE" ELSE pOverrideIdleClipName = "FACIALS@GEN_FEMALE@BASE" ENDIF ELSE IF IS_PED_MALE(m_rawDetails.ped) pOverrideIdleClipName = "FACIALS@GEN_MALE@BASE" ELSE pOverrideIdleClipName = "FACIALS@GEN_FEMALE@BASE" ENDIF ENDIF BREAK ENDSWITCH SET_FACIAL_IDLE_ANIM_OVERRIDE(m_rawDetails.ped, "mood_drunk_1", pOverrideIdleClipName) SET_PED_RESET_FLAG(m_rawDetails.ped, PRF_DisableActionMode, TRUE) SET_PED_RESET_FLAG(m_rawDetails.ped, PRF_DisablePlayerJumping, TRUE) SET_PED_CAN_PLAY_AMBIENT_ANIMS(m_rawDetails.ped, FALSE) SET_PED_FLEE_ATTRIBUTES(m_rawDetails.ped, FA_DISABLE_AMBIENT_CLIPS, TRUE) SET_PED_IS_DRUNK(m_rawDetails.ped, TRUE) RETURN TRUE ENDFUNC // ----------------------------------------------------------------------------------------- // Walking // ----------------------------------------------------------------------------------------- FUNC BOOL Stop_Walking() IF NOT (Is_Ped_At_This_Drunk_Level(m_rawDetails.ped)) //, g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel)) RETURN FALSE ENDIF IF NOT (m_ragdollOn) RETURN FALSE ENDIF Force_Cleanup_Drunk_Ped(m_rawDetails.ped) m_status.moveClip = "" MPGlobalsAmbience.bUpdatePlayerWalk = TRUE RETURN TRUE ENDFUNC PROC Set_Entity_Steer_Bias(ENTITY_INDEX EntityIndex, FLOAT steerBias) IF NETWORK_IS_GAME_IN_PROGRESS() AND NOT NETWORK_HAS_CONTROL_OF_ENTITY(EntityIndex) CASSERTLN(DEBUG_DRUNK, "Set_Entity_Steer_Bias called when network doesn't have control of entity") EXIT ENDIF IF (IS_ENTITY_A_PED(EntityIndex)) SET_PED_STEER_BIAS(GET_PED_INDEX_FROM_ENTITY_INDEX(EntityIndex), steerBias) ELIF (IS_ENTITY_A_VEHICLE(EntityIndex)) SET_VEHICLE_STEER_BIAS(GET_VEHICLE_INDEX_FROM_ENTITY_INDEX(EntityIndex), steerBias) ENDIF ENDPROC // ----------------------------------------------------------------------------------------- // Cleanup // ----------------------------------------------------------------------------------------- // PURPOSE: Cancel a steering bias PROC Cancel_Steering_Bias() IF (IS_ENTITY_DEAD(m_rawDetails.ped)) EXIT ENDIF ENTITY_INDEX theEntity = m_rawDetails.ped IF (IS_PED_IN_ANY_VEHICLE(m_rawDetails.ped)) VEHICLE_INDEX theCar = GET_VEHICLE_PED_IS_IN(m_rawDetails.ped) PED_INDEX theDriver = GET_PED_IN_VEHICLE_SEAT(theCar, VS_DRIVER) IF NOT (m_rawDetails.ped = theDriver) EXIT ENDIF theEntity = theCar ELIF NOT (GET_FOLLOW_PED_CAM_VIEW_MODE() = CAM_VIEW_MODE_FIRST_PERSON) OR NOT (PLAYER_PED_ID() = m_rawDetails.ped) EXIT ENDIF m_steeringBias = 0.0 Set_Entity_Steer_Bias(theEntity, 0.0) ENDPROC // PURPOSE: Cleanup any parts of the script that need it and terminate PROC Drunk_Cleanup() #IF IS_DEBUG_BUILD CPRINTLN(DEBUG_DRUNK, " This Unique Drunk Ped ID has been told to stop being drunk: ", m_myUniqueID) #ENDIF IF NOT IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_STORY) AND NOT IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_STORY_FRIENDS) IF NOT (IS_ENTITY_DEAD(m_rawDetails.ped)) enumCharacterList ePed = GET_PLAYER_PED_ENUM(m_rawDetails.ped) IF g_drunkPeds[m_myPedsArrayIndex].iWeedHit > 0 SWITCH ePed //#1532953 CASE CHAR_MICHAEL PLAY_PED_AMBIENT_SPEECH(m_rawDetails.ped, "POST_STONED") BREAK CASE CHAR_FRANKLIN PLAY_PED_AMBIENT_SPEECH(m_rawDetails.ped, "POST_STONED") BREAK CASE CHAR_TREVOR PLAY_PED_AMBIENT_SPEECH(m_rawDetails.ped, "POST_STONED") BREAK ENDSWITCH ENDIF SWITCH ePed CASE CHAR_AMANDA SET_AMBIENT_VOICE_NAME(m_rawDetails.ped, "AMANDA_NORMAL") BREAK CASE CHAR_LAMAR SET_AMBIENT_VOICE_NAME(m_rawDetails.ped, "LAMAR_NORMAL") BREAK ENDSWITCH ENDIF ENDIF Stop_Ragdolling() IF (m_thisIsPlayer) g_playerIsDrunk = FALSE ENDIF Cancel_Steering_Bias() #IF IS_DEBUG_BUILD m_status.longTerm = DS_NO_STATUS m_status.shortTerm = DS_NO_STATUS Update_Drunk_Debug_Variables() #ENDIF REMOVE_ANIM_DICT(Get_Drunk_Level_Moveclip(DL_verydrunk)) REMOVE_ANIM_DICT(Get_Drunk_Level_Moveclip(DL_moderatedrunk)) REMOVE_ANIM_DICT(Get_Drunk_Level_Moveclip(DL_slightlydrunk)) g_bMPPlayerPassingOutDrunk = FALSE IF GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("appEmail")) > 0 HANG_UP_AND_PUT_AWAY_PHONE() ENDIF TERMINATE_THIS_THREAD() ENDPROC // ----------------------------------------------------------------------------------------- // General Data // ----------------------------------------------------------------------------------------- // PURPOSE: Checks to see if the Unique Drunk Ped ID for the drunk ped has been generated and stores it locally. PROC Store_My_UniqueID() IF NOT (m_myUniqueID = NO_UNIQUE_DRUNK_PED_ID) EXIT ENDIF m_myUniqueID = Get_Peds_Unique_Drunk_Ped_ID(m_rawDetails.ped) IF (m_myUniqueID = NO_UNIQUE_DRUNK_PED_ID) EXIT ENDIF m_myPedsArrayIndex = Get_Peds_Drunk_Ped_Array_Index(m_myUniqueID) ENDPROC // NOTES: A ped skeleton only updates when on-screen so GET_PED_BONE_POSITION only reports correct values // when on-screen and now asserts if called when off-screen. Before the assert was added the skeleton // didn't move so always reported the last on-screen position of the skeleton. If off-screen I'm now // going to do this by storing the height of the last known head position and all calculations will // be based on the ped coordinates based on this stored height. // // PURPOSE: Return the head coordinates - this will be accurate if the ped is on-screen and // estimated if off-screen [more...] // // RETURN VALUE: VECTOR The head coordinates FUNC VECTOR Get_Head_Coordinates() FLOAT groundZ = 0.0 FLOAT holdZ = 0.0 VECTOR xyzHead IF (WAS_PED_SKELETON_UPDATED(m_rawDetails.ped)) // ...ped skeleton is on-screen so head coordinates are accurate xyzHead = GET_PED_BONE_COORDS(m_rawDetails.ped, BONETAG_HEAD , <<0.0, 0.0, 0.0>>) holdZ = xyzHead.z xyzHead.z += 1.0 GET_GROUND_Z_FOR_3D_COORD(xyzHead, groundZ) xyzHead.z = holdZ // Update the last known head height above ground Z m_lastKnownHeadHeight = xyzHead.z - groundZ ELSE // ...ped skeleton is off-screen so approximate the head position based on last known values xyzHead = GET_ENTITY_COORDS(m_rawDetails.ped) xyzHead.z += 2.0 GET_GROUND_Z_FOR_3D_COORD(xyzHead, groundZ) // Store the z coordinates of the head as the last known head height above the ground Z // NOTE: this is so that if the ped is on a slope the coords remains the same relative height above ground xyzHead.z = groundZ + m_lastKnownHeadHeight ENDIF RETURN xyzHead ENDFUNC // PURPOSE: Checks whether or not this is the player or an AI PROC Store_Player_Or_AI() m_thisIsPlayer = FALSE IF (m_rawDetails.ped = PLAYER_PED_ID()) m_thisIsPlayer = TRUE g_playerIsDrunk = TRUE g_iPlayerDrunkCount++ ENDIF IF NOT (IS_ENTITY_DEAD(m_rawDetails.ped)) enumCharacterList ePed = GET_PLAYER_PED_ENUM(m_rawDetails.ped) SWITCH ePed CASE CHAR_AMANDA SET_AMBIENT_VOICE_NAME(m_rawDetails.ped, "AMANDA_DRUNK") BREAK CASE CHAR_LAMAR SET_AMBIENT_VOICE_NAME(m_rawDetails.ped, "LAMAR_DRUNK") BREAK ENDSWITCH ENDIF ENDPROC // ----------------------------------------------------------------------------------------- // Notices // ----------------------------------------------------------------------------------------- // PURPOSE: Act on a 'Extended Time' drunk notice // // INPUT PARAMS: paramTime_msec INT containint the milliseconds extended time PROC Read_Drunk_Notice_Extended_Time(INT paramTime_msec) m_rawDetails.overall_msec += paramTime_msec m_rawDetails.ragdoll_msec += paramTime_msec m_timing.overall += paramTime_msec m_timing.ragdolling += paramTime_msec #IF IS_DEBUG_BUILD CPRINTLN(DEBUG_DRUNK, " This Unique Drunk Ped ID has been told to extend it's time: ", m_myUniqueID, " by ", paramTime_msec) #ENDIF ENDPROC PROC Read_Drunk_Notice_Hit_Alcohol(INT iHitCount) g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit += iHitCount // SCRIPT_ASSERT("g_drunkPeds[arrayIndex].iAlcoholHit 444") IF (m_timing.ragdolling = DRUNK_LEVEL_CONSTANT) g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel = DL_verydrunk ELSE IF (g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit < 3 AND g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit <> 0) g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel = DL_NO_LEVEL ELSE INT remainingMsec = (m_timing.ragdolling - TIMERA()) IF (remainingMsec <= 0) remainingMsec = 0 ENDIF remainingMsec = ((remainingMsec / 1000) + 1) g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel = DL_verydrunk IF (remainingMsec < 30) g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel = DL_moderatedrunk ENDIF IF (remainingMsec < 10) g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel = DL_slightlydrunk ENDIF IF NOT Is_Ped_At_This_Drunk_Level(m_rawDetails.ped) Start_Ragdolling(g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel) CPRINTLN(DEBUG_DRUNK, " not at level", Get_String_From_DrunkLevel(g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel)) ELSE CPRINTLN(DEBUG_DRUNK, " at level", Get_String_From_DrunkLevel(g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel)) ENDIF ENDIF ENDIF #IF IS_DEBUG_BUILD CPRINTLN(DEBUG_DRUNK, " This Unique Drunk Ped ID taken another Alcohol hit: ", m_myUniqueID, " to ", Get_String_From_DrunkLevel(g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel)) #ENDIF ENDPROC PROC Read_Drunk_Notice_Hit_Weed() g_drunkPeds[m_myPedsArrayIndex].iWeedHit++ // SCRIPT_ASSERT("g_drunkPeds[arrayIndex].iAlcoholHit 444") IF (m_timing.ragdolling = DRUNK_LEVEL_CONSTANT) g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel = DL_verydrunk ELSE IF (g_drunkPeds[m_myPedsArrayIndex].iWeedHit < 9 AND g_drunkPeds[m_myPedsArrayIndex].iWeedHit <> 0) g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel = DL_NO_LEVEL ELSE INT remainingMsec = (m_timing.ragdolling - TIMERA()) IF (remainingMsec <= 0) remainingMsec = 0 ENDIF remainingMsec = ((remainingMsec / 1000) + 1) g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel = DL_verydrunk IF (remainingMsec < 30) g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel = DL_moderatedrunk ENDIF IF (remainingMsec < 10) g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel = DL_slightlydrunk ENDIF IF NOT Is_Ped_At_This_Drunk_Level(m_rawDetails.ped) Start_Ragdolling(g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel) CPRINTLN(DEBUG_DRUNK, " not at level ", Get_String_From_DrunkLevel(g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel)) ELSE CPRINTLN(DEBUG_DRUNK, " at level ", Get_String_From_DrunkLevel(g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel)) ENDIF ENDIF ENDIF #IF IS_DEBUG_BUILD CPRINTLN(DEBUG_DRUNK, " This Unique Drunk Ped ID taken another Weed hit: ", m_myUniqueID, " to ", Get_String_From_DrunkLevel(g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel)) #ENDIF ENDPROC // PURPOSE: Act on a 'In Vehicle' drunk notice PROC Read_Drunk_Notice_In_Vehicle() // Change the long-term status to be 'Get Into Vehicle' m_status.longTerm = DSLT_GET_INTO_VEHICLE #IF IS_DEBUG_BUILD CPRINTLN(DEBUG_DRUNK, " This Unique Drunk Ped ID has been told his leader is in a vehicle: ", m_myUniqueID) #ENDIF ENDPROC // PURPOSE: Act on this Drunk Notice directed at this drunk ped // // INPUT PARAMS: paramArrayIndex Array Index into the Drunk Notices array PROC Read_This_Drunk_Notice(INT paramArrayIndex) g_eDrunkNoticeIDs thisNoticeID = g_drunkNotices[paramArrayIndex].notice SWITCH (thisNoticeID) CASE DNID_BECOME_SOBER Drunk_Cleanup() BREAK CASE DNID_EXTENDED_TIME Read_Drunk_Notice_Extended_Time(g_drunkNotices[paramArrayIndex].intval) BREAK CASE DNID_HIT_ALCOHOL Read_Drunk_Notice_Hit_Alcohol(g_drunkNotices[paramArrayIndex].inthit) BREAK CASE DNID_HIT_WEED Read_Drunk_Notice_Hit_Weed() BREAK CASE DNID_IN_VEHICLE Read_Drunk_Notice_In_Vehicle() BREAK // Ignore notices aimed at the control script only CASE DNID_STILL_DRUNK BREAK // Ignore this CASE DNID_NO_DRUNK_NOTICE BREAK DEFAULT SCRIPT_ASSERT("drunk: Read_This_Drunk_Notice - Unknown Drunk Notice ID. Tell Alwyn.") BREAK ENDSWITCH ENDPROC // PURPOSE: Check to see if any drunk notices are directed at this drunk ped and deal with them. // Delete any that are specifically directed at this ped. PROC Read_All_Drunk_Notices_Directed_At_Me() g_eDrunkNoticeIDs thisNoticeID = DNID_NO_DRUNK_NOTICE INT thisLoop = 0 REPEAT MAX_NUMBER_OF_DRUNK_NOTICES thisLoop thisNoticeID = g_drunkNotices[thisLoop].notice IF NOT (thisNoticeID = DNID_NO_DRUNK_NOTICE) // Is this notice directed specifically at me? IF (g_drunkNotices[thisLoop].reader = m_myUniqueID) Read_This_Drunk_Notice(thisLoop) Clear_One_Drunk_Notice(thisLoop) // Is this notice directed at followers of my leader? ELIF (g_drunkNotices[thisLoop].reader = UNIQUE_ID_ALL_FOLLOWERS) IF NOT (m_leaderUniqueID = NO_UNIQUE_DRUNK_PED_ID) IF (m_leaderUniqueID = g_drunkNotices[thisLoop].poster) Read_This_Drunk_Notice(thisLoop) ENDIF ENDIF ENDIF ENDIF ENDREPEAT ENDPROC // ----------------------------------------------------------------------------------------- // Timings // ----------------------------------------------------------------------------------------- // PURPOSE: Based on the drunkLevel, calculate how long the various components of being drunk should last PROC Store_Drunk_Timings() // Clear out the timings struct m_timing.ragdolling = m_rawDetails.ragdoll_msec m_timing.overall = m_rawDetails.overall_msec m_timing.activity = INACTIVE_DRUNK_TIMER m_timing.failsafe = INACTIVE_DRUNK_TIMER // Ensure the maximum drunk time is greater than the other drunk timings #IF IS_DEBUG_BUILD IF (m_timing.overall < m_timing.ragdolling) SCRIPT_ASSERT("drunk: Store_Drunk_Timings(): maximum drunk time is less than ragdolling time") ENDIF #ENDIF ENDPROC // PURPOSE: Check the various drunk control timers to see if any have timed out PROC Maintain_Drunk_Timers() IF NOT (m_timing.ragdolling = DRUNK_LEVEL_CONSTANT) // Has the ragdolling timer expired? IF NOT (m_timing.ragdolling = INACTIVE_DRUNK_TIMER) IF (TIMERA() >= m_timing.ragdolling) Stop_Ragdolling() m_timing.ragdolling = INACTIVE_DRUNK_TIMER m_status.shortTerm = DS_IDLE ENDIF ENDIF // Has the overall timer expired? IF (TIMERA() > m_timing.overall) Drunk_Cleanup() ENDIF ENDIF ENDPROC // ----------------------------------------------------------------------------------------- // Modifiers // ----------------------------------------------------------------------------------------- // PURPOSE: Check the various drunk crime checks to see if a BAWSAQ modifier needs incimenting PROC Maintain_Drunk_Crime_Modifiers() // Only needed for the player IF NOT (m_thisIsPlayer) m_wantedLevel = -1 EXIT ENDIF // m_wantedLevel is -1, get the players wanted level to initialise IF m_wantedLevel < 0 m_wantedLevel = GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) EXIT ENDIF INT iCurrentWantedLevel = GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) // Wanted level has increased since last incremented DRNKCRIME IF iCurrentWantedLevel <> m_wantedLevel IF iCurrentWantedLevel > m_wantedLevel BawsaqIncrementDrunkModifier_DRNKCRIME() ENDIF m_wantedLevel = iCurrentWantedLevel EXIT ENDIF ENDPROC //// PURPOSE: Check the various drunk hangover checks to see if a BAWSAQ modifier needs incimenting //PROC Maintain_Drunk_Hangover_Modifiers() // // // Maintain the BAWSAQ drunk modifier stat for number of drunk crimes //// BawsaqIncrementDrunkModifier_DRNKCRIME() // //ENDPROC // ----------------------------------------------------------------------------------------- // Status // ----------------------------------------------------------------------------------------- // PURPOSE: Store the initial status for this drunk ped PROC Store_Initial_Status() // If the char is sitting in a vehicle then make the status 'In Vehicle' otherwise switch on ragdoll m_status.shortTerm = DSST_SWITCH_ON_RAGDOLL IF NOT (IS_ENTITY_DEAD(m_rawDetails.ped)) IF (IS_PED_SITTING_IN_ANY_VEHICLE(m_rawDetails.ped)) // ...started in a vehicle m_status.shortTerm = DSST_IN_VEHICLE ENDIF ENDIF IF (m_thisIsPlayer) BawsaqIncrementDrunkModifier_TIMESDRUNK() BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_TDRNK) //stockmarket #1514495 IF NETWORK_IS_GAME_IN_PROGRESS() INT iDrunkCount = GET_MP_INT_CHARACTER_STAT(MP_STAT_NUM_TIMES_DRUNK) CONST_INT iCONST_THRESHOLD 10 INT iDrunkTarget = ((iDrunkCount/iCONST_THRESHOLD)+1) * iCONST_THRESHOLD CPRINTLN(DEBUG_SHOPS, "Store_Initial_Status: request drunk (", iDrunkCount ," + ", 1, ") >= ", iDrunkTarget, " times") IF (iDrunkCount+1) >= iDrunkTarget REQUEST_SYSTEM_ACTIVITY_TYPE_DRUNK(iDrunkTarget) ENDIF SET_MP_INT_CHARACTER_STAT(MP_STAT_NUM_TIMES_DRUNK, iDrunkCount+1) m_bPlayerDrinkingInMP = TRUE ELSE INT iDrunkCountSP0 = 0, iDrunkCountSP1 = 0, iDrunkCountSP2 = 0 STAT_GET_INT(SP0_SP_NUM_TIMES_DRUNK, iDrunkCountSP0) STAT_GET_INT(SP1_SP_NUM_TIMES_DRUNK, iDrunkCountSP1) STAT_GET_INT(SP2_SP_NUM_TIMES_DRUNK, iDrunkCountSP2) INT iDrunkCount = iDrunkCountSP0+iDrunkCountSP1+iDrunkCountSP2 CONST_INT iCONST_THRESHOLD 10 INT iDrunkTarget = ((iDrunkCount/iCONST_THRESHOLD)+1) * iCONST_THRESHOLD CPRINTLN(DEBUG_SHOPS, "Store_Initial_Status: request drunk (", iDrunkCount ," + ", 1, ") >= ", iDrunkTarget, " times") IF (iDrunkCount+1) >= iDrunkTarget REQUEST_SYSTEM_ACTIVITY_TYPE_DRUNK(iDrunkTarget) ENDIF SWITCH GET_CURRENT_PLAYER_PED_ENUM() CASE CHAR_MICHAEL STAT_SET_INT(SP0_SP_NUM_TIMES_DRUNK, iDrunkCountSP0+1) BREAK CASE CHAR_FRANKLIN STAT_SET_INT(SP1_SP_NUM_TIMES_DRUNK, iDrunkCountSP1+1) BREAK CASE CHAR_TREVOR STAT_SET_INT(SP2_SP_NUM_TIMES_DRUNK, iDrunkCountSP2+1) BREAK ENDSWITCH ENDIF m_status.longTerm = DSLT_PLAYER_CONTROLLED EXIT ENDIF // A leaderless AI m_status.longTerm = DS_IDLE // g_drunkpeds[m_mypedsarrayindex].iAlcoholHit++ // SCRIPT_ASSERT("g_drunkPeds[arrayIndex].iAlcoholHit 555") IF (m_timing.ragdolling = DRUNK_LEVEL_CONSTANT) g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel = DL_verydrunk // m_status.moveClip = Get_Drunk_Level_Moveclip(DL_verydrunk) ELSE IF (g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit < 3 AND g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit <> 0) g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel = DL_NO_LEVEL ELSE INT remainingMsec = (m_timing.ragdolling - TIMERA()) IF (remainingMsec <= 0) remainingMsec = 0 ENDIF remainingMsec = ((remainingMsec / 1000) + 1) g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel = DL_verydrunk IF (remainingMsec < 30) g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel = DL_moderatedrunk // m_status.moveClip = Get_Drunk_Level_Moveclip(DL_moderatedrunk) ENDIF IF (remainingMsec < 10) g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel = DL_slightlydrunk // m_status.moveClip = Get_Drunk_Level_Moveclip(DL_slightlydrunk) ENDIF ENDIF ENDIF ENDPROC // ----------------------------------------------------------------------------------------- // Maintenance // ----------------------------------------------------------------------------------------- // PURPOSE: Check if the ped is still close to his vehicle // // RETURN VALUE: BOOL TRUE if the ped is still close to the target vehicle, otherwise FALSE FUNC BOOL Is_Ped_Close_To_Vehicle() IF (m_rawDetails.vehicle = NULL) RETURN FALSE ENDIF IF (IS_ENTITY_DEAD(m_rawDetails.vehicle)) RETURN FALSE ENDIF VECTOR xyzP = GET_ENTITY_COORDS(m_rawDetails.ped) VECTOR xyzV = GET_ENTITY_COORDS(m_rawDetails.vehicle) FLOAT theDist = GET_DISTANCE_BETWEEN_COORDS(xyzP, xyzV) RETURN (theDist < MAX_DISTANCE_FROM_VEHICLE_m) ENDFUNC // PURPOSE: Check for any changes in the ped status that forces a short-term status change PROC Check_For_Enforced_Short_Term_Status_Changes() // IF (Check_If_Falling()) // EXIT // ENDIF ENDPROC // PURPOSE: Make sure the ped continues to ragdoll for the required duration - NM can quit early under some circumstances PROC Maintain_Ragdolling_For_Required_Duration() IF (m_rawDetails.ped = PLAYER_PED_ID()) // DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_JUMP) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_DUCK) IF GET_PED_STEALTH_MOVEMENT(m_rawDetails.ped) IF (g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel = DL_verydrunk) OR (g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel = DL_moderatedrunk) CPRINTLN(DEBUG_DRUNK, " turn off stealth movement for this drunken ped [", Get_String_From_DrunkLevel(g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel), "]") SET_PED_STEALTH_MOVEMENT(m_rawDetails.ped, FALSE) ELSE CDEBUG1LN(DEBUG_DRUNK, " allow stealth movement for this drunken ped [", Get_String_From_DrunkLevel(g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel), "]") ENDIF ENDIF IF IS_PED_DUCKING(m_rawDetails.ped) CPRINTLN(DEBUG_DRUNK, " turn off ducking for this drunken ped") SET_PED_DUCKING(m_rawDetails.ped, FALSE) ENDIF ENDIF IF (m_timing.ragdolling <> INACTIVE_DRUNK_TIMER) IF (m_timing.ragdolling = DRUNK_LEVEL_CONSTANT) IF (g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel <> DL_verydrunk) g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel = DL_verydrunk // m_status.moveClip = Get_Drunk_Level_Moveclip(DL_verydrunk) ENDIF ELSE INT remainingMsec = (m_timing.ragdolling - TIMERA()) IF (remainingMsec <= 0) remainingMsec = 0 ENDIF remainingMsec = ((remainingMsec / 1000) + 1) IF (g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel = DL_verydrunk) IF (remainingMsec < 30) g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel = DL_moderatedrunk IF NOT Start_Ragdolling(DL_moderatedrunk) g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel = DL_verydrunk EXIT ENDIF ENDIF ENDIF IF (g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel = DL_moderatedrunk) IF (remainingMsec < 10) g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel = DL_slightlydrunk IF NOT Start_Ragdolling(DL_moderatedrunk) g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel = DL_moderatedrunk EXIT ENDIF ENDIF ENDIF IF (g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel = DL_slightlydrunk) ENDIF ENDIF ELSE EXIT ENDIF IF NOT IS_STRING_NULL_OR_EMPTY(m_transitionClip) IF NOT Safe_To_Play_Transition_Animation(m_rawDetails.ped) STRING sTransitionDict = "MOVE_M@DRUNK@TRANSITIONS" IF IS_ENTITY_PLAYING_ANIM(m_rawDetails.ped, sTransitionDict, m_transitionClip) STOP_ANIM_TASK(m_rawDetails.ped, sTransitionDict, m_transitionClip, SLOW_BLEND_OUT) ENDIF m_transitionClip = "" EXIT ENDIF ENDIF // 1/12/2015: AM_MP_PROPERTY_INT.sc references these hardcoded threshold values for being drunk/stoned a lot // so if they every get updated here they should also be updated there IF (g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit >= 10) OR (g_drunkPeds[m_myPedsArrayIndex].iWeedHit >= 15) OR IS_BIT_SET(g_iArcadeFortuneBS, ARCADE_FORTUNE_GLOBAL_BS_DRANK_PEYOTE) IF (GET_SCRIPT_TASK_STATUS(m_rawDetails.ped, SCRIPT_TASK_SYNCHRONIZED_SCENE) = PERFORMING_TASK) AND NOT IS_BIT_SET(g_SimpleInteriorData.iForthBS, BS4_SIMPLE_INTERIOR_GLOBAL_BS_PREVENT_DRUNK_RAGDOLL) EXIT ENDIF IF IS_ANY_SPEECH_PLAYING(m_rawDetails.ped) EXIT ENDIF IF IS_PED_IN_ANY_VEHICLE(m_rawDetails.ped, TRUE) IF (g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit >= 10) g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit = 9 ENDIF IF (g_drunkPeds[m_myPedsArrayIndex].iWeedHit >= 15) g_drunkPeds[m_myPedsArrayIndex].iWeedHit = 14 ENDIF CPRINTLN(DEBUG_DRUNK, " network player is in a vehicle, not passing out.") EXIT ENDIF // no passout for g_sMPTunables.bBB_NIGHTCLUB_DISABLE_NIGHTCLUB_PASS_OUT_DISABLE if ped is in nightclub IF NETWORK_IS_GAME_IN_PROGRESS() AND m_rawDetails.ped = PLAYER_PED_ID() AND IS_PLAYER_IN_NIGHTCLUB(PLAYER_ID()) AND g_sMPTunables.bBB_NIGHTCLUB_DISABLE_NIGHTCLUB_PASS_OUT_DISABLE // reset the limit, so they don't pass out as soon as they walk out the door. IF (g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit >= 10) g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit = 9 ENDIF IF (g_drunkPeds[m_myPedsArrayIndex].iWeedHit >= 15) g_drunkPeds[m_myPedsArrayIndex].iWeedHit = 14 ENDIF CPRINTLN(DEBUG_DRUNK, " network player is in nightclub and g_sMPTunables.bBB_NIGHTCLUB_DISABLE_NIGHTCLUB_PASS_OUT_DISABLE is set, not passing out.") EXIT ENDIF IF NETWORK_IS_GAME_IN_PROGRESS() AND m_rawDetails.ped = PLAYER_PED_ID() AND IS_LOCAL_PLAYER_IN_ARENA_SPECTATOR_BOX() // reset the limit, so they don't pass out as soon as they walk out the door. IF (g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit >= 10) g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit = 9 ENDIF IF (g_drunkPeds[m_myPedsArrayIndex].iWeedHit >= 15) g_drunkPeds[m_myPedsArrayIndex].iWeedHit = 14 ENDIF CPRINTLN(DEBUG_DRUNK, " network player is in Arena Spectator Box, not passing out.") EXIT ENDIF IF NETWORK_IS_GAME_IN_PROGRESS() AND NETWORK_IS_ACTIVITY_SESSION() AND CASINO_HEIST_FLOW_IS_CURRENT_MISSION_CASINO_HEIST_FINALE() IF (g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit >= 10) g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit = 9 ENDIF IF (g_drunkPeds[m_myPedsArrayIndex].iWeedHit >= 15) g_drunkPeds[m_myPedsArrayIndex].iWeedHit = 14 ENDIF CPRINTLN(DEBUG_DRUNK, " network player is in Casino Heist, not passing out.") EXIT ENDIF #IF FEATURE_HEIST_ISLAND IF NETWORK_IS_GAME_IN_PROGRESS() AND NETWORK_IS_ACTIVITY_SESSION() AND HEIST_ISLAND_FLOW_IS_CURRENT_MISSION_HEIST_ISLAND_FINALE() IF (g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit >= 10) g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit = 9 ENDIF IF (g_drunkPeds[m_myPedsArrayIndex].iWeedHit >= 15) g_drunkPeds[m_myPedsArrayIndex].iWeedHit = 14 ENDIF CPRINTLN(DEBUG_DRUNK, " network player is in Island Heist, not passing out.") EXIT ENDIF IF GB_IS_PLAYER_ON_ISLAND_HEIST_SCOPING_MISSION(PLAYER_ID()) IF (g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit >= 10) g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit = 9 ENDIF IF (g_drunkPeds[m_myPedsArrayIndex].iWeedHit >= 15) g_drunkPeds[m_myPedsArrayIndex].iWeedHit = 14 ENDIF CPRINTLN(DEBUG_DRUNK, " network player is on Island Heist scoping mission, not passing out.") EXIT ENDIF #ENDIF IF NETWORK_IS_GAME_IN_PROGRESS() AND m_rawDetails.ped = PLAYER_PED_ID() AND IS_PLAYER_IN_CASINO(PLAYER_ID()) AND g_sMPTunables.bVC_CASINO_DISABLE_PASSOUT // reset the limit, so they don't pass out as soon as they walk out the door. IF (g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit >= 10) g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit = 9 ENDIF IF (g_drunkPeds[m_myPedsArrayIndex].iWeedHit >= 15) g_drunkPeds[m_myPedsArrayIndex].iWeedHit = 14 ENDIF CPRINTLN(DEBUG_DRUNK, " network player is in Arena Spectator Box, not passing out.") EXIT ENDIF IF NETWORK_IS_GAME_IN_PROGRESS() AND m_rawDetails.ped = PLAYER_PED_ID() AND IS_PLAYER_IN_CASINO_APARTMENT(PLAYER_ID()) AND g_sMPTunables.bVC_PENTHOUSE_DISABLE_PASSOUT // reset the limit, so they don't pass out as soon as they walk out the door. IF (g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit >= 10) g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit = 9 ENDIF IF (g_drunkPeds[m_myPedsArrayIndex].iWeedHit >= 15) g_drunkPeds[m_myPedsArrayIndex].iWeedHit = 14 ENDIF CPRINTLN(DEBUG_DRUNK, " network player is in Arena Spectator Box, not passing out.") EXIT ENDIF IF NETWORK_IS_GAME_IN_PROGRESS() AND m_rawDetails.ped = PLAYER_PED_ID() AND GB_GET_GB_CASINO_VARIATION_PLAYER_IS_ON(PLAYER_ID()) = CSV_UNDER_THE_INFLUENCE // reset the limit, so they don't pass out as soon as they walk out the door. IF (g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit >= 10) g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit = 9 ENDIF IF (g_drunkPeds[m_myPedsArrayIndex].iWeedHit >= 15) g_drunkPeds[m_myPedsArrayIndex].iWeedHit = 14 ENDIF CPRINTLN(DEBUG_DRUNK, " network player is playing Under the Influence casino mission, not passing out.") EXIT ENDIF IF NETWORK_IS_GAME_IN_PROGRESS() AND m_rawDetails.ped = PLAYER_PED_ID() AND g_bBrowserVisible AND !g_bHANGOVER_WAKEUP_BROWSER_OPEN_KILLSWITCH // reset the limit, so they don't pass out as soon as they walk out the door. IF (g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit >= 10) g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit = 9 ENDIF IF (g_drunkPeds[m_myPedsArrayIndex].iWeedHit >= 15) g_drunkPeds[m_myPedsArrayIndex].iWeedHit = 14 ENDIF CPRINTLN(DEBUG_DRUNK, " network player browser open, not passing out.") EXIT ENDIF #IF FEATURE_GEN9_EXCLUSIVE IF NETWORK_IS_GAME_IN_PROGRESS() AND IS_PLAYER_IN_OFFICE_PROPERTY(PLAYER_ID()) AND NOT HAS_PLAYER_COMPLETED_MP_INTRO() IF (g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit >= 10) g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit = 9 ENDIF IF (g_drunkPeds[m_myPedsArrayIndex].iWeedHit >= 15) g_drunkPeds[m_myPedsArrayIndex].iWeedHit = 14 ENDIF CPRINTLN(DEBUG_DRUNK, " network player is in Executive Office, not passing out.") EXIT ENDIF #ENDIF // stop network player from passing out inside appartments. // IF NETWORK_IS_GAME_IN_PROGRESS() // IF (m_rawDetails.ped = PLAYER_PED_ID()) // IF (NATIVE_TO_INT(PLAYER_ID()) > -1) // IF (GlobalplayerBD_FM[NATIVE_TO_INT(PLAYER_ID())].propertyDetails.iCurrentlyInsideProperty > 0) // // CPRINTLN(DEBUG_DRUNK, " network player is in appartment, not passing out.") // // // reset the limit, so they don't pass out as soon as they walk out the door. // IF (g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit >= 10) // g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit = 9 // ENDIF // // IF (g_drunkPeds[m_myPedsArrayIndex].iWeedHit >= 15) // g_drunkPeds[m_myPedsArrayIndex].iWeedHit = 14 // ENDIF // // EXIT // ENDIF // ENDIF // ENDIF // ENDIF m_status.longTerm = DSLT_HANGOVER_WAKEUP EXIT ENDIF IF NOT (m_ragdollOn) EXIT ENDIF IF NOT (Is_Ped_At_This_Drunk_Level(m_rawDetails.ped)) //, g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel)) EXIT ENDIF ENDPROC // PURPOSE: If the ped is already ragdolling then the Short-Term status will become Idle, // otherwise ragdolling will activate. PROC Maintain_ShortTerm_Status_Switch_On_Ragdoll() IF (m_timing.ragdolling = DRUNK_LEVEL_CONSTANT) g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel = DL_verydrunk // m_status.moveClip = Get_Drunk_Level_Moveclip(DL_verydrunk) ELSE IF (g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit < 3 AND g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit <> 0) g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel = DL_NO_LEVEL ELSE INT remainingMsec = (m_timing.ragdolling - TIMERA()) IF (remainingMsec <= 0) remainingMsec = 0 ENDIF remainingMsec = ((remainingMsec / 1000) + 1) g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel = DL_verydrunk IF (remainingMsec < 30) g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel = DL_moderatedrunk // m_status.moveClip = Get_Drunk_Level_Moveclip(DL_moderatedrunk) ENDIF IF (remainingMsec < 10) g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel = DL_slightlydrunk // m_status.moveClip = Get_Drunk_Level_Moveclip(DL_slightlydrunk) ENDIF ENDIF ENDIF // Don't ragdoll if in a car IF (IS_PED_IN_ANY_VEHICLE(m_rawDetails.ped)) m_status.shortTerm = DSST_IN_VEHICLE EXIT ENDIF // Don't ragdoll if already ragdolling IF (Is_Ped_At_This_Drunk_Level(m_rawDetails.ped)) //, g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel)) m_status.shortTerm = DS_IDLE EXIT ENDIF // Don't ragdoll if the ragdoll timer has expired IF (m_timing.ragdolling = INACTIVE_DRUNK_TIMER) CPRINTLN(DEBUG_DRUNK, "(m_timing.ragdolling = INACTIVE_DRUNK_TIMER)") EXIT ENDIF IF NOT (Start_Ragdolling(g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel)) EXIT ENDIF // Update the short-term status to Idle m_status.shortTerm = DS_IDLE ENDPROC // PURPOSE: Check to see if the ped should continue with the walking task. PROC Maintain_ShortTerm_Status_Walk() // Check if the activity timer has expired IF (TIMERA() < m_timing.activity) // ...it hasn't expired, so make sure the ped hasn't quit ragdolling when it should still be active Maintain_Ragdolling_For_Required_Duration() EXIT ENDIF // It has expired Stop_Walking() m_timing.activity = INACTIVE_DRUNK_TIMER m_status.shortTerm = DS_IDLE ENDPROC // PURPOSE: Maintains a ped that is close to a vehicle trying to get close enough to enter the vehicle // Assumes that peds are always passengers, that the player is always the driver // Should not be used for the player PROC Maintain_ShortTerm_Status_Enter_Vehicle() CPRINTLN(DEBUG_DRUNK, " Maintain_ShortTerm_Status_Enter_Vehicle") // This shouldn't be the player IF (m_thisIsPlayer) SCRIPT_ASSERT("drunk: Maintain_ShortTerm_Status_Enter_Vehicle(): ped should not be player") EXIT ENDIF // Does the ped have a vehicle? IF (m_rawDetails.vehicle = NULL) CPRINTLN(DEBUG_DRUNK, " vehicle is NULL") // ...no, so switch Ragdoll back on m_status.shortTerm = DSST_SWITCH_ON_RAGDOLL EXIT ENDIF // Make sure the vehicle is still driveable IF NOT (IS_VEHICLE_DRIVEABLE(m_rawDetails.vehicle)) CPRINTLN(DEBUG_DRUNK, " vehicle is not driveable") // ...no, so switch ragdoll back on m_rawDetails.vehicle = NULL m_status.shortTerm = DSST_SWITCH_ON_RAGDOLL EXIT ENDIF // Check if the ped is close enough to start the 'Enter Vehicle' task CONST_FLOAT PASSENGER_THRESHOLD_m 3.0 VECTOR xyzMe = GET_ENTITY_COORDS(m_rawDetails.ped) VECTOR xyzV = GET_ENTITY_COORDS(m_rawDetails.vehicle) FLOAT theDist = GET_DISTANCE_BETWEEN_COORDS(xyzMe, xyzV) IF (theDist > PASSENGER_THRESHOLD_m) CPRINTLN(DEBUG_DRUNK, " still a bit far away") // Make the ped walk a bit closer IF NOT (Start_Ragdolling(g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel)) // ...failed to activate walking m_status.shortTerm = DS_IDLE EXIT ENDIF CONST_INT WALK_TIME_msec 2000 // Set the action and activity timer m_status.shortTerm = DSST_WALK m_timing.activity = TIMERA() + WALK_TIME_msec EXIT ENDIF // Choose an empty passenger seat INT maxPassengersAllowed = GET_VEHICLE_MAX_NUMBER_OF_PASSENGERS(m_rawDetails.vehicle) INT thisSeat = 0 BOOL keepChecking = TRUE // If the leader is in the back of a taxi, then only check the back two seats //KGMTAXI IF (IS_CHAR_IN_BACK_OF_TAXI(m_rawDetails.leader)) thisSeat = 1 //KGMTAXI ENDIF WHILE (keepChecking) IF (thisSeat < maxPassengersAllowed) // ...check if this car seat is free IF (IS_VEHICLE_SEAT_FREE(m_rawDetails.vehicle, INT_TO_ENUM(VEHICLE_SEAT, thisSeat))) CPRINTLN(DEBUG_DRUNK, " found an empty car seat") keepChecking = FALSE ELSE thisSeat++ ENDIF ELSE // ...ran out of car seats keepChecking = FALSE thisSeat = NO_AVAILABLE_SEAT ENDIF ENDWHILE // If there is no available seat, switch on ragdoll again (except, for a taxi, try the front passenger seat) IF (thisSeat = NO_AVAILABLE_SEAT) //KGMTAXI IF NOT (IS_CHAR_IN_BACK_OF_TAXI(m_rawDetails.leader)) //KGMTAXI // ...try front passenger seat //KGMTAXI IF (IS_CAR_PASSENGER_SEAT_FREE(m_rawDetails.vehicle, SEAT_FRONT_PASSENGER)) //KGMTAXI thisSeat = SEAT_FRONT_PASSENGER //KGMTAXI CPRINTLN(DEBUG_DRUNK, " using front seat of the taxi") //KGMTAXI ENDIF //KGMTAXI ENDIF // May now have found a seat, so do another check IF (thisSeat = NO_AVAILABLE_SEAT) CPRINTLN(DEBUG_DRUNK, " failed to find an empty car seat") m_status.shortTerm = DSST_SWITCH_ON_RAGDOLL EXIT ENDIF ENDIF // Found a seat // Stop Natural Motion and get ped into car Stop_Ragdolling() //SET_NEXT_DESIRED_MOVE_BLEND_RATIO(PEDMOVE_WALK) //- deprecated // Enter player's car as a passenger CPRINTLN(DEBUG_DRUNK, " enter car as passenger [thisSeat:", thisSeat, "]") TASK_ENTER_VEHICLE(m_rawDetails.ped, m_rawDetails.vehicle, -1, INT_TO_ENUM(VEHICLE_SEAT, thisSeat)) m_status.shortTerm = DSST_ENTERING_VEHICLE ENDPROC // PURPOSE: Maintain the process of getting a ped into a vehicle // Assumes that peds are always passengers, that the player is always the driver PROC Maintain_ShortTerm_Status_Entering_Vehicle() IF NOT (m_thisIsPlayer) CPRINTLN(DEBUG_DRUNK, " Maintain_ShortTerm_Status_Entering_Vehicle") ENDIF VEHICLE_INDEX thisVehicle = NULL // Is the ped sitting in the back of a taxi? BOOL inBackOfTaxi = FALSE //KGMTAXI IF (IS_CHAR_IN_BACK_OF_TAXI(m_rawDetails.ped)) //KGMTAXI inBackOfTaxi = TRUE //KGMTAXI //KGMTAXI IF NOT (m_thisIsPlayer) //KGMTAXI CPRINTLN(DEBUG_DRUNK, " in back of taxi") //KGMTAXI ENDIF //KGMTAXI ENDIF // Is the ped sitting in a car or in the back of a taxi? IF (inBackOfTaxi) OR (IS_PED_SITTING_IN_ANY_VEHICLE(m_rawDetails.ped)) IF NOT (m_thisIsPlayer) CPRINTLN(DEBUG_DRUNK, " in a vehicle") ENDIF // ...ped is in the back of a taxi or is sitting in any car // Is the taxi the vehicle the ped is supposed to be in? thisVehicle = GET_VEHICLE_PED_IS_IN(m_rawDetails.ped) IF NOT (thisVehicle = m_rawDetails.vehicle) IF NOT (m_thisIsPlayer) CPRINTLN(DEBUG_DRUNK, " wrong vehicle") ENDIF // ...this is the wrong vehicle, so exit the vehicle again if this ped is not the player IF NOT (m_thisIsPlayer) IF NOT (m_thisIsPlayer) CPRINTLN(DEBUG_DRUNK, " leave vehicle") ENDIF // ...this is not the player // Ped's can only be in the wrong vehicle if they are following another ped and they don't have // their own vehicle, so eject them TASK_LEAVE_ANY_VEHICLE(m_rawDetails.ped) m_status.shortTerm = DSST_LEAVE_VEHICLE EXIT ENDIF // This is the player, so this has to be the 'correct' vehicle, so update the vehicle // to be the current vehicle m_rawDetails.vehicle = thisVehicle ENDIF // If the ped is in a taxi and the taxi is the correct car then there is nothing else to do, // so update the status to be 'in vehicle' IF (inBackOfTaxi) IF NOT (m_thisIsPlayer) CPRINTLN(DEBUG_DRUNK, " status now In Vehicle (back of taxi)") ENDIF Change_ShortTerm_Status_To_In_Vehicle() EXIT ENDIF // If this is not the player then there is nothing else to do IF NOT (m_thisIsPlayer) IF NOT (m_thisIsPlayer) CPRINTLN(DEBUG_DRUNK, " status now In Vehicle") ENDIF Change_ShortTerm_Status_To_In_Vehicle() EXIT ENDIF IF NOT (m_thisIsPlayer) CPRINTLN(DEBUG_DRUNK, " NON-PLAYER'S SHOULDN'T REACH HERE") ENDIF // This is the player // Is the player driving the vehicle? PED_INDEX driverOfVehicle = GET_PED_IN_VEHICLE_SEAT(m_rawDetails.vehicle, VS_DRIVER) IF (driverOfVehicle = m_rawDetails.ped) // ...player is the driver, so nothing else to do Change_ShortTerm_Status_To_In_Vehicle() EXIT ENDIF // Player is not the driver, so the player needs to shuffle over to the driver's seat TASK_SHUFFLE_TO_NEXT_VEHICLE_SEAT(m_rawDetails.ped, thisVehicle) // Change the status and create a failsafe timeout m_status.shortTerm = DSST_SHUFFLE_CARSEATS m_timing.failsafe = TIMERA() + FAILSAFE_SHUFFLE_TIMEOUT_msec EXIT ENDIF // Ped is not in a vehicle, so check if the vehicle has moved away IF NOT (Is_Ped_Close_To_Vehicle()) CLEAR_PED_TASKS(m_rawDetails.ped) m_status.shortTerm = DSST_SWITCH_ON_RAGDOLL EXIT ENDIF // AI may get locked out of a taxi while the player is choosing destinations, etc IF NOT (m_thisIsPlayer) SCRIPTTASKSTATUS thisStatus = GET_SCRIPT_TASK_STATUS(m_rawDetails.ped, SCRIPT_TASK_ENTER_VEHICLE) IF (thisStatus = FINISHED_TASK) // ...The 'enter car' task has ended but it looks like the AI is still not in the car // If the leader is in the back of a taxi then warp this drunk ped into a free taxi seat // NOTE: The taxi script locks the player inside while choosing destinations //KGMTAXI IF (IS_CHAR_IN_BACK_OF_TAXI(m_rawDetails.leader)) //KGMTAXI // ...leader is in back of taxi //KGMTAXI // Is this AI sitting in a car? //KGMTAXI IF NOT (IS_CHAR_SITTING_IN_ANY_CAR(m_rawDetails.ped)) //KGMTAXI Warp_Into_Leaders_Taxi() //KGMTAXI EXIT //KGMTAXI ENDIF //KGMTAXI ELSE // IF the task is finished and the ped is not in any car then it may be that the car seat he // was heading for has been filled, so switch on ragdolling again IF NOT (IS_PED_IN_ANY_VEHICLE(m_rawDetails.ped)) CLEAR_PED_TASKS(m_rawDetails.ped) m_status.shortTerm = DSST_SWITCH_ON_RAGDOLL EXIT ENDIF //KGMTAXI ENDIF ENDIF ENDIF ENDPROC // PURPOSE: Makes sure that the ped successfully warps into the taxi PROC Maintain_ShortTerm_Status_Warp_Into_Taxi() // Is the ped sitting in a car? IF (IS_PED_SITTING_IN_ANY_VEHICLE(m_rawDetails.ped)) // Change status to 'in vehicle' m_status.shortTerm = DSST_IN_VEHICLE EXIT ENDIF // Not yet in the car - check for failsafe timeout IF (TIMERA() < m_timing.failsafe) EXIT ENDIF // Timed Out so switch back to ragdoll m_status.shortTerm = DSST_SWITCH_ON_RAGDOLL m_timing.failsafe = INACTIVE_DRUNK_TIMER ENDPROC // PURPOSE: Make sure that the ped manages to complete the 'shuffle carseats' task. PROC Maintain_ShortTerm_Status_Shuffle_Carseats() // Check for failsafe timeout IF (TIMERA() <= m_timing.failsafe) EXIT ENDIF // Timeout has occurred SCRIPTTASKSTATUS thisStatus = GET_SCRIPT_TASK_STATUS(PLAYER_PED_ID(), SCRIPT_TASK_SHUFFLE_TO_NEXT_VEHICLE_SEAT) IF NOT (thisStatus = FINISHED_TASK) // Extend the failsafe timer then test again later m_timing.failsafe = TIMERA() + FAILSAFE_SHUFFLE_TIMEOUT_msec EXIT ENDIF // The task is finished. // If the ped is no longer in any car then swap back to ragdoll IF NOT (IS_PED_IN_ANY_VEHICLE(m_rawDetails.ped)) m_status.shortTerm = DSST_SWITCH_ON_RAGDOLL m_timing.failsafe = INACTIVE_DRUNK_TIMER EXIT ENDIF // Check if the ped is now successfully the driver of the vehicle VEHICLE_INDEX thisVehicle = GET_VEHICLE_PED_IS_IN(m_rawDetails.ped) PED_INDEX driverOfVehicle = GET_PED_IN_VEHICLE_SEAT(thisVehicle, VS_DRIVER) IF (driverOfVehicle = m_rawDetails.ped) // ...this ped is the driver, so task complete Change_ShortTerm_Status_To_In_Vehicle() m_timing.failsafe = INACTIVE_DRUNK_TIMER EXIT ENDIF // This ped is not the driver, so give the shuffle task again TASK_SHUFFLE_TO_NEXT_VEHICLE_SEAT(m_rawDetails.ped, thisVehicle) // Change the status and create a failsafe timeout m_status.shortTerm = DSST_SHUFFLE_CARSEATS m_timing.failsafe = TIMERA() + FAILSAFE_SHUFFLE_TIMEOUT_msec ENDPROC // PURPOSE: Maintain the 'In Vehicle' task // For the player, this checks if the player has left the vehicle. PROC Maintain_ShortTerm_Status_In_Vehicle() // Nothing to do if the ped is no longer in the vehicle IF NOT (IS_PED_IN_ANY_VEHICLE(m_rawDetails.ped)) // ...ped is no longer in any vehicle, so switch on ragdoll again m_status.shortTerm = DSST_SWITCH_ON_RAGDOLL EXIT ENDIF // if player drinks too much in vehicle IF NETWORK_IS_GAME_IN_PROGRESS() IF (g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit >= 10) OR (g_drunkPeds[m_myPedsArrayIndex].iWeedHit >= 15) // limit how drunk / stoned they get in vehicle so they never pass out. IF (g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit >= 10) g_drunkPeds[m_myPedsArrayIndex].iAlcoholHit = 9 CPRINTLN(DEBUG_DRUNK, "Maintain_ShortTerm_Status_In_Vehicle - limiting how drunk ped can get in vehicle.") ENDIF IF (g_drunkPeds[m_myPedsArrayIndex].iWeedHit >= 15) g_drunkPeds[m_myPedsArrayIndex].iWeedHit = 14 CPRINTLN(DEBUG_DRUNK, "Maintain_ShortTerm_Status_In_Vehicle - limiting how stoned ped can get in vehicle.") ENDIF // CPRINTLN(DEBUG_DRUNK, "Maintain_ShortTerm_Status_In_Vehicle - too drunk in vehicle mp, fading out.") // // IF NOT (GET_SCRIPT_TASK_STATUS(m_rawDetails.ped, SCRIPT_TASK_SYNCHRONIZED_SCENE) = PERFORMING_TASK) // AND NOT (IS_ANY_SPEECH_PLAYING(m_rawDetails.ped)) // // IF NOT IS_SCREEN_FADED_OUT() // DO_SCREEN_FADE_OUT(DEFAULT_FADE_TIME_LONG) // WHILE IS_SCREEN_FADING_OUT() // WAIT(0) // ENDWHILE // ENDIF // // IF NOT IS_PED_INJURED(m_rawDetails.ped) // IF IS_PED_IN_ANY_VEHICLE(m_rawDetails.ped) // TASK_LEAVE_ANY_VEHICLE(m_rawDetails.ped) // ENDIF // ENDIF // // // if in network game just cleanup and set flag for neil // IF NETWORK_IS_GAME_IN_PROGRESS() // // NET_SET_PLAYER_CONTROL(PLAYER_ID(), FALSE, NSPC_SET_INVISIBLE | NSPC_NO_COLLISION | NSPC_FREEZE_POSITION) // g_SpawnData.bPassedOutDrunk = TRUE // IF IS_PLAYER_WANTED_LEVEL_GREATER(PLAYER_ID(), 0 ) // g_SpawnData.bPassedOutDrunkWithWantedLevel = TRUE // ELSE // g_SpawnData.bPassedOutDrunkWithWantedLevel = FALSE // ENDIF // // Quit_Drunk_Camera_Immediately() // Drunk_Cleanup() // ENDIF // // // EXIT // ENDIF ENDIF ENDIF // Ped is still in the vehicle // If this is the player then nothing more to do IF (m_thisIsPlayer) EXIT ENDIF // This is an AI VEHICLE_INDEX thisVehicle = GET_VEHICLE_PED_IS_IN(m_rawDetails.ped) // If the vehicle is no longer driveable then exit IF NOT (IS_VEHICLE_DRIVEABLE(thisVehicle)) TASK_LEAVE_ANY_VEHICLE(m_rawDetails.ped) m_status.shortTerm = DSST_LEAVE_VEHICLE EXIT ENDIF // Seems fine to leave the ped in this state ENDPROC // PURPOSE: Calculate and return a steering bias FUNC FLOAT Friend_Drink_Calculate_Steering_Bias(ENTITY_INDEX EntityIndex, FLOAT paramRange, FLOAT paramOffset) // INPUT PARAMS: paramRange // The max distance from 0.0 (+ or -) // paramOffset // An offset to add on to the distance // RETURN VALUE: FLOAT // The calculated bias (between -1.0 and 1.0) FLOAT thisValue = GET_RANDOM_FLOAT_IN_RANGE(-paramRange, paramRange) FLOAT thisOffset = GET_RANDOM_FLOAT_IN_RANGE(0.0, paramOffset) IF (thisValue < 0.0) thisValue -= thisOffset ELSE thisValue += thisOffset ENDIF IF IS_ENTITY_A_PED(EntityIndex) IF IS_PED_SPRINTING(GET_PED_INDEX_FROM_ENTITY_INDEX(EntityIndex)) CONST_FLOAT fCONST_DRUNK_STERRRING_BIAS_PED_SPRINT_MULTIPLIER 4.5 thisValue *= fCONST_DRUNK_STERRRING_BIAS_PED_SPRINT_MULTIPLIER ELSE CONST_FLOAT fCONST_DRUNK_STERRRING_BIAS_PED_MULTIPLIER 3.0 thisValue *= fCONST_DRUNK_STERRRING_BIAS_PED_MULTIPLIER ENDIF ELSE MODEL_NAMES EntityModelHashKey = GET_ENTITY_MODEL(EntityIndex) IF IS_THIS_MODEL_A_BIKE(EntityModelHashKey) CONST_FLOAT fCONST_DRUNK_STERRRING_BIAS_BIKE_MULTIPLIER 1.5 thisValue *= fCONST_DRUNK_STERRRING_BIAS_BIKE_MULTIPLIER ELSE CONST_FLOAT fCONST_DRUNK_STERRRING_BIAS_MULTIPLIER 0.5 thisValue *= fCONST_DRUNK_STERRRING_BIAS_MULTIPLIER ENDIF ENDIF thisValue = CLAMP(thisValue, -1.0000, 1.0000) RETURN thisValue ENDFUNC // PURPOSE: Update the Steering Bias if the ped is the driver of a car PROC Maintain_Steering_Bias() ENTITY_INDEX theEntity = m_rawDetails.ped // Is the Char still in a car? IF (IS_PED_IN_ANY_VEHICLE(m_rawDetails.ped)) // Is the char the driver of the car? VEHICLE_INDEX theCar = GET_VEHICLE_PED_IS_IN(m_rawDetails.ped) PED_INDEX theDriver = GET_PED_IN_VEHICLE_SEAT(theCar, VS_DRIVER) IF NOT (theDriver = m_rawDetails.ped) EXIT ENDIF IF NETWORK_IS_GAME_IN_PROGRESS() AND NOT NETWORK_HAS_CONTROL_OF_ENTITY(theCar) CDEBUG1LN(DEBUG_DRUNK, "Maintain_Steering_Bias called when network doesn't have control of entity") EXIT ENDIF theEntity = theCar ELIF NOT (PLAYER_PED_ID() = m_rawDetails.ped) EXIT ELIF NOT (GET_FOLLOW_PED_CAM_VIEW_MODE() = CAM_VIEW_MODE_FIRST_PERSON) m_steeringBias = 0.0 Set_Entity_Steer_Bias(theEntity, 0.0) EXIT ENDIF // Has the Steering Bias timer expired? IF (TIMERA() < m_timing.steeringTime) Set_Entity_Steer_Bias(theEntity, m_steeringBias) EXIT ENDIF // Set up a new timer IF (IS_ENTITY_A_PED(theEntity)) m_timing.steeringTime = TIMERA() + STEERING_BIAS_PED_TIMEOUT_msec ELSE m_timing.steeringTime = TIMERA() + STEERING_BIAS_TIMEOUT_msec ENDIF // Is the car still moving? FLOAT thisSpeed = GET_ENTITY_SPEED(theEntity) IF (thisSpeed < SPEED_CLASSED_AS_STOPPED) m_steeringBias = 0.0 Set_Entity_Steer_Bias(theEntity, 0.0) EXIT ENDIF // Give the car a new steering bias - this should be based on the overall time remaining IF (m_timing.overall = DRUNK_LEVEL_CONSTANT) m_steeringBias = Friend_Drink_Calculate_Steering_Bias(theEntity, 0.13, 0.06) CDEBUG1LN(DEBUG_DRUNK, " m_steeringBias: ", "drunk level constant, so extreme //", m_steeringBias) ELSE INT timeRemaining = m_timing.overall - TIMERA() IF (timeRemaining < 05000) m_steeringBias = 0.0 CDEBUG1LN(DEBUG_DRUNK, " m_steeringBias: ", TO_FLOAT(timeRemaining) / 1000.0, " less than 10 secs, so none //", m_steeringBias) ELIF (timeRemaining < 15000) m_steeringBias = Friend_Drink_Calculate_Steering_Bias(theEntity, 0.05, 0.02) CDEBUG1LN(DEBUG_DRUNK, " m_steeringBias: ", TO_FLOAT(timeRemaining) / 1000.0, " less than 30 secs, so mild //", m_steeringBias) ELIF (timeRemaining < 30000) m_steeringBias = Friend_Drink_Calculate_Steering_Bias(theEntity, 0.07, 0.03) CDEBUG1LN(DEBUG_DRUNK, " m_steeringBias: ", TO_FLOAT(timeRemaining) / 1000.0, " less than 60 secs, so medium //", m_steeringBias) ELIF (timeRemaining < 45000) m_steeringBias = Friend_Drink_Calculate_Steering_Bias(theEntity, 0.09, 0.04) CDEBUG1LN(DEBUG_DRUNK, " m_steeringBias: ", TO_FLOAT(timeRemaining) / 1000.0, " less than 90 secs, so heavy //", m_steeringBias) ELIF (timeRemaining < 600000) m_steeringBias = Friend_Drink_Calculate_Steering_Bias(theEntity, 0.1, 0.05) CDEBUG1LN(DEBUG_DRUNK, " m_steeringBias: ", TO_FLOAT(timeRemaining) / 1000.0, " less than 120 secs, so very heavy //", m_steeringBias) ELSE m_steeringBias = Friend_Drink_Calculate_Steering_Bias(theEntity, 0.13, 0.06) CDEBUG1LN(DEBUG_DRUNK, " m_steeringBias: ", TO_FLOAT(timeRemaining) / 1000.0, " greater than 120 secs, so extreme //", m_steeringBias) ENDIF ENDIF Set_Entity_Steer_Bias(theEntity, m_steeringBias) ENDPROC // PURPOSE: Check if the player should get a wanted level for driving drunk past a police car PROC Maintain_Wanted_Level() IF NOT (m_thisIsPlayer) EXIT ENDIF IF NOT (IS_PLAYER_PLAYING(PLAYER_ID())) EXIT ENDIF //KGMTAXI IF (IS_CHAR_IN_BACK_OF_TAXI(PLAYER_PED_ID())) //KGMTAXI EXIT //KGMTAXI ENDIF IF NOT (IS_PED_SITTING_IN_ANY_VEHICLE(PLAYER_PED_ID())) EXIT ENDIF IF (IS_PLAYER_WANTED_LEVEL_GREATER(PLAYER_ID(), 0)) EXIT ENDIF // Ignore if the steering bias has stopped // ...TO DO // Ignore if the the car is moving slowly VEHICLE_INDEX theCar = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()) FLOAT thisSpeed = GET_ENTITY_SPEED(theCar) CONST_FLOAT MINIMUM_CAR_SPEED 5.0 IF (thisSpeed < MINIMUM_CAR_SPEED) EXIT ENDIF // Is there a police car nearby? CONST_FLOAT NEARBY_POLICE_CAR_RANGE_m 30.0 CONST_FLOAT NEARBY_POLICE_CAR_HEIGHT_m 3.0 VECTOR xyzPlayer = GET_ENTITY_COORDS(PLAYER_PED_ID()) VECTOR xyzMin = xyzPlayer - <> VECTOR xyzMax = xyzPlayer + <> IF NOT (IS_COP_VEHICLE_IN_AREA_3D(xyzMin, xyzMax)) AND NOT (IS_COP_PED_IN_AREA_3D(xyzMin, xyzMax)) EXIT ENDIF SET_PLAYER_WANTED_LEVEL_NO_DROP(PLAYER_ID(), 1) SET_PLAYER_WANTED_LEVEL_NOW(PLAYER_ID()) BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_DRNKCRM) //stockmarket #1514495 CPRINTLN(DEBUG_DRUNK, "Maintain_Wanted_Level") ENDPROC // PURPOSE: Switch on ragdoll again when a ped has left his vehicle PROC Maintain_ShortTerm_Status_Leave_Vehicle() IF NOT (IS_PED_IN_ANY_VEHICLE(m_rawDetails.ped)) // ...ped is no longer in any vehicle, so switch on ragdoll again m_status.shortTerm = DSST_SWITCH_ON_RAGDOLL EXIT ENDIF ENDPROC // PURPOSE: Generate a new short-term task when the long-term task is 'Get Into Vehicle' PROC Maintain_LongTerm_Status_Get_Into_Vehicle() CPRINTLN(DEBUG_DRUNK, " Maintain_LongTerm_Status_Get_Into_Vehicle") // This shouldn't be the player IF (m_thisIsPlayer) SCRIPT_ASSERT("drunk: Maintain_LongTerm_Status_Get_Into_Vehicle(): ped should not be player") EXIT ENDIF IF NOT (Is_Ped_Close_To_Vehicle()) CONST_INT WALK_TIME_msec 5000 // Set the action and activity timer m_status.shortTerm = DSST_WALK m_timing.activity = TIMERA() + WALK_TIME_msec EXIT ENDIF // Ped is now close to the leader's vehicle, so enter the vehicle m_status.shortTerm = DSST_ENTER_VEHICLE ENDPROC // PURPOSE: Generate a new short-term task when the long-term task is 'Idle' PROC Maintain_LongTerm_Status_Idle() // This shouldn't be the player IF (m_thisIsPlayer) SCRIPT_ASSERT("drunk: Maintain_LongTerm_Status_Idle(): ped should not be player") EXIT ENDIF // Remove the ped's vehicle - for Idle there can't be a leader so no vehicle m_rawDetails.vehicle = NULL // Ped has no leader so make this ped lean randomly (and perhaps therefore walk) // VECTOR xyzMe = GET_ENTITY_COORDS(m_rawDetails.ped) // // FLOAT leanValue = GET_RANDOM_FLOAT_IN_RANGE(0.05, WALKING_LEAN_VALUE) // Activate a short-term walking task IF NOT (Start_Ragdolling(g_drunkPeds[m_myPedsArrayIndex].eDrunkLevel)) // ...failed to activate walking EXIT ENDIF CONST_INT LEAN_TIME_MIN_msec 500 CONST_INT LEAN_TIME_MAX_msec 3000 INT theTime = GET_RANDOM_INT_IN_RANGE(LEAN_TIME_MIN_msec, LEAN_TIME_MAX_msec) // Set the action and activity timer m_status.shortTerm = DSST_WALK m_timing.activity = TIMERA() + theTime ENDPROC PROC Maintain_LongTerm_Status_Hangover_Wakeup() IF NOT IS_BIT_SET(g_SimpleInteriorData.iForthBS, BS4_SIMPLE_INTERIOR_GLOBAL_BS_PREVENT_DRUNK_RAGDOLL) SET_PED_TO_RAGDOLL(m_rawDetails.ped, DEFAULT_FADE_TIME_LONG+0500, DEFAULT_FADE_TIME_LONG+1000, TASK_RELAX) ENDIF g_bMPPlayerPassingOutDrunk = TRUE IF NOT IS_SCREEN_FADED_OUT() DO_SCREEN_FADE_OUT(DEFAULT_FADE_TIME_LONG) WHILE IS_SCREEN_FADING_OUT() WAIT(0) ENDWHILE ENDIF // if in network game just cleanup and set flag for neil IF NETWORK_IS_GAME_IN_PROGRESS() //NETWORK_LEAVE_PED_BEHIND_BEFORE_WARP(PLAYER_ID(), GET_ENTITY_COORDS(PLAYER_PED_ID(), FALSE), TRUE, TRUE) SCRIPT_TIMER stPlayerFade START_NET_TIMER(stPlayerFade) IF DOES_ENTITY_EXIST(PLAYER_PED_ID()) AND NOT IS_ENTITY_DEAD(PLAYER_PED_ID()) NETWORK_FADE_OUT_ENTITY(PLAYER_PED_ID(), FALSE, TRUE) ENDIF WHILE DOES_ENTITY_EXIST(PLAYER_PED_ID()) AND NOT IS_ENTITY_DEAD(PLAYER_PED_ID()) AND NETWORK_GET_ENTITY_IS_NETWORKED(PLAYER_PED_ID()) // url:bugstar:7854566 - Caused by player getting dunk in MP and switching sessions while passing out AND NETWORK_IS_ENTITY_FADING(PLAYER_PED_ID()) WAIT(0) ENDWHILE IF NOT NETWORK_GET_ENTITY_IS_NETWORKED(PLAYER_PED_ID()) // url:bugstar:7854566 - Caused by player getting dunk in MP and switching sessions while passing out PRINTLN("Maintain_LongTerm_Status_Hangover_Wakeup - Stopping drunk.sc because player ped is not networked while drunk in MP") Drunk_Cleanup() ENDIF CLEAR_BIT(g_SimpleInteriorData.iForthBS, BS4_SIMPLE_INTERIOR_GLOBAL_BS_PREVENT_DRUNK_RAGDOLL) NET_SET_PLAYER_CONTROL(PLAYER_ID(), FALSE, NSPC_SET_INVISIBLE | NSPC_NO_COLLISION | NSPC_FREEZE_POSITION) g_SpawnData.bPassedOutDrunk = TRUE IF IS_BIT_SET(g_SimpleInteriorData.iBS ,BS_SIMPLE_INTERIOR_GLOBAL_DATA_ALL_EXIT_BUNKER_FROM_TRUCK_TRIGGERED) CLEAR_BIT(g_SimpleInteriorData.iBS ,BS_SIMPLE_INTERIOR_GLOBAL_DATA_ALL_EXIT_BUNKER_FROM_TRUCK_TRIGGERED) PRINTLN("Maintain_LongTerm_Status_Hangover_Wakeup - BS_SIMPLE_INTERIOR_GLOBAL_DATA_ALL_EXIT_BUNKER_FROM_TRUCK_TRIGGERED FALSE") ENDIF IF IS_BIT_SET(g_SimpleInteriorData.iThirdBS, BS3_SIMPLE_INTERIOR_GLOBAL_DATA_ALL_EXIT_BASE_FROM_AIRCRAFT_TRIGGERED) CLEAR_BIT(g_SimpleInteriorData.iThirdBS, BS3_SIMPLE_INTERIOR_GLOBAL_DATA_ALL_EXIT_BASE_FROM_AIRCRAFT_TRIGGERED) PRINTLN("Maintain_LongTerm_Status_Hangover_Wakeup - BS3_SIMPLE_INTERIOR_GLOBAL_DATA_ALL_EXIT_BASE_FROM_AIRCRAFT_TRIGGERED FALSE") ENDIF IF IS_PLAYER_WANTED_LEVEL_GREATER(PLAYER_ID(), 0 ) g_SpawnData.bPassedOutDrunkWithWantedLevel = TRUE ELSE g_SpawnData.bPassedOutDrunkWithWantedLevel = FALSE ENDIF IF IS_SCRIPT_GLOBAL_SHAKING() CPRINTLN(DEBUG_DRUNK, "Maintain_LongTerm_Status_Hangover_Wakeup: someone started a global script cam shake, nuke it on drunk wakeup!!") STOP_SCRIPT_GLOBAL_SHAKING() ENDIF IF GB_IS_LOCAL_PLAYER_MEMBER_OF_A_BIKER_GANG() BIK_ADD_POINTS_FOR_THIS(BIK_ADD_POINTS_DRUNK) ENDIF Quit_Drunk_Camera_Immediately() Drunk_Cleanup() ENDIF // Should not reach SP part below if player got wasted in MP IF m_bPlayerDrinkingInMP // url:bugstar:7854566 - Caused by player getting dunk in MP and switching sessions while passing out PRINTLN("Maintain_LongTerm_Status_Hangover_Wakeup - Stopping drunk.sc because player is no longer in MP session while started to pass out drunk in MP") Drunk_Cleanup() ENDIF STRING pDrunkDebugName = "" RESPAWN_CUTSCENE_STRUCT sRespawnCutscene g_eDrunkWakeupCutscene eDrunkWakeupScene = DWC_NO_DRUNK_WAKEUP_CUTSCENE SWITCH GET_CURRENT_PLAYER_PED_ENUM() CASE CHAR_MICHAEL IF (GetMichaelScheduleStage() <> MSS_M6_Exiled) eDrunkWakeupScene = DWC_MICHAEL_mansion ELSE eDrunkWakeupScene = DWC_MICHAEL_trailer ENDIF BREAK CASE CHAR_FRANKLIN IF NOT Get_Mission_Flow_Flag_State(FLOWFLAG_FRANKLIN_MOVED_TO_HILLS_APARTMENT) eDrunkWakeupScene = DWC_FRANKLIN_city ELSE eDrunkWakeupScene = DWC_FRANKLIN_hills ENDIF BREAK CASE CHAR_TREVOR IF NOT Is_Savehouse_Respawn_Available(SAVEHOUSE_TREVOR_SC) IF Get_Mission_Flow_Flag_State(FLOWFLAG_TREVOR_RESTRICTED_TO_COUNTRY) eDrunkWakeupScene = DWC_TREVOR_trailer ENDIF IF Get_Mission_Flow_Flag_State(FLOWFLAG_TREVOR_RESTRICTED_TO_CITY) eDrunkWakeupScene = DWC_TREVOR_beach ENDIF IF (eDrunkWakeupScene = DWC_NO_DRUNK_WAKEUP_CUTSCENE) IF NOT GET_RANDOM_BOOL() eDrunkWakeupScene = DWC_TREVOR_trailer ELSE eDrunkWakeupScene = DWC_TREVOR_beach ENDIF ENDIF ELSE eDrunkWakeupScene = DWC_TREVOR_stripclub ENDIF BREAK ENDSWITCH SWITCH eDrunkWakeupScene CASE DWC_MICHAEL_mansion pDrunkDebugName = "DWC_MICHAEL_mansion" sRespawnCutscene.pAnimDictName = "SAVEM_Default@" sRespawnCutscene.pAnimClipName = "M_GetOut_R" sRespawnCutscene.pAnimCamName = "M_GetOut_R_CAM" sRespawnCutscene.vAnimPos = <<-814.181, 181.100, 75.740 >> sRespawnCutscene.vAnimRot = <<0.0000, 0.0000, 21.1994 >> sRespawnCutscene.ePedMotionState = MS_ON_FOOT_IDLE BREAK CASE DWC_MICHAEL_trailer pDrunkDebugName = "DWC_MICHAEL_trailer" sRespawnCutscene.pAnimDictName = "SAVECountryside@" sRespawnCutscene.pAnimClipName = "M_GetOut_countryside" sRespawnCutscene.pAnimCamName = "M_GetOut_countryside_CAM" sRespawnCutscene.vAnimPos = <<1968.14, 3816.79, 32.4287>> sRespawnCutscene.vAnimRot = <<0.0000, 0.0000, 29.7938 >> sRespawnCutscene.ePedMotionState = MS_ON_FOOT_IDLE BREAK CASE DWC_FRANKLIN_city pDrunkDebugName = "DWC_FRANKLIN_city" sRespawnCutscene.pAnimDictName = "SWITCH@FRANKLIN@BED" sRespawnCutscene.pAnimClipName = "Sleep_GetUp_RubEyes" sRespawnCutscene.pAnimCamName = "Sleep_GetUp_RubEyes_CAM" sRespawnCutscene.vAnimPos = <<-17.2168, -1441.2240, 30.1015>> sRespawnCutscene.vAnimRot = <<0.0000, 0.0000, -179.6530>> sRespawnCutscene.ePedMotionState = MS_ON_FOOT_IDLE BREAK CASE DWC_FRANKLIN_hills pDrunkDebugName = "DWC_FRANKLIN_hills" sRespawnCutscene.pAnimDictName = "SAVEBighouse@" sRespawnCutscene.pAnimClipName = "F_GetOut_r_bighouse" sRespawnCutscene.pAnimCamName = "F_GetOut_r_bighouse_CAM" sRespawnCutscene.vAnimPos = <<-1.049, 524.283, 170.064 >> sRespawnCutscene.vAnimRot = <<0.0000, 0.0000, 24.000 >> sRespawnCutscene.ePedMotionState = MS_ON_FOOT_IDLE BREAK CASE DWC_TREVOR_trailer pDrunkDebugName = "DWC_TREVOR_trailer" sRespawnCutscene.pAnimDictName = "SAVECountryside@" sRespawnCutscene.pAnimClipName = "T_GetOut_countryside" sRespawnCutscene.pAnimCamName = "T_GetOut_countryside_CAM" sRespawnCutscene.vAnimPos = <<1968.14, 3816.79, 32.4287>> sRespawnCutscene.vAnimRot = <<0.0000, 0.0000, 29.7938 >> sRespawnCutscene.ePedMotionState = MS_ON_FOOT_IDLE BREAK CASE DWC_TREVOR_beach pDrunkDebugName = "DWC_TREVOR_beach" sRespawnCutscene.pAnimDictName = "SAVEVeniceB@" sRespawnCutscene.pAnimClipName = "T_GetOut_r_veniceB" sRespawnCutscene.pAnimCamName = "T_GetOut_r_veniceB_CAM" sRespawnCutscene.vAnimPos = <<-1148.438, -1512.246, 9.689 >> sRespawnCutscene.vAnimRot = <<0.0000, 0.0000, 36.250 >> sRespawnCutscene.ePedMotionState = MS_ON_FOOT_IDLE BREAK CASE DWC_TREVOR_stripclub pDrunkDebugName = "DWC_TREVOR_stripclub" sRespawnCutscene.pAnimDictName = "SAVECouch@" sRespawnCutscene.pAnimClipName = "T_GetOut_couch" sRespawnCutscene.pAnimCamName = "T_GetOut_couch_CAM" sRespawnCutscene.vAnimPos = << 94.53, -1289.86, 28.27 >> sRespawnCutscene.vAnimRot = <<0.0000, 0.0000, 29.7938 >> sRespawnCutscene.ePedMotionState = MS_ON_FOOT_IDLE BREAK ENDSWITCH IF NOT IS_ENTITY_DEAD(m_rawDetails.ped) SET_ENTITY_COORDS(m_rawDetails.ped, sRespawnCutscene.vAnimPos) ENDIF WAIT(0500) sRespawnCutscene.DialogueTextLabel = "" sRespawnCutscene.fDialoguePhase = -1 #IF IS_DEBUG_BUILD sRespawnCutscene.respawn_widgetId = g_wDrawDebugDrunkInfo #ENDIF RUN_RESPAWN_CUTSCENE(pDrunkDebugName, sRespawnCutscene, "") BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_HANGOVR) //stockmarket #1514495 Drunk_Cleanup() ENDPROC /* // PURPOSE: Check to see if a player is trying to enter a car // // RETURN VALUE: BOOL TRUE if the player tried to enter a vehicle, otherwise FALSE FUNC BOOL Maintain_Player_Trying_To_Enter_Vehicle() // Has the player has tried to enter a vehicle? IF NOT (IS_CONTROL_JUST_PRESSED(PLAYER_CONTROL, INPUT_ENTER)) RETURN FALSE ENDIF // Make sure the player is in control // This is to fix GTA E1 PS3 bug 754 IF NOT (IS_PLAYER_CONTROL_ON(PLAYER_ID())) RETURN FALSE ENDIF // Player has tried to enter a car // Check if there is a car nearby that the player can enter VEHICLE_INDEX closestCar = NULL VECTOR xyzP = GET_ENTITY_COORDS(m_rawDetails.ped) INT searchFlags = (VEHICLE_SEARCH_FLAG_RETURN_RANDOM_VEHICLES | VEHICLE_SEARCH_FLAG_RETURN_MISSION_VEHICLES | VEHICLE_SEARCH_FLAG_RETURN_VEHICLES_WITH_PEDS_ENTERING_OR_EXITING) closestCar = GET_CLOSEST_VEHICLE(xyzP, MAX_DISTANCE_FROM_VEHICLE_m, DUMMY_MODEL_FOR_SCRIPT, searchFlags) IF (closestCar = NULL) RETURN FALSE ENDIF // There is a nearby car // Ensure it is driveable IF NOT (IS_VEHICLE_DRIVEABLE(closestCar)) RETURN FALSE ENDIF // Check if the player is close enough to either the driver's door or the passenger door (to prevent running around the whole car) CONST_FLOAT OFFSET_ON_DRIVERS_SIDE_m -1.0 CONST_FLOAT OFFSET_ON_PASSENGER_SIDE_m 1.0 CONST_FLOAT OFFSET_ON_DRIVERS_SIDE_TAXI_m 0.0 CONST_FLOAT VALID_PLAYER_RANGE_m 2.0 CONST_FLOAT VALID_PLAYER_TAXI_RANGE_m 4.0 FLOAT thisOffset = OFFSET_ON_DRIVERS_SIDE_m FLOAT thisRange = VALID_PLAYER_RANGE_m BOOL onDriverSide = TRUE BOOL isCloseToCar = FALSE BOOL useCentreOfCar = FALSE // Taxi? //KGMTAXI IF (IS_VEHICLE_MODEL(closestCar, TAXI)) //KGMTAXI OR (IS_VEHICLE_MODEL(closestCar, CABBY)) //KGMTAXI OR (IS_VEHICLE_MODEL(closestCar, TAXI2)) //KGMTAXI thisRange = VALID_PLAYER_TAXI_RANGE_m //KGMTAXI thisOffset = OFFSET_ON_DRIVERS_SIDE_TAXI_m //KGMTAXI useCentreOfCar = TRUE //KGMTAXI ENDIF // Player on driver's side or in taxi? VECTOR theOffsetVector = << thisOffset, 0.0, 0.0 >> VECTOR xyzCar = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(closestCar, theOffsetVector) VECTOR theRangeVector = << thisRange, thisRange, thisRange >> IF (IS_ENTITY_AT_COORD(m_rawDetails.ped, xyzCar, theRangeVector, FALSE)) isCloseToCar = TRUE onDriverSide = TRUE ENDIF // Only test passenger side offset if not using the centre of the car for the driver's side offset IF NOT (isCloseToCar) AND NOT (useCentreOfCar) theOffsetVector = << OFFSET_ON_PASSENGER_SIDE_m, 0.0, 0.0 >> xyzCar = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(closestCar, theOffsetVector) theRangeVector = << VALID_PLAYER_RANGE_m, VALID_PLAYER_RANGE_m, VALID_PLAYER_RANGE_m >> IF (IS_ENTITY_AT_COORD(m_rawDetails.ped, xyzCar, theRangeVector, FALSE)) isCloseToCar = TRUE onDriverSide = FALSE ENDIF ENDIF IF NOT (isCloseToCar) RETURN FALSE ENDIF // Close enough to the car to jack // Stop Natural Motion and get player into car Stop_Ragdolling() // SET_NEXT_DESIRED_MOVE_BLEND_RATIO(PEDMOVE_WALK) // Check if a bike MODEL_NAMES thisModel = GET_ENTITY_MODEL(closestCar) BOOL isBike = IS_THIS_MODEL_A_BIKE(thisModel) IF (onDriverSide) OR (isBike) CPRINTLN(DEBUG_DRUNK, " enter car as DRIVER") TASK_ENTER_VEHICLE(m_rawDetails.ped, closestCar, DEFAULT_TIME_BEFORE_WARP, VS_DRIVER) ELSE CPRINTLN(DEBUG_DRUNK, " enter car as FRONT_RIGHT") TASK_ENTER_VEHICLE(m_rawDetails.ped, closestCar, DEFAULT_TIME_BEFORE_WARP, VS_FRONT_RIGHT) ENDIF m_rawDetails.vehicle = closestCar m_status.shortTerm = DSST_ENTERING_VEHICLE RETURN TRUE ENDFUNC */ // PURPOSE: Check to see if a player is driving a car // // RETURN VALUE: BOOL TRUE if the player is driving a vehicle, otherwise FALSE FUNC BOOL Maintain_Player_Is_Driving_Vehicle() // IF NOT (IS_PED_SITTING_IN_ANY_VEHICLE(m_rawDetails.ped)) RETURN FALSE ENDIF VEHICLE_INDEX drivenCar = NULL drivenCar = GET_VEHICLE_PED_IS_IN(m_rawDetails.ped) // Ensure it is driveable IF NOT (IS_VEHICLE_DRIVEABLE(drivenCar)) RETURN FALSE ENDIF IF NOT (GET_PED_IN_VEHICLE_SEAT(drivenCar, VS_DRIVER) = m_rawDetails.ped) RETURN FALSE ENDIF m_rawDetails.vehicle = drivenCar m_status.shortTerm = DSST_ENTERING_VEHICLE RETURN TRUE ENDFUNC // PURPOSE: Maintain the components associated with being drunk // A ped should always have an Immediate task. If Idle then the Overall task is used to // generate a new Immediate task. PROC Maintain_Being_Drunk() // Ensure the ped is still alive IF (IS_ENTITY_DEAD(m_rawDetails.ped)) Drunk_Cleanup() ENDIF // If this is the player, ensure the player is playing IF (m_thisIsPlayer) IF NOT (IS_PLAYER_PLAYING(PLAYER_ID())) Drunk_Cleanup() ENDIF ENDIF // Need to see if a new short-term status should interrupt any current task - eg: Get Up From Floor Check_For_Enforced_Short_Term_Status_Changes() // Every ped should have an immediate status. This flag will be used to highlight problems. BOOL foundShortTermStatus = TRUE // Deal with the Immediate task SWITCH (m_status.shortTerm) CASE DSST_SWITCH_ON_RAGDOLL Maintain_ShortTerm_Status_Switch_On_Ragdoll() EXIT CASE DSST_WALK Maintain_ShortTerm_Status_Walk() EXIT CASE DSST_ENTER_VEHICLE Maintain_ShortTerm_Status_Enter_Vehicle() EXIT CASE DSST_ENTERING_VEHICLE Maintain_ShortTerm_Status_Entering_Vehicle() EXIT CASE DSST_WARP_INTO_TAXI Maintain_ShortTerm_Status_Warp_Into_Taxi() EXIT CASE DSST_SHUFFLE_CARSEATS Maintain_ShortTerm_Status_Shuffle_Carseats() EXIT CASE DSST_IN_VEHICLE Maintain_ShortTerm_Status_In_Vehicle() Maintain_Steering_Bias() Maintain_Wanted_Level() EXIT CASE DSST_LEAVE_VEHICLE Maintain_ShortTerm_Status_Leave_Vehicle() EXIT // When Idle, look to the long-term objective for something to do CASE DS_IDLE BREAK DEFAULT foundShortTermStatus = FALSE BREAK ENDSWITCH // Error Checking IF NOT (foundShortTermStatus) SCRIPT_ASSERT("drunk: Maintain_Being_Drunk(): Found a ped with an illegal Short-Term Status") EXIT ENDIF IF NOT (m_status.shortTerm = DS_IDLE) SCRIPT_ASSERT("drunk: Maintain_Being_Drunk(): Long-term status for a ped is being checked but their Short-term Status is not Idle") EXIT ENDIF // Deal with the long-term objectives - a ped should only reach here if the long-term status is Idle SWITCH (m_status.longTerm) // Player Controlled drunk ped's need to do a few checks CASE DSLT_PLAYER_CONTROLLED IF NOT /*(Maintain_Player_Trying_To_Enter_Vehicle()) AND NOT*/ (Maintain_Player_Is_Driving_Vehicle()) Maintain_Ragdolling_For_Required_Duration() Maintain_Steering_Bias() ENDIF BREAK CASE DSLT_GET_INTO_VEHICLE Maintain_LongTerm_Status_Get_Into_Vehicle() BREAK // Peds with no long-term objective CASE DS_IDLE Maintain_LongTerm_Status_Idle() BREAK // Peds with no long-term objective CASE DSLT_HANGOVER_WAKEUP Maintain_LongTerm_Status_Hangover_Wakeup() BREAK DEFAULT SCRIPT_ASSERT("drunk: Maintain_Being_Drunk(): Found a ped with an illegal long-term Status") BREAK ENDSWITCH ENDPROC SCRIPT (g_sDrunkRequests scriptArgs) // This script needs to cleanup only when the game moves from SP to MP IF (HAS_FORCE_CLEANUP_OCCURRED(FORCE_CLEANUP_FLAG_SP_TO_MP)) CPRINTLN(DEBUG_DRUNK, "...drunk.sc has been forced to cleanup (SP to MP)") Drunk_Cleanup() ENDIF // Store details passed as args m_rawDetails = scriptArgs Store_My_UniqueID() Store_Player_Or_AI() // Still need to tell controller on first frame that this ped is still drunk Post_Drunk_Notice(m_myUniqueID, UNIQUE_ID_CONTROL_SCRIPT, DNID_STILL_DRUNK) #IF IS_DEBUG_BUILD CPRINTLN(DEBUG_DRUNK, "--------------------------------------------------------------") IF (m_myUniqueID = NO_UNIQUE_DRUNK_PED_ID) IF (m_leaderUniqueID = NO_UNIQUE_DRUNK_PED_ID) CPRINTLN(DEBUG_DRUNK, "Started new drunk ped with unique ID: currently unknown and with a leader with unique ID: currently unknown") ELSE CPRINTLN(DEBUG_DRUNK, "Started new drunk ped with unique ID: currently unknown and with a leader with unique ID: ", m_leaderUniqueID) ENDIF ELSE IF (m_leaderUniqueID = NO_UNIQUE_DRUNK_PED_ID) CPRINTLN(DEBUG_DRUNK, "Started new drunk ped with unique ID: ", m_myUniqueID, " and with a leader with unique ID: currently unknown") ELSE CPRINTLN(DEBUG_DRUNK, "Started new drunk ped with unique ID: ", m_myUniqueID, " and with a leader with unique ID: ", m_leaderUniqueID) ENDIF ENDIF CPRINTLN(DEBUG_DRUNK, "--------------------------------------------------------------") #ENDIF // Use TimerA as the control timer SETTIMERA(0) // Store length of time that the various components of being drunk should last Store_Drunk_Timings() // Store the initial statuses Store_Initial_Status() WHILE (TRUE) WAIT(0) // Clear out any previously sent notices by me Clear_All_Notices_From_This_Unique_Drunk_Ped_ID(m_myUniqueID) // Does the drunk effects need to continue? Maintain_Drunk_Timers() // Maintain the BAWSAQ modifiers for drunken events Maintain_Drunk_Crime_Modifiers() // Maintain_Drunk_Hangover_Modifiers() // Read and act on any notices directed at this drunk ped Read_All_Drunk_Notices_Directed_At_Me() // Post a notice each frame telling the controller that this ped is still drunk Post_Drunk_Notice(m_myUniqueID, UNIQUE_ID_CONTROL_SCRIPT, DNID_STILL_DRUNK) // Grab any data that may not have been available when the script launched Store_My_UniqueID() // Maintain the components of being drunk Maintain_Being_Drunk() // Ensure multiplayer "on call" missions not triggered while drunk IF NETWORK_IS_GAME_IN_PROGRESS() AND NOT NETWORK_IS_ACTIVITY_SESSION() AND NOT IS_TRANSITION_SESSION_RANKED_QUICKMATCH_READY_TO_LAUNCH() SET_TRANSITION_SESSIONS_CLEAN_UP_ON_CALL_NOW_IF_NEEDED() ENDIF #IF IS_DEBUG_BUILD Update_Drunk_Debug_Variables() // Draw useful info (state, time etc) on this drunk ped Draw_Debug_Drink_Info() IF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_K) EXPLODE_PED_HEAD(m_rawDetails.ped) ENDIF #ENDIF ENDWHILE ENDSCRIPT