2883 lines
93 KiB
Python
Executable File
2883 lines
93 KiB
Python
Executable File
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, "<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, "<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, "<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, "<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, "<DRUNK> don't play transition: playing a synch scene")
|
|
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF IS_PED_SHOOTING(thePed)
|
|
CPRINTLN(DEBUG_DRUNK, "<DRUNK> don't play transition: ped is shooting")
|
|
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF IS_ENTITY_IN_AIR(thePed)
|
|
CPRINTLN(DEBUG_DRUNK, "<DRUNK> don't play transition: ped is in air")
|
|
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF IS_PED_RAGDOLL(thePed)
|
|
CPRINTLN(DEBUG_DRUNK, "<DRUNK> don't play transition: ped is ragdoll")
|
|
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF IS_PED_CLIMBING(thePed)
|
|
CPRINTLN(DEBUG_DRUNK, "<DRUNK> don't play transition: ped is climbing")
|
|
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF g_bBrowserVisible
|
|
CPRINTLN(DEBUG_DRUNK, "<DRUNK> don't play transition: browser visible")
|
|
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF IS_CUSTOM_MENU_ON_SCREEN()
|
|
CPRINTLN(DEBUG_DRUNK, "<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, "<DRUNK> don't play transition: not free of ambient tasks")
|
|
|
|
RETURN FALSE
|
|
ENDIF
|
|
IF NOT IS_PLAYER_CONTROL_ON(PLAYER_ID())
|
|
CPRINTLN(DEBUG_DRUNK, "<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, "<DRUNK> don't play transition: player is aiming")
|
|
|
|
RETURN FALSE
|
|
ENDIF
|
|
IF IS_PLAYER_BROWSING_ITEMS_IN_ANY_SHOP()
|
|
CPRINTLN(DEBUG_DRUNK, "<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, "<DRUNK> don't play transition: velocity too high")
|
|
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
CPRINTLN(DEBUG_DRUNK, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<DRUNK> status now In Vehicle")
|
|
ENDIF
|
|
Change_ShortTerm_Status_To_In_Vehicle()
|
|
EXIT
|
|
ENDIF
|
|
|
|
IF NOT (m_thisIsPlayer)
|
|
CPRINTLN(DEBUG_DRUNK, "<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, "<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, "<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, "<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, "<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, "<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, "<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, "<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 - <<NEARBY_POLICE_CAR_RANGE_m, NEARBY_POLICE_CAR_RANGE_m, NEARBY_POLICE_CAR_HEIGHT_m>>
|
|
VECTOR xyzMax = xyzPlayer + <<NEARBY_POLICE_CAR_RANGE_m, NEARBY_POLICE_CAR_RANGE_m, NEARBY_POLICE_CAR_HEIGHT_m>>
|
|
|
|
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, "<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, "<DRUNK> enter car as DRIVER")
|
|
TASK_ENTER_VEHICLE(m_rawDetails.ped, closestCar, DEFAULT_TIME_BEFORE_WARP, VS_DRIVER)
|
|
ELSE
|
|
CPRINTLN(DEBUG_DRUNK, "<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
|
|
|