Files
2025-09-29 00:52:08 +02:00

1121 lines
37 KiB
Python
Executable File

//////////////////////////////////////////////////////////////////////////////////////////
// //
// SCRIPT NAME : savegame_bed.sc //
// AUTHOR : Kenneth Ross //
// DESCRIPTION : Enables the player to save their current game progress. //
// This will be attached to various world points and only work //
// when player character and savehouse conditions are met. //
// //
//////////////////////////////////////////////////////////////////////////////////////////
//Compile out Title Update changes to header functions.
//Must be before includes.
//CONST_INT USE_TU_CHANGES 0 // Removed by Kenneth R.
USING "rage_builtins.sch"
USING "globals.sch"
USING "brains.sch"
USING "script_player.sch"
USING "savegame_private.sch"
USING "savegame_public.sch"
USING "savegame_bed_data.sch"
USING "respawn_location_private.sch"
USING "cellphone_public.sch"
USING "selector_public.sch"
USING "cutscene_public.sch"
USING "context_control_public.sch"
USING "player_scene_private.sch"
ENUM SCRIPT_STAGE_ENUM
SCRIPT_STAGE_INITIALISE = 0,
SCRIPT_STAGE_WAIT_FOR_TRIGGER,
SCRIPT_STAGE_SAVEGAME,
SCRIPT_STAGE_IDLE,
SCRIPT_STAGE_CLEANUP
ENDENUM
SCRIPT_STAGE_ENUM eScriptStage = SCRIPT_STAGE_INITIALISE
ENUM SAVE_STAGE_ENUM
SAVE_STAGE_INTRO = 0,
SAVE_STAGE_PERFORM_SAVE,
SAVE_STAGE_OUTRO,
SAVE_STAGE_CLEANUP
ENDENUM
SAVE_STAGE_ENUM eSaveStage = SAVE_STAGE_INTRO
INT iStage = 0
INT iSceneID
VECTOR vInCoords
BOOL bSaveActive
BOOL bLeaveArea
INT iGarageAreaChecksToUse
BOOL bDoGarageStraightCut
//INT iWardrobeHintTimer
//BOOL bDisplayWardrobeHint
BOOL bAnimDictLoaded, bAudioBankLoaded
TEXT_LABEL_15 sHelpTrig = "SAVE_TRIG"
TEXT_LABEL_23 sAudioBank = "SCRIPT\\Alarm_Clocks"
STRING sDefaultAlarmSound = "Alarm_Clocks_Bell"
CAMERA_INDEX camID
CAMERA_INDEX camID_Garage
BOOL bPickupsCreated
SAVEGAME_BED_DATA_STRUCT sData
TEXT_LABEL_63 tlCamAnim
BOOL bBlockGarageCamUntilExit
INT iSavebedGetUpStage
MODEL_NAMES eStartPedModel
INT iContextID = NEW_CONTEXT_INTENTION
enumCharacterList eCurrentPlayerPed
INT iSavegameBedRetryAttempt = 0
#IF IS_DEBUG_BUILD
BOOL d_bOverrideAlarm
TEXT_WIDGET_ID d_textID
BOOL d_bTestPickup, d_bDoAutoSave
PICKUP_INDEX d_pickupID
VECTOR d_pickupCoords, d_pickupRot
PROC SETUP_SAVEGAME_BED_DEBUG_WIDGETS()
START_WIDGET_GROUP("Savegame Bed Debug")
ADD_WIDGET_BOOL("Make autosave request", d_bDoAutoSave)
ADD_WIDGET_INT_READ_ONLY("iSavebedGetUpStage", iSavebedGetUpStage)
ADD_WIDGET_BOOL("Create test pickup", d_bTestPickup)
ADD_WIDGET_VECTOR_SLIDER("Pickup coords", d_pickupCoords, -6000, 6000, 0.005)
ADD_WIDGET_VECTOR_SLIDER("Pickup rot", d_pickupRot, 0.0, 360, 1.0)
ADD_WIDGET_BOOL("Override alarm sound", d_bOverrideAlarm)
d_textID = ADD_TEXT_WIDGET("Sounds Name")
SET_CONTENTS_OF_TEXT_WIDGET(d_textID, sDefaultAlarmSound)
STOP_WIDGET_GROUP()
ENDPROC
PROC MAINTAIN_SAVEGAME_BED_DEBUG_WIDGETS()
IF d_bDoAutoSave
MAKE_AUTOSAVE_REQUEST()
d_bDoAutoSave = FALSE
ENDIF
IF d_bTestPickup
IF DOES_PICKUP_EXIST(d_pickupID)
REMOVE_PICKUP(d_pickupID)
ENDIF
INT iPlacementFlags = 0
SET_BIT(iPlacementFlags, enum_to_int(PLACEMENT_FLAG_SNAP_TO_GROUND))
SET_BIT(iPlacementFlags, enum_to_int(PLACEMENT_FLAG_UPRIGHT))
SET_BIT(iPlacementFlags, enum_to_int(PLACEMENT_FLAG_FIXED))
d_pickupID = CREATE_PICKUP_ROTATE(PICKUP_HEALTH_STANDARD, d_pickupCoords, d_pickupRot, iPlacementFlags)
ELSE
IF DOES_PICKUP_EXIST(d_pickupID)
REMOVE_PICKUP(d_pickupID)
ENDIF
ENDIF
ENDPROC
#ENDIF
/// PURPOSE:
/// Calls the common SAFE_TO_SAVE_GAME, and also does some bed save specific checks
/// RETURNS:
/// TRUE if it is currently safe to save. FALSE otherwise
FUNC BOOL SAFE_TO_SAVE_GAME_BED()
//B* 1866394: Disable check if the context controller isn't running yet
IF GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("context_controller")) < 1
CPRINTLN(debug_ambient, "Context_controller thread not running, can't register bed context key")
RETURN FALSE //Can't check context button unless the script is running
ENDIF
// Locate checks
IF IS_ANY_PED_SHOOTING_IN_AREA(sData.vBedCoords-<<10.0, 10.0, 10.0>>, sData.vBedCoords+<<10.0, 10.0, 10.0>>, FALSE)
RETURN FALSE
ENDIF
// safehouse available, phone away, not in vehicle
IF NOT Is_Savehouse_Respawn_Available(sData.eSavehouse)
OR IS_PHONE_ONSCREEN()
OR IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
#IF IS_DEBUG_BUILD
IF IS_CONTROL_JUST_PRESSED(FRONTEND_CONTROL,INPUT_CONTEXT)
OR IS_DISABLED_CONTROL_JUST_PRESSED(FRONTEND_CONTROL,INPUT_CONTEXT)
IF (NOT Is_Savehouse_Respawn_Available(sData.eSavehouse))
PRINTLN("SAFE_TO_SAVE_GAME_BED() = FALSE - savehouse not available")
ELIF (IS_PHONE_ONSCREEN())
PRINTLN("SAFE_TO_SAVE_GAME_BED() = FALSE - phone on screen")
ELIF (IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()))
PRINTLN("SAFE_TO_SAVE_GAME_BED() = FALSE - player in vehicle")
ELSE
PRINTLN("SAFE_TO_SAVE_GAME_BED() = FALSE - some other reason?")
ENDIF
ENDIF
#ENDIF
RETURN FALSE
ENDIF
//If the player is in a trigger scene for a mission with a lead-in
IF g_eMissionSceneToCleanup != SP_MISSION_NONE
IF IS_BIT_SET(g_sMissionStaticData[g_eMissionSceneToCleanup].settingsBitset, MF_INDEX_NO_SAVE_ON_LEAD_IN)
PRINTLN("SAFE_TO_SAVE_GAME_BED() = FALSE - Player is in a trigger scene for a mission with a lead-in.")
RETURN FALSE
ENDIF
ENDIF
// If the cops are too close.
IF (GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) > 0 AND IS_COP_PED_IN_AREA_3D(sData.vBedCoords-<<10.0, 10.0, 10.0>>, sData.vBedCoords+<<10.0, 10.0, 10.0>>))
OR (GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) > 3)
#IF IS_DEBUG_BUILD
IF IS_CONTROL_JUST_PRESSED(FRONTEND_CONTROL,INPUT_CONTEXT)
OR IS_DISABLED_CONTROL_JUST_PRESSED(FRONTEND_CONTROL,INPUT_CONTEXT)
PRINTLN("SAFE_TO_SAVE_GAME_BED() = FALSE - cops are too close")
ENDIF
#ENDIF
RETURN FALSE
ENDIF
// no specifc problems found, do the general checks
RETURN SAFE_TO_SAVE_GAME()
ENDFUNC
/// PURPOSE: Determines if the savegame bed is allowed to run
FUNC BOOL IS_SAVEGAME_BED_SAFE_TO_RUN()
// Debug flag not set
#IF IS_DEBUG_BUILD
IF NOT g_savedGlobals.sFlow.isGameflowActive
AND NOT g_bSavegameBedAvailableInDebug
RETURN FALSE
ENDIF
#ENDIF
// No issues found so assume it is safe to run
RETURN TRUE
ENDFUNC
/// PURPOSE: Loads any assets required in the save process
FUNC BOOL LOAD_ASSETS_FOR_SAVE_PROCESS()
// Anims
REQUEST_ANIM_DICT(sData.tlAnimDict)
IF NOT HAS_ANIM_DICT_LOADED(sData.tlAnimDict)
RETURN FALSE
ENDIF
bAnimDictLoaded = TRUE
IF NOT REQUEST_AMBIENT_AUDIO_BANK(sAudioBank)
RETURN FALSE
ENDIF
bAudioBankLoaded = TRUE
RETURN TRUE
ENDFUNC
/// PURPOSE: Unloads any assets required in the browse process
PROC UNLOAD_ASSETS_FOR_SAVE_PROCESS()
IF bAnimDictLoaded
REMOVE_ANIM_DICT(sData.tlAnimDict)
bAnimDictLoaded = FALSE
ENDIF
IF bAudioBankLoaded
RELEASE_AMBIENT_AUDIO_BANK()
bAudioBankLoaded = FALSE
ENDIF
ENDPROC
PROC ADD_HEALTH_PICKUPS()
IF bPickupsCreated
OR NOT sData.bDataSet
OR IS_PED_INJURED(PLAYER_PED_ID())
OR GET_DISTANCE_BETWEEN_COORDS(sData.vBedCoords, GET_ENTITY_COORDS(PLAYER_PED_ID())) > 20.0
EXIT
ENDIF
INT iPickup
// Create pickups once
IF NOT bPickupsCreated
IF IS_SAVEHOUSE_INTERIOR_READY(sData.eSavehouse)
PRINTLN("savegame_bed - Creating pickups using index ", sData.iPickupIndex)
INT iPlacementFlags
iPlacementFlags = 0
SET_BIT(iPlacementFlags, enum_to_int(PLACEMENT_FLAG_SNAP_TO_GROUND))
SET_BIT(iPlacementFlags, enum_to_int(PLACEMENT_FLAG_UPRIGHT))
SET_BIT(iPlacementFlags, enum_to_int(PLACEMENT_FLAG_FIXED))
TEXT_LABEL_31 tlRoomName
REPEAT NUM_OF_SAVEHOUSE_HEALTH_PICKUPS iPickup
IF NOT ARE_VECTORS_EQUAL(sData.vPickupCoords[iPickup], <<0,0,0>>)
g_piSavehouseHealthPickups[sData.iPickupIndex][iPickup] = CREATE_PICKUP_ROTATE(PICKUP_HEALTH_STANDARD, sData.vPickupCoords[iPickup], sData.vPickupRot[iPickup], iPlacementFlags)
PRINTLN("savegame_bed - creating health pickup at ", sData.vPickupCoords[iPickup], " using index ", sData.iPickupIndex)
IF GET_SAVEGAME_ROOM_NAME_FOR_PICKUP(sData.eSavehouse, iPickup, tlRoomName)
PRINTLN("savegame_bed - adding health pickup to room ", tlRoomName)
ADD_PICKUP_TO_INTERIOR_ROOM_BY_NAME(g_piSavehouseHealthPickups[sData.iPickupIndex][iPickup], tlRoomName)
ENDIF
ENDIF
ENDREPEAT
bPickupsCreated = TRUE
ENDIF
ENDIF
ENDPROC
PROC REMOVE_HEALTH_PICKUPS(BOOL bForce = FALSE)
IF NOT sData.bDataSet
EXIT
ENDIF
INT iPickup
// Remove any created pickups
IF bPickupsCreated OR bForce
PRINTLN("savegame_bed - Removing pickups using index ", sData.iPickupIndex)
REPEAT NUM_OF_SAVEHOUSE_HEALTH_PICKUPS iPickup
IF DOES_PICKUP_EXIST(g_piSavehouseHealthPickups[sData.iPickupIndex][iPickup])
REMOVE_PICKUP(g_piSavehouseHealthPickups[sData.iPickupIndex][iPickup])
PRINTLN("savegame_bed - removing health pickup at ", sData.vPickupCoords[iPickup], " using index ", sData.iPickupIndex)
ENDIF
ENDREPEAT
bPickupsCreated = FALSE
ENDIF
ENDPROC
/// PURPOSE: Creates health pickups around the savehouses
PROC MANAGE_HEALTH_PICKUPS()
IF eScriptStage = SCRIPT_STAGE_INITIALISE
OR eScriptStage = SCRIPT_STAGE_IDLE
OR NOT sData.bDataSet
OR eCurrentPlayerPed != sData.eCharacter
EXIT
ENDIF
IF IS_SCREEN_FADED_OUT()
REMOVE_HEALTH_PICKUPS()
ELSE
ADD_HEALTH_PICKUPS()
ENDIF
ENDPROC
/// PURPOSE: Cleans up any assets that were created
PROC CLEANUP_SCRIPT()
IF iContextID != NEW_CONTEXT_INTENTION
RELEASE_CONTEXT_INTENTION(iContextID)
ENDIF
UNLOAD_ASSETS_FOR_SAVE_PROCESS()
IF bSaveActive
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
CLEAR_PED_TASKS(PLAYER_PED_ID())
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
SET_ENTITY_PROOFS(PLAYER_PED_ID(), FALSE, FALSE, FALSE, FALSE, FALSE)
FREEZE_ENTITY_POSITION(PLAYER_PED_ID(), FALSE)
ENDIF
IF DOES_CAM_EXIST(camID)
SET_CAM_ACTIVE(camID, FALSE)
DESTROY_CAM(camID)
RENDER_SCRIPT_CAMS(FALSE, FALSE)
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0)
ENDIF
ENDIF
/*IF IS_THIS_HELP_MESSAGE_BEING_DISPLAYED(sHelpTrig)
CLEAR_HELP()
ENDIF*/
#IF IS_DEBUG_BUILD
PRINTNL()
PRINTSTRING("SAVEGAME BED SCRIPT TERMINATING")
PRINTNL()
#ENDIF
// Remove them so we do not create duplicates when the script starts up again
REMOVE_HEALTH_PICKUPS(TRUE)
TERMINATE_THIS_THREAD()
ENDPROC
/// PURPOSE: Resets the controller if the character changes
PROC CHECK_CONTROLLER_RESET()
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
IF eScriptStage = SCRIPT_STAGE_WAIT_FOR_TRIGGER
OR eScriptStage = SCRIPT_STAGE_IDLE
IF eStartPedModel != GET_ENTITY_MODEL(PLAYER_PED_ID())
PRINTLN("savegame_bed - resetting script for character change")
iStage = 0
eScriptStage = SCRIPT_STAGE_INITIALISE
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE: Loads the required shop assets and sets up items to browse
PROC DO_INITIALISE()
SWITCH iStage
CASE 0
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
eStartPedModel = GET_ENTITY_MODEL(PLAYER_PED_ID())
// Setup the savegame bed data on the coords that were passed into the script
IF GET_SAVEGAME_BED_DATA(sData, vInCoords)
GET_SAVEGAME_BED_ANIM_DATA(sData)
REMOVE_HEALTH_PICKUPS(TRUE)
iSavebedGetUpStage = 0
iGarageAreaChecksToUse = 0
bDoGarageStraightCut = FALSE
iStage++
ELSE
// Problem finding suitable savegame bed so wait for character change or cleanup
eScriptStage = SCRIPT_STAGE_IDLE
ENDIF
ENDIF
BREAK
CASE 1
// Make sure the script is allowed to run before we initialise
IF IS_SAVEGAME_BED_SAFE_TO_RUN()
eScriptStage = SCRIPT_STAGE_WAIT_FOR_TRIGGER
ENDIF
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE: Clears wardrobe hint help when timer is up
PROC PROCESS_SAVEBED_GETUP()
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
INT iDrawSceneRot
SWITCH iSavebedGetUpStage
CASE 0
IF NOT IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_STORY)
IF NOT IS_STRING_NULL_OR_EMPTY(sData.tlSleepLoop)
AND NOT IS_STRING_NULL_OR_EMPTY(sData.tlGetOut)
IF IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), sData.tlAnimDict, sData.tlSleepLoop)
SETTIMERA(0)
iSavebedGetUpStage++
ENDIF
ENDIF
ENDIF
BREAK
CASE 1
LOAD_ASSETS_FOR_SAVE_PROCESS()
IF IsPlayerMovingLeftStick(iDrawSceneRot)
OR TIMERA() > 30000
iSavebedGetUpStage++
ENDIF
BREAK
CASE 2
IF LOAD_ASSETS_FOR_SAVE_PROCESS()
iSceneID = CREATE_SYNCHRONIZED_SCENE(sData.vSceneCoords, sData.vSceneRot)
SET_SYNCHRONIZED_SCENE_LOOPED(iSceneID, FALSE)
TASK_SYNCHRONIZED_SCENE(PLAYER_PED_ID(), iSceneID, sData.tlAnimDict, sData.tlGetOut, NORMAL_BLEND_IN, NORMAL_BLEND_OUT)
iSavebedGetUpStage++
ENDIF
BREAK
CASE 3
IF IS_SYNCHRONIZED_SCENE_RUNNING(iSceneID)
PRINTLN("Get up phase = ", GET_SYNCHRONIZED_SCENE_PHASE(iSceneID))
ENDIF
// Wait for the 'get out' phase to complete
IF NOT IS_SYNCHRONIZED_SCENE_RUNNING(iSceneID)
OR GET_SYNCHRONIZED_SCENE_PHASE(iSceneID) >= 1.0
OR (GET_SYNCHRONIZED_SCENE_PHASE(iSceneID) >= 0.78 AND IsPlayerMovingLeftStick(iDrawSceneRot))
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
SET_ENTITY_PROOFS(PLAYER_PED_ID(), FALSE, FALSE, FALSE, FALSE, FALSE)
CLEAR_PED_TASKS(PLAYER_PED_ID())
iSavebedGetUpStage = 0
UNLOAD_ASSETS_FOR_SAVE_PROCESS()
ENDIF
BREAK
ENDSWITCH
ENDIF
ENDPROC
PROC PROCESS_SAVE_GARAGE()
// Switch to the garage cam when close
IF sData.bUseGarageCamera
IF NOT bBlockGarageCamUntilExit
IF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), sData.vGarageAngledArea1[iGarageAreaChecksToUse], sData.vGarageAngledArea2[iGarageAreaChecksToUse], sData.fGarageAngledAreaWidth[iGarageAreaChecksToUse])
IF (GET_CAM_VIEW_MODE_FOR_CONTEXT(GET_CAM_ACTIVE_VIEW_MODE_CONTEXT()) = CAM_VIEW_MODE_FIRST_PERSON)
bBlockGarageCamUntilExit = TRUE
ENDIF
ENDIF
ELSE
IF NOT IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), sData.vGarageAngledArea1[iGarageAreaChecksToUse], sData.vGarageAngledArea2[iGarageAreaChecksToUse], sData.fGarageAngledAreaWidth[iGarageAreaChecksToUse])
IF (GET_CAM_VIEW_MODE_FOR_CONTEXT(GET_CAM_ACTIVE_VIEW_MODE_CONTEXT()) != CAM_VIEW_MODE_FIRST_PERSON)
bBlockGarageCamUntilExit = FALSE
ENDIF
ENDIF
ENDIF
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
AND IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
AND IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), sData.vGarageAngledArea1[iGarageAreaChecksToUse], sData.vGarageAngledArea2[iGarageAreaChecksToUse], sData.fGarageAngledAreaWidth[iGarageAreaChecksToUse])
AND NOT bBlockGarageCamUntilExit
IF NOT DOES_CAM_EXIST(camID_Garage)
camID_Garage = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", FALSE)
SET_CAM_ACTIVE(camID_Garage, TRUE)
IF bDoGarageStraightCut
SET_CAM_PARAMS(camID_Garage, sData.vGarageCamCoord, sData.vGarageCarmRot, sData.fGarageCamFOV, 0)
ELSE
SET_CAM_PARAMS(camID_Garage, GET_FINAL_RENDERED_CAM_COORD(), GET_FINAL_RENDERED_CAM_ROT(), GET_FINAL_RENDERED_CAM_FOV(), 0)
SET_CAM_PARAMS(camID_Garage, sData.vGarageCamCoord, sData.vGarageCarmRot, sData.fGarageCamFOV, 1200)
ENDIF
RENDER_SCRIPT_CAMS(TRUE, FALSE)
ENDIF
IF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), sData.vGarageAngledArea1[1], sData.vGarageAngledArea2[1], sData.fGarageAngledAreaWidth[1])
iGarageAreaChecksToUse = 1
ENDIF
ELSE
bDoGarageStraightCut = FALSE
IF DOES_CAM_EXIST(camID_Garage)
DESTROY_CAM(camID_Garage)
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
AND IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
AND (GET_CAM_VIEW_MODE_FOR_CONTEXT(GET_CAM_ACTIVE_VIEW_MODE_CONTEXT()) != CAM_VIEW_MODE_FIRST_PERSON)
STOP_RENDERING_SCRIPT_CAMS_USING_CATCH_UP()
ELSE
RENDER_SCRIPT_CAMS(FALSE, FALSE)
ENDIF
ENDIF
IF NOT IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), sData.vGarageAngledArea1[0], sData.vGarageAngledArea2[0], sData.fGarageAngledAreaWidth[0])
iGarageAreaChecksToUse = 0
ELSE
bDoGarageStraightCut = TRUE
ENDIF
ENDIF
IF Is_Savehouse_Respawn_Available(sData.eSavehouse)
AND eCurrentPlayerPed = sData.eCharacter
AND NOT IS_PED_INJURED(PLAYER_PED_ID())
AND IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), sData.vGarageDoorAngledArea1[0], sData.vGarageDoorAngledArea2[0], sData.fGarageDoorAngledAreaWidth[0])
SET_DOOR_STATE(sData.eGarageDoor, DOORSTATE_FORCE_UNLOCKED_THIS_FRAME)
ELIF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), sData.vGarageDoorAngledArea1[1], sData.vGarageDoorAngledArea2[1], sData.fGarageDoorAngledAreaWidth[1])
SET_DOOR_STATE(sData.eGarageDoor, DOORSTATE_FORCE_UNLOCKED_THIS_FRAME)
ELSE
SET_DOOR_STATE(sData.eGarageDoor, DOORSTATE_LOCKED)
ENDIF
ENDIF
ENDPROC
/// PURPOSE: Checks for the player entering the savegame bed locate
PROC CHECK_SAVEBED_TRIGGER()
BOOL bPrintHelp = FALSE
BOOL bPlayerInLocate = FALSE
BOOL bPlayerFacingBed = TRUE
// Only check for activation when we are in range
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
AND NOT IS_CUTSCENE_PLAYING()
AND GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), sData.vBedCoords) <= 5.0
AND iSavebedGetUpStage = 0
AND eCurrentPlayerPed = sData.eCharacter
LOAD_ASSETS_FOR_SAVE_PROCESS()
bPlayerInLocate = (IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), sData.vAngledAreaCoords[0], sData.vAngledAreaCoords[1], sData.fAngledAreaWidth))
IF bPlayerInLocate
IF NOT IS_PLAYER_CONTROL_ON(PLAYER_ID())
bLeaveArea = TRUE
ENDIF
bPlayerFacingBed = TRUE
IF (GET_CAM_VIEW_MODE_FOR_CONTEXT(GET_CAM_ACTIVE_VIEW_MODE_CONTEXT()) = CAM_VIEW_MODE_FIRST_PERSON)
CONST_FLOAT fCONST_MAX_HEADING 90.0
VECTOR vPlayerCoords = GET_ENTITY_COORDS(PLAYER_PED_ID())
FLOAT fPlayerHeading = GET_ENTITY_HEADING(PLAYER_PED_ID())
FLOAT fPlayerBedHeading = GET_HEADING_FROM_VECTOR_2D(sData.vBedCoords.x - vPlayerCoords.x, sData.vBedCoords.y - vPlayerCoords.y)
FLOAT fHeadingDiff = (fPlayerBedHeading - fPlayerHeading)
IF fHeadingDiff > 180
fHeadingDiff -= 180
ENDIF
IF fHeadingDiff < -180
fHeadingDiff += 180
ENDIF
fHeadingDiff = ABSF(fHeadingDiff)
IF fHeadingDiff > fCONST_MAX_HEADING
CDEBUG1LN(DEBUG_AMBIENT, "[CHECK_SAVEBED_TRIGGER] Not facing bed - fHeadingDiff[", fHeadingDiff, ":", fPlayerHeading, " - ", fPlayerBedHeading, "] > fCONST_MAX_HEADING[", ROUND(fCONST_MAX_HEADING), "]")
bPlayerFacingBed = FALSE
ELSE
CDEBUG1LN(DEBUG_AMBIENT, "[CHECK_SAVEBED_TRIGGER] Facing bed - fHeadingDiff[", fHeadingDiff, ":", fPlayerHeading, " - ", fPlayerBedHeading, "] <= fCONST_MAX_HEADING[", ROUND(fCONST_MAX_HEADING), "]")
ENDIF
ENDIF
ELSE
bLeaveArea = FALSE
ENDIF
IF SAFE_TO_SAVE_GAME_BED()
IF bPlayerInLocate AND NOT bLeaveArea AND bPlayerFacingBed
IF NOT bLeaveArea
/*bPrintHelp = IS_THIS_HELP_MESSAGE_BEING_DISPLAYED(sHelpTrig)
IF NOT bPrintHelp
IF NOT IS_HELP_MESSAGE_BEING_DISPLAYED()
PRINT_HELP_FOREVER(sHelpTrig)
bPrintHelp = TRUE
ENDIF
ENDIF
IF IS_THIS_HELP_MESSAGE_BEING_DISPLAYED(sHelpTrig)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_SELECT_WEAPON)
IF IS_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, INPUT_FRONTEND_LB)
bPrintHelp = FALSE
eScriptStage = SCRIPT_STAGE_SAVEGAME
eSaveStage = SAVE_STAGE_INTRO
iStage = 0
ENDIF
ENDIF*/
bPrintHelp = TRUE
IF iContextID = NEW_CONTEXT_INTENTION
REGISTER_CONTEXT_INTENTION(iContextID, CP_MEDIUM_PRIORITY, sHelpTrig)
ENDIF
SET_INPUT_EXCLUSIVE(PLAYER_CONTROL, INPUT_CONTEXT)
IF HAS_CONTEXT_BUTTON_TRIGGERED(iContextID)
bPrintHelp = FALSE
PAUSE_FLOW_HELP_QUEUE(TRUE)
eScriptStage = SCRIPT_STAGE_SAVEGAME
eSaveStage = SAVE_STAGE_INTRO
iStage = 0
ENDIF
ENDIF
ENDIF
ENDIF
ELIF iSavebedGetUpStage = 0
UNLOAD_ASSETS_FOR_SAVE_PROCESS()
ENDIF
/*IF NOT bPrintHelp
IF IS_THIS_HELP_MESSAGE_BEING_DISPLAYED(sHelpTrig)
CLEAR_HELP()
ENDIF
ENDIF*/
IF NOT bPrintHelp
IF iContextID != NEW_CONTEXT_INTENTION
RELEASE_CONTEXT_INTENTION(iContextID)
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
PROC DO_SAVEGAME()
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
SET_ALL_RANDOM_PEDS_FLEE_THIS_FRAME(PLAYER_ID())
PED_INDEX nearbyPeds[5]
SWITCH eSaveStage
CASE SAVE_STAGE_INTRO
SWITCH iStage
CASE 0
SET_SCRIPTS_SAFE_FOR_CUTSCENE(TRUE,DEFAULT,TRUE,TRUE)
LOAD_ASSETS_FOR_SAVE_PROCESS()
//Block all phonecalls/texts from coming in for 45 seconds after triggering sleeping.
ADD_GLOBAL_COMMUNICATION_DELAY(45000)
// Clear the number of kills since last savehouse stat for this character.
SWITCH eCurrentPlayerPed
CASE CHAR_MICHAEL STAT_SET_INT(SP0_KILLS_SINCE_SAFEHOUSE_VISIT, 0) BREAK
CASE CHAR_FRANKLIN STAT_SET_INT(SP1_KILLS_SINCE_SAFEHOUSE_VISIT, 0) BREAK
CASE CHAR_TREVOR STAT_SET_INT(SP2_KILLS_SINCE_SAFEHOUSE_VISIT, 0) BREAK
ENDSWITCH
iStage++
BREAK
CASE 1
// Wait for the assets
IF LOAD_ASSETS_FOR_SAVE_PROCESS()
// Remove any HUD elements
DISPLAY_RADAR(FALSE)
DISPLAY_HUD(FALSE)
// Reposition the players vehicle
VEHICLE_INDEX playersVehicle
playersVehicle = GET_PLAYERS_LAST_VEHICLE()
IF DOES_ENTITY_EXIST(playersVehicle)
IF IS_VEHICLE_DRIVEABLE(playersVehicle)
IF GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(playersVehicle), sData.vBedCoords) < 75.0
// Make sure it is a mission entity otherwise it may get removed with the clear area.
IF NOT IS_ENTITY_A_MISSION_ENTITY(playersVehicle)
SET_ENTITY_AS_MISSION_ENTITY(playersVehicle, TRUE)
ENDIF
CLEAR_AREA(sData.vVehicleCoords, 10.0, TRUE)
IF IS_VEHICLE_DRIVEABLE(playersVehicle)
/*IF IS_PLAYERS_VEHICLE_OF_TYPE(PV_SAFE_FOR_REPOSITION)
SET_ENTITY_COORDS(playersVehicle, sData.vVehicleCoords)
SET_ENTITY_HEADING(playersVehicle, sData.fVehicleHeading)
SET_VEHICLE_ON_GROUND_PROPERLY(playersVehicle)
ENDIF*/
SET_VEHICLE_DOORS_SHUT(playersVehicle)
ENDIF
ENDIF
ENDIF
ENDIF
// Clear the area and set up the player
CLEAR_AREA(sData.vBedCoords, 15.0, TRUE)
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE)
SET_ENTITY_PROOFS(PLAYER_PED_ID(), TRUE, TRUE, TRUE, TRUE, TRUE)
SET_CURRENT_PED_WEAPON(PLAYER_PED_ID(), WEAPONTYPE_UNARMED, TRUE)
CLEAR_PED_TASKS_IMMEDIATELY(PLAYER_PED_ID())
SET_PED_CLOTH_PRONE(PLAYER_PED_ID(), TRUE)
// Mark the players last vehicle as no longer needed so that the save garage can pick it up.
IF IS_VEHICLE_DRIVEABLE(playersVehicle)
IF DOES_ENTITY_BELONG_TO_THIS_SCRIPT(playersVehicle)
SET_VEHICLE_AS_NO_LONGER_NEEDED(playersVehicle)
ENDIF
ENDIF
BOOL bAltEntry
bAltEntry = FALSE
// If michael and left hand side...
IF sData.eSavehouse = SAVEHOUSE_MICHAEL_BH
IF g_eCurrentFamilyEvent[FM_MICHAEL_WIFE] = FE_M7_WIFE_sleeping
bAltEntry = TRUE
ELIF g_eCurrentFamilyEvent[FM_MICHAEL_WIFE] != FE_M_WIFE_passed_out_BED
AND g_eCurrentFamilyEvent[FM_MICHAEL_WIFE] != FE_M2_WIFE_sleeping
#IF NOT IS_JAPANESE_BUILD
AND g_eCurrentFamilyEvent[FM_MICHAEL_WIFE] != FE_M2_WIFE_using_vibrator
AND g_eCurrentFamilyEvent[FM_MICHAEL_WIFE] != FE_M_WIFE_using_vibrator_END
AND g_eCurrentFamilyEvent[FM_MICHAEL_WIFE] != FE_M7_WIFE_using_vibrator
#ENDIF
IF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<-816.737061,179.975952,75.303238>>, <<-814.274292,180.950089,78.542625>>, 7.437500)
bAltEntry = TRUE
ENDIF
ENDIF
ELIF sData.eSavehouse = SAVEHOUSE_FRANKLIN_VH
IF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<0.342038,521.995911,169.429657>>, <<-0.790193,524.314209,171.699051>>, 7.437500)
bAltEntry = TRUE
ENDIF
ELIF sData.eSavehouse = SAVEHOUSE_TREVOR_VB
IF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<-1150.280029,-1513.458740,9.321099>>, <<-1148.496460,-1512.256226,11.287054>>, 4.375000)
bAltEntry = TRUE
ENDIF
// If michael and trevor is present...
ELIF sData.eSavehouse = SAVEHOUSE_MICHAEL_CS
INT iPeds, iPed
iPeds = GET_PED_NEARBY_PEDS(PLAYER_PED_ID(), nearbyPeds)
REPEAT iPeds iPed
IF DOES_ENTITY_EXIST(nearbyPeds[iPed])
AND NOT IS_PED_INJURED(nearbyPeds[iPed])
AND GET_ENTITY_MODEL(nearbyPeds[iPed]) = GET_PLAYER_PED_MODEL(CHAR_TREVOR)
SET_ENTITY_AS_MISSION_ENTITY(nearbyPeds[iPed], FALSE, TRUE)
DELETE_PED(nearbyPeds[iPed])
PRIVATE_Set_Current_Family_Member_Event(FM_TREVOR_0_TREVOR, FAMILY_MEMBER_BUSY)
ENDIF
ENDREPEAT
ENDIF
GET_SAVEGAME_BED_ANIM_DATA(sData, bAltEntry)
// Set up the 'get in' phase
iSceneID = CREATE_SYNCHRONIZED_SCENE(sData.vSceneCoords, sData.vSceneRot)
TASK_SYNCHRONIZED_SCENE(PLAYER_PED_ID(), iSceneID, sData.tlAnimDict, sData.tlGetIn, INSTANT_BLEND_IN, NORMAL_BLEND_OUT)
SET_SYNCHRONIZED_SCENE_HOLD_LAST_FRAME(iSceneID, TRUE)
// Set up the animated camera
IF NOT DOES_CAM_EXIST(camID)
camID = CREATE_CAM("DEFAULT_ANIMATED_CAMERA", FALSE)
ENDIF
tlCamAnim = sData.tlGetIn
tlCamAnim += "_CAM"
PLAY_CAM_ANIM(camID, tlCamAnim, sData.tlAnimDict, sData.vSceneCoords, sData.vSceneRot)
SET_CAM_ACTIVE(camID, TRUE)
IF (GET_CAM_VIEW_MODE_FOR_CONTEXT(GET_CAM_ACTIVE_VIEW_MODE_CONTEXT()) != CAM_VIEW_MODE_FIRST_PERSON)
RENDER_SCRIPT_CAMS(TRUE, FALSE)
ENDIF
SETTIMERA(0)
bSaveActive = TRUE
iStage++
ENDIF
BREAK
CASE 2
// Wait for the 'get in' phase to complete
IF IS_SYNCHRONIZED_SCENE_RUNNING(iSceneID)
IF GET_SYNCHRONIZED_SCENE_PHASE(iSceneID) >= 1.0
// Set up the 'bed loop' phase
// iSceneID = CREATE_SYNCHRONIZED_SCENE(sData.vSceneCoords, sData.vSceneRot)
// SET_SYNCHRONIZED_SCENE_LOOPED(iSceneID, TRUE)
// TASK_SYNCHRONIZED_SCENE(PLAYER_PED_ID(), iSceneID, sData.tlAnimDict, sData.tlGetInLoop, NORMAL_BLEND_IN, NORMAL_BLEND_OUT)
//FREEZE_ENTITY_POSITION(PLAYER_PED_ID(), TRUE)
iStage=0
eSaveStage = SAVE_STAGE_PERFORM_SAVE
ENDIF
// Something has gone wrong with the sync scene - see if we can fix it, otherwise bail.
ELIF TIMERA() > 1000
IF iSavegameBedRetryAttempt < 1
AND NOT IS_CUTSCENE_PLAYING()
PRINTLN("Savegame bed sync scene not running!? RETRY")
iSceneID = CREATE_SYNCHRONIZED_SCENE(sData.vSceneCoords, sData.vSceneRot)
TASK_SYNCHRONIZED_SCENE(PLAYER_PED_ID(), iSceneID, sData.tlAnimDict, sData.tlGetIn, INSTANT_BLEND_IN, NORMAL_BLEND_OUT)
SET_SYNCHRONIZED_SCENE_HOLD_LAST_FRAME(iSceneID, TRUE)
SETTIMERA(0)
iSavegameBedRetryAttempt++
ELSE
PRINTLN("Savegame bed sync scene not running!? BAIL")
eSaveStage = SAVE_STAGE_CLEANUP
ENDIF
ENDIF
BREAK
ENDSWITCH
BREAK
CASE SAVE_STAGE_PERFORM_SAVE
SWITCH iStage
CASE 0
If not IS_SCREEN_FADING_OUT()
and IS_SCREEN_FADED_IN()
DO_SCREEN_FADE_OUT(DEFAULT_FADE_TIME)
ELif IS_SCREEN_FADED_OUT()
// Advance time now so it gets saved.
SWITCH eCurrentPlayerPed
CASE CHAR_MICHAEL ADD_TO_CLOCK_TIME(6, 0, 0) ADVANCE_FRIEND_TIMERS(6.0) BREAK
CASE CHAR_FRANKLIN ADD_TO_CLOCK_TIME(8, 0, 0) ADVANCE_FRIEND_TIMERS(8.0) BREAK
CASE CHAR_TREVOR ADD_TO_CLOCK_TIME(12, 0, 0) ADVANCE_FRIEND_TIMERS(12.0) BREAK
DEFAULT ADD_TO_CLOCK_TIME(6, 0, 0) ADVANCE_FRIEND_TIMERS(6.0) BREAK
ENDSWITCH
Force_All_Drunk_Peds_To_Become_Sober_And_Quit_Camera()
DISABLE_CELLPHONE_THIS_FRAME_ONLY()
HANG_UP_AND_PUT_AWAY_PHONE()
PERFORM_PRE_SAVEGAME_ROUTINE(FALSE, FALSE)
SET_SAVE_MENU_ACTIVE()
iStage++
ENDIF
BREAK
CASE 1
// Perform any routines if we made a successful save
IF GET_STATUS_OF_MANUAL_SAVE() <> SAVEGAME_OPERATION_IN_PROGRESS
iStage++
ENDIF
BREAK
CASE 2
//IF GET_STATUS_OF_MANUAL_SAVE() = SAVEGAME_OPERATION_SUCCEEDED
// Clear decals.
CLEAR_PED_BLOOD_DAMAGE_BY_ZONE(PLAYER_PED_ID(), PDZ_TORSO)
CLEAR_PED_BLOOD_DAMAGE_BY_ZONE(PLAYER_PED_ID(), PDZ_HEAD)
CLEAR_PED_BLOOD_DAMAGE_BY_ZONE(PLAYER_PED_ID(), PDZ_LEFT_ARM)
CLEAR_PED_BLOOD_DAMAGE_BY_ZONE(PLAYER_PED_ID(), PDZ_RIGHT_ARM)
CLEAR_PED_BLOOD_DAMAGE_BY_ZONE(PLAYER_PED_ID(), PDZ_LEFT_LEG)
CLEAR_PED_BLOOD_DAMAGE_BY_ZONE(PLAYER_PED_ID(), PDZ_RIGHT_LEG)
CLEAR_PED_ENV_DIRT(PLAYER_PED_ID())
SKIP_RADIO_FORWARD()
// Play the alarm clock sound
STRING sAlarmSounds
SWITCH sData.eAlarm
CASE ALARMCLOCK_BELL
sAlarmSounds = "Alarm_Clocks_Bell"
BREAK
CASE ALARMCLOCK_COWBELL
sAlarmSounds = "Alarm_Clocks_Cowbell"
BREAK
CASE ALARMCLOCK_ELECTRONIC
sAlarmSounds = "Alarm_Clocks_Electronic"
BREAK
DEFAULT
sAlarmSounds = sDefaultAlarmSound
BREAK
ENDSWITCH
#IF IS_DEBUG_BUILD
IF d_bOverrideAlarm
sAlarmSounds = GET_CONTENTS_OF_TEXT_WIDGET(d_textID)
ENDIF
#ENDIF
PLAY_SOUND_FRONTEND(-1, sAlarmSounds)
//ENDIF
// Make sure it is a mission entity otherwise it may get removed with the clear area.
VEHICLE_INDEX playersVehicle
playersVehicle = GET_PLAYERS_LAST_VEHICLE()
IF DOES_ENTITY_EXIST(playersVehicle)
IF IS_VEHICLE_DRIVEABLE(playersVehicle)
IF GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(playersVehicle), sData.vBedCoords) < 75.0
IF NOT IS_ENTITY_A_MISSION_ENTITY(playersVehicle)
SET_ENTITY_AS_MISSION_ENTITY(playersVehicle, TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
SET_PLAYER_WANTED_LEVEL(PLAYER_ID(), 0)
CLEAR_AREA(GET_ENTITY_COORDS(PLAYER_PED_ID()), 500.0, TRUE)
IF IS_VEHICLE_DRIVEABLE(playersVehicle)
IF DOES_ENTITY_BELONG_TO_THIS_SCRIPT(playersVehicle)
SET_VEHICLE_AS_NO_LONGER_NEEDED(playersVehicle)
ENDIF
ENDIF
iStage=0
eSaveStage = SAVE_STAGE_OUTRO
BREAK
ENDSWITCH
BREAK
CASE SAVE_STAGE_OUTRO
SWITCH iStage
CASE 0
TEXT_LABEL_31 tlRoomType
GET_SAVEGAME_ROOM_TYPE(sData.eSavehouse, tlRoomType)
INTERIOR_INSTANCE_INDEX savehouseInterior
savehouseInterior = GET_INTERIOR_AT_COORDS_WITH_TYPE(g_sSavehouses[sData.eSavehouse].vSpawnCoords, tlRoomType)
IF savehouseInterior != NULL
REFRESH_INTERIOR(savehouseInterior)
ENDIF
NEW_LOAD_SCENE_START_SPHERE(GET_ENTITY_COORDS(PLAYER_PED_ID(), FALSE), 12.0)
SETTIMERA(0)
iStage++
BREAK
CASE 1
IF IS_NEW_LOAD_SCENE_ACTIVE()
AND NOT IS_NEW_LOAD_SCENE_LOADED()
AND TIMERA() < 8000
// wait
PRINTLN("SAVEGAME BED - waiting for new load scene to finish")
ELSE
IF IS_NEW_LOAD_SCENE_ACTIVE()
NEW_LOAD_SCENE_STOP()
ENDIF
iStage++
ENDIF
BREAK
CASE 2
DO_SCREEN_FADE_IN(DEFAULT_FADE_TIME_LONG)
THEFEED_FLUSH_QUEUE()
//FREEZE_ENTITY_POSITION(PLAYER_PED_ID(), FALSE)
// Set up the 'get out' phase
iSceneID = CREATE_SYNCHRONIZED_SCENE(sData.vSceneCoords, sData.vSceneRot)
SET_SYNCHRONIZED_SCENE_LOOPED(iSceneID, FALSE)
SET_SYNCHRONIZED_SCENE_HOLD_LAST_FRAME(iSceneID, FALSE)
TASK_SYNCHRONIZED_SCENE(PLAYER_PED_ID(), iSceneID, sData.tlAnimDict, sData.tlGetOut, NORMAL_BLEND_IN, WALK_BLEND_OUT, SYNCED_SCENE_NONE, RBF_NONE, INSTANT_BLEND_IN, AIK_DISABLE_LEG_IK)
// Set up the animated camera
IF NOT DOES_CAM_EXIST(camID)
camID = CREATE_CAM("DEFAULT_ANIMATED_CAMERA", FALSE)
ENDIF
tlCamAnim = sData.tlGetOut
tlCamAnim += "_CAM"
PLAY_CAM_ANIM(camID, tlCamAnim, sData.tlAnimDict, sData.vSceneCoords, sData.vSceneRot)
SET_CAM_ACTIVE(camID, TRUE)
IF (GET_CAM_VIEW_MODE_FOR_CONTEXT(GET_CAM_ACTIVE_VIEW_MODE_CONTEXT()) != CAM_VIEW_MODE_FIRST_PERSON)
RENDER_SCRIPT_CAMS(TRUE, FALSE)
ENDIF
iStage++
BREAK
CASE 3
// Wait for the 'get out' phase to complete
IF NOT IS_SYNCHRONIZED_SCENE_RUNNING(iSceneID)
OR GET_SYNCHRONIZED_SCENE_PHASE(iSceneID) >= 1.0
iStage=0
eSaveStage = SAVE_STAGE_CLEANUP
ENDIF
BREAK
ENDSWITCH
BREAK
CASE SAVE_STAGE_CLEANUP
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
SET_ENTITY_PROOFS(PLAYER_PED_ID(), FALSE, FALSE, FALSE, FALSE, FALSE)
CLEAR_PED_TASKS(PLAYER_PED_ID())
IF DOES_CAM_EXIST(camID)
SET_CAM_ACTIVE(camID, FALSE)
DESTROY_CAM(camID)
ENDIF
IF (GET_CAM_VIEW_MODE_FOR_CONTEXT(GET_CAM_ACTIVE_VIEW_MODE_CONTEXT()) != CAM_VIEW_MODE_FIRST_PERSON)
STOP_RENDERING_SCRIPT_CAMS_USING_CATCH_UP()
ENDIF
DISPLAY_RADAR(TRUE)
DISPLAY_HUD(TRUE)
PAUSE_FLOW_HELP_QUEUE(FALSE)
SET_SCRIPTS_SAFE_FOR_CUTSCENE(FALSE)
// Relaunch Chop script when saving as Franklin
IF eCurrentPlayerPed = CHAR_FRANKLIN
IF sData.eSavehouse = SAVEHOUSE_FRANKLIN_SC
OR sData.eSavehouse = SAVEHOUSE_FRANKLIN_VH
REACTIVATE_NAMED_WORLD_BRAINS_WAITING_TILL_OUT_OF_RANGE("chop")
ENDIF
ENDIF
SET_PED_CLOTH_PRONE(PLAYER_PED_ID(), TRUE)
bSaveActive = FALSE
iSavegameBedRetryAttempt = 0
// Let player know how to change clothes
/*bDisplayWardrobeHint = FALSE
IF g_savedGlobals.sAmbient.iWardrobeHintsDisplayed < 2
IF DOES_SAVEHOUSE_HAVE_WARDROBE(sData.eSavehouse)
PRINT_HELP_FOREVER("SAVE_WARD")
iWardrobeHintTimer = GET_GAME_TIMER()
bDisplayWardrobeHint = TRUE
g_savedGlobals.sAmbient.iWardrobeHintsDisplayed++
ENDIF
ENDIF*/
eScriptStage = SCRIPT_STAGE_WAIT_FOR_TRIGGER
BREAK
ENDSWITCH
ENDIF
ENDPROC
PROC MANAGE_INPUT_BLOCKS()
IF eScriptStage = SCRIPT_STAGE_SAVEGAME
DISABLE_CELLPHONE_THIS_FRAME_ONLY()
DISABLE_SELECTOR_THIS_FRAME()
DISABLE_CONTROL_ACTION(FRONTEND_CONTROL, INPUT_FRONTEND_PAUSE)
ENDIF
ENDPROC
SCRIPT(coords_struct in_coords)
PRINTNL()
PRINTSTRING("SAVEGAME BED SCRIPT STARTING")
PRINTNL()
PRINTVECTOR(in_coords.vec_coord[0])
PRINTNL()
vInCoords = in_coords.vec_coord[0]
IF HAS_FORCE_CLEANUP_OCCURRED(FORCE_CLEANUP_FLAG_SP_TO_MP)
CLEANUP_SCRIPT()
ENDIF
//Load spPacks verions of the savegame_bed
IF g_bLoadedClifford
IF GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("savegame_bedCLF")) = 0
REQUEST_SCRIPT_WITH_NAME_HASH(HASH("savegame_bedCLF"))
WHILE NOT HAS_SCRIPT_WITH_NAME_HASH_LOADED(HASH("savegame_bedCLF"))
WAIT(0)
ENDWHILE
START_NEW_SCRIPT_WITH_NAME_HASH_AND_ARGS(HASH("savegame_bedCLF"),in_coords, SIZE_OF(in_coords),DEFAULT_STACK_SIZE)
ENDIF
//Shutdown bed save script since we're switching to AGT
TERMINATE_THIS_THREAD()
ENDIF
#IF IS_DEBUG_BUILD
SETUP_SAVEGAME_BED_DEBUG_WIDGETS()
#ENDIF
// Main loop
WHILE TRUE
WAIT(0)
#IF IS_DEBUG_BUILD
MAINTAIN_SAVEGAME_BED_DEBUG_WIDGETS()
#ENDIF
// Cleanup the script when the player goes out of range
IF NOT IS_WORLD_POINT_WITHIN_BRAIN_ACTIVATION_RANGE()
OR g_bMagDemoActive
eScriptStage = SCRIPT_STAGE_CLEANUP
ENDIF
eCurrentPlayerPed = GET_CURRENT_PLAYER_PED_ENUM()
// Perform the main processing
SWITCH eScriptStage
CASE SCRIPT_STAGE_INITIALISE
DO_INITIALISE()
BREAK
CASE SCRIPT_STAGE_WAIT_FOR_TRIGGER
PROCESS_SAVEBED_GETUP()
PROCESS_SAVE_GARAGE()
CHECK_SAVEBED_TRIGGER()
BREAK
CASE SCRIPT_STAGE_SAVEGAME
DO_SAVEGAME()
BREAK
CASE SCRIPT_STAGE_CLEANUP
CLEANUP_SCRIPT()
BREAK
ENDSWITCH
MANAGE_INPUT_BLOCKS()
MANAGE_HEALTH_PICKUPS()
CHECK_CONTROLLER_RESET()
ENDWHILE
ENDSCRIPT