945 lines
25 KiB
Python
Executable File
945 lines
25 KiB
Python
Executable File
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
//
|
|
// MISSION NAME : VehicleRepair.sc
|
|
// AUTHOR : Aaron Gandaa
|
|
// DESCRIPTION : Vehicle Repair Script / Mini Game
|
|
//
|
|
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
|
|
|
|
//----------------------
|
|
// INCLUDES
|
|
//----------------------
|
|
USING "rgeneral_include.sch"
|
|
USING "RC_Helper_Functions.sch"
|
|
USING "RC_Asset_Public.sch"
|
|
USING "RC_Camera_Public.sch"
|
|
USING "commands_brains.sch"
|
|
USING "net_fps_cam.sch"
|
|
USING "Fairground_Shared.sch"
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
USING "shared_debug.sch"
|
|
#ENDIF
|
|
|
|
//----------------------
|
|
// ENUM
|
|
//----------------------
|
|
|
|
//----------------------
|
|
// CONSTANTS
|
|
//----------------------
|
|
CONST_INT MAX_OCCUPIED_WHEEL_CARS 8
|
|
CONST_INT MAX_WHEEL_CARS 16
|
|
CONST_INT MAX_WHEEL_CAR_OCCUPANTS 2
|
|
CONST_FLOAT WHEEL_CAR_RADIUS 15.3
|
|
CONST_INT WHEEL_CAR_LOD_DIST 1000
|
|
|
|
CONST_INT PLAYER_WHEEL_CAR 1
|
|
|
|
//----------------------
|
|
// STRUCT
|
|
//----------------------
|
|
STRUCT WHEEL_CAR
|
|
BOOL bOccupied = FALSE
|
|
INT iSyncSceneID
|
|
INT iIndex
|
|
|
|
OBJECT_INDEX objectID
|
|
PED_INDEX pedID[MAX_WHEEL_CAR_OCCUPANTS]
|
|
ENDSTRUCT
|
|
|
|
//----------------------
|
|
// VARIABLES
|
|
//----------------------
|
|
ASSET_REQUESTER asRequest
|
|
|
|
MODEL_NAMES wheelModel = PROP_LD_FERRIS_WHEEL
|
|
MODEL_NAMES wheelCarModel = PROP_FERRIS_CAR_01
|
|
STRING sWheelCarAnimDict = "MISSFINALE_C2IG_5"
|
|
|
|
OBJECT_INDEX wheelObjectID
|
|
WHEEL_CAR wheelCar[MAX_WHEEL_CARS]
|
|
|
|
INT iRevolutions = 0
|
|
FLOAT fWheelRotation = 0.0
|
|
FLOAT fWheelRotationRate = 2.0
|
|
VECTOR vWheelCenter = <<-1663.970, -1126.700, 30.700>>
|
|
VECTOR vPedWheelCarAttachOffset = <<0.5, 0.5, -1.94>> // radius = 0.5, height below = -1.94
|
|
FLOAT fWheelGroundZ = 13.0
|
|
FLOAT fPlayerWheelCarAngle = 260.0
|
|
INT iPlayerWheelCarAnim = 0
|
|
|
|
INT iGeneratorSoundID = -1
|
|
INT iRattlingSoundID = -1
|
|
INT iSlowSqueakSoundID = -1
|
|
INT iSqueakSoundID = -1
|
|
INT iCameraTimer
|
|
|
|
BOOL bStandardCamera = TRUE
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
WIDGET_GROUP_ID widgetGroup
|
|
BOOL bQuit = FALSE
|
|
BOOL bShowDebug = FALSE
|
|
BOOL bRespotPlayer = FALSE
|
|
#ENDIF
|
|
|
|
CAMERA_INDEX initialCamera
|
|
|
|
FIRST_PERSON_CAM_STRUCT fpsCam
|
|
CAMERA_STRUCT outerCamera
|
|
BASIC_CAMERA fpsTestCam
|
|
CAMERA_INDEX cameraID
|
|
BOOL bFPSMode
|
|
|
|
BOOL bSkipped = FALSE
|
|
INT iOccupiedCount = 0
|
|
|
|
//----------------------
|
|
// FUNCTIONS
|
|
//----------------------
|
|
|
|
//----------------------
|
|
// DBG FUNCTIONS
|
|
//----------------------
|
|
#IF IS_DEBUG_BUILD
|
|
|
|
/// PURPOSE:
|
|
/// Initializes Debug Widgets
|
|
PROC SETUP_DEBUG_WIDGETS()
|
|
SET_PROFILING_OF_THIS_SCRIPT(TRUE)
|
|
widgetGroup = START_WIDGET_GROUP("Fairground - Bigwheel")
|
|
ADD_WIDGET_BOOL("Quit Script", bQuit)
|
|
ADD_WIDGET_BOOL("Show Debug", bShowDebug)
|
|
ADD_WIDGET_BOOL("Use Standard Cam", bStandardCamera)
|
|
ADD_WIDGET_VECTOR_SLIDER("Wheel Pos", vWheelCenter, -2500.0, 2500, 0.1)
|
|
ADD_WIDGET_FLOAT_SLIDER("Rotate Rate", fWheelRotationRate, 0, 180, 1)
|
|
ADD_WIDGET_FLOAT_SLIDER("Rotation", fWheelRotation, 0, 360, 1)
|
|
ADD_WIDGET_INT_READ_ONLY("Revs", iRevolutions)
|
|
|
|
ADD_WIDGET_BOOL("Respot Player", bRespotPlayer)
|
|
ADD_WIDGET_FLOAT_SLIDER("Player Wheel Angle", fPlayerWheelCarAngle, -360, 360, 1)
|
|
ADD_WIDGET_INT_SLIDER("Player Wheel Anim", iPlayerWheelCarAnim, 0, 3, 1)
|
|
|
|
START_WIDGET_GROUP("FPS Camera")
|
|
ADD_WIDGET_INT_SLIDER("Look X Limit", fpsCam.iLookXLimit, -360, 360, 1)
|
|
ADD_WIDGET_INT_SLIDER("Look Y Limit", fpsCam.iLookYLimit, -360, 360, 1)
|
|
STOP_WIDGET_GROUP()
|
|
STOP_WIDGET_GROUP()
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Removes Debug Widgets
|
|
PROC CLEANUP_DEBUG_WIDGETS()
|
|
IF DOES_WIDGET_GROUP_EXIST(widgetGroup)
|
|
DELETE_WIDGET_GROUP(widgetGroup)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
#ENDIF
|
|
|
|
/// PURPOSE:
|
|
/// Switch to First Person
|
|
PROC SWITCH_TO_FIRST_PERSON_MODE(BOOL bForceCameraShutdown = TRUE)
|
|
VECTOR v
|
|
IF IS_ENTITY_OK(PLAYER_PED_ID())
|
|
|
|
IF (bForceCameraShutdown)
|
|
SHUTDOWN_CAMERA(cameraID)
|
|
ENDIF
|
|
|
|
|
|
fpsCam.iLookXLimit = 160
|
|
fpsCam.iLookYLimit = 20
|
|
|
|
IF (bStandardCamera)
|
|
v = GET_PED_BONE_COORDS(PLAYER_PED_ID(), BONETAG_HEAD, <<0, -0.25, 0>>)
|
|
INIT_FIRST_PERSON_CAMERA(fpsCam, v, GET_ENTITY_ROTATION(PLAYER_PED_ID()), 50.0, fpsCam.iLookXLimit, fpsCam.iLookYLimit)
|
|
ATTACH_CAM_TO_PED_BONE(fpsCam.theCam, PLAYER_PED_ID(), BONETAG_HEAD, <<0, -0.25, 0>>)
|
|
ELSE
|
|
SETUP_BASIC_FPS_CAMERA(fpsTestCam, TRUE)
|
|
ENABLE_BASIC_CAMERA(fpsTestCam)
|
|
ENDIF
|
|
|
|
SET_ENTITY_VISIBLE(PLAYER_PED_ID(), FALSE)
|
|
|
|
IF IS_AUDIO_SCENE_ACTIVE("FAIRGROUND_RIDES_FERRIS_WHALE_ALTERNATIVE_VIEW")
|
|
STOP_AUDIO_SCENE("FAIRGROUND_RIDES_FERRIS_WHALE_ALTERNATIVE_VIEW")
|
|
ENDIF
|
|
START_AUDIO_SCENE("FAIRGROUND_RIDES_FERRIS_WHALE")
|
|
ENDIF
|
|
|
|
CPRINTLN(DEBUG_MISSION, "[BIGWHEEL] - FPS CAMERA ON - ", GET_FRAME_COUNT())
|
|
bFPSMode = TRUE
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Switch to External View
|
|
PROC SWITCH_TO_EXTERNAL_MODE()
|
|
IF IS_ENTITY_OK(PLAYER_PED_ID())
|
|
DESTROY_BASIC_CAMERA(fpsTestCam)
|
|
CLEAR_FIRST_PERSON_CAMERA(fpsCam)
|
|
ENABLE_CAMERA_STRUCT(outerCamera, cameraID)
|
|
SET_ENTITY_VISIBLE(PLAYER_PED_ID(), TRUE)
|
|
bFPSMode = FALSE
|
|
|
|
IF IS_AUDIO_SCENE_ACTIVE("FAIRGROUND_RIDES_FERRIS_WHALE")
|
|
STOP_AUDIO_SCENE("FAIRGROUND_RIDES_FERRIS_WHALE")
|
|
ENDIF
|
|
|
|
START_AUDIO_SCENE("FAIRGROUND_RIDES_FERRIS_WHALE_ALTERNATIVE_VIEW")
|
|
ENDIF
|
|
|
|
CPRINTLN(DEBUG_MISSION, "[BIGWHEEL] - EXT CAMERA ON - ", GET_FRAME_COUNT())
|
|
ENDPROC
|
|
|
|
PROC DISABLE_CONTROL_AND_WAIT(INT i)
|
|
INT iWaitEnd = GET_GAME_TIMER() + i
|
|
|
|
WHILE (GET_GAME_TIMER() < iWaitEnd)
|
|
RC_DISABLE_CONTROL_ACTIONS_FOR_LEAD_IN()
|
|
DISABLE_SELECTOR_THIS_FRAME()
|
|
WAIT(0)
|
|
ENDWHILE
|
|
ENDPROC
|
|
|
|
//----------------------
|
|
// WHEEL
|
|
//----------------------
|
|
|
|
/// PURPOSE:
|
|
/// Calculate Position Of Wheel Car
|
|
/// PARAMS:
|
|
/// iGondola - Gondola Index
|
|
/// RETURNS:
|
|
/// Position of car
|
|
FUNC VECTOR CALCULATE_WHEEL_CAR_POSITION(INT iGondola)
|
|
FLOAT fAngle = (360.0 / TO_FLOAT(MAX_WHEEL_CARS)) * TO_FLOAT(iGondola)
|
|
RETURN GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(wheelObjectID, <<0, WHEEL_CAR_RADIUS * SIN(fAngle), -WHEEL_CAR_RADIUS * COS(fAngle)>>)
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Gets the offset from a wheel car that a ped needs to be standing on the end
|
|
/// PARAMS:
|
|
/// angle - angle around the wheel car
|
|
/// RETURNS:
|
|
/// Vector
|
|
FUNC VECTOR CALCULATE_PED_WHEEL_CAR_OFFSET(FLOAT angle)
|
|
VECTOR v
|
|
|
|
v.x = SIN(angle) * vPedWheelCarAttachOffset.x
|
|
v.y = COS(angle) * vPedWheelCarAttachOffset.y
|
|
v.z = vPedWheelCarAttachOffset.z
|
|
|
|
RETURN v
|
|
ENDFUNC
|
|
|
|
|
|
// get bystander variant
|
|
FUNC INT GET_WHEEL_BYSTANDER_VARIANT(INT iGondola, INT iIndex)
|
|
SWITCH iGondola
|
|
CASE 0
|
|
IF iIndex=0
|
|
RETURN 0
|
|
ELSE
|
|
RETURN 1
|
|
ENDIF
|
|
BREAK
|
|
CASE 1
|
|
IF iIndex=0
|
|
RETURN 0
|
|
ELSE
|
|
RETURN 1
|
|
ENDIF
|
|
BREAK
|
|
CASE 2
|
|
IF iIndex=0
|
|
RETURN 2
|
|
ELSE
|
|
RETURN 3
|
|
ENDIF
|
|
BREAK
|
|
CASE 3
|
|
IF iIndex=0
|
|
RETURN 2
|
|
ELSE
|
|
RETURN 3
|
|
ENDIF
|
|
BREAK
|
|
CASE 4
|
|
IF iIndex=0
|
|
RETURN 2
|
|
ELSE
|
|
RETURN 3
|
|
ENDIF
|
|
BREAK
|
|
CASE 5
|
|
IF iIndex=0
|
|
RETURN 0
|
|
ELSE
|
|
RETURN 1
|
|
ENDIF
|
|
BREAK
|
|
CASE 6
|
|
IF iIndex=0
|
|
RETURN 0
|
|
ELSE
|
|
RETURN 1
|
|
ENDIF
|
|
BREAK
|
|
CASE 7
|
|
IF iIndex=0
|
|
RETURN 0
|
|
ELSE
|
|
RETURN 1
|
|
ENDIF
|
|
BREAK
|
|
CASE 8
|
|
IF iIndex=0
|
|
RETURN 2
|
|
ELSE
|
|
RETURN 3
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
RETURN 0
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Gets a random wheel car anim
|
|
/// RETURNS:
|
|
/// String Name
|
|
FUNC STRING GET_WHEEL_CAR_PED_ANIM(INT iVariant)
|
|
SWITCH iVariant
|
|
CASE 0
|
|
RETURN "Stand_Idle_1_PEDA"
|
|
BREAK
|
|
CASE 1
|
|
RETURN "Stand_Idle_1_PEDB"
|
|
BREAK
|
|
CASE 2
|
|
RETURN "Stand_Idle_2_PEDA"
|
|
BREAK
|
|
CASE 3
|
|
RETURN "Stand_Idle_2_PEDB"
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
RETURN NULL_STRING()
|
|
ENDFUNC
|
|
|
|
FUNC FLOAT GET_ANIM_ROT_FOR_OCCUPIED_GONDOLA(INT iGondola)
|
|
SWITCH iGondola
|
|
CASE 0
|
|
RETURN 180.0
|
|
BREAK
|
|
CASE 1
|
|
RETURN 340.0
|
|
BREAK
|
|
CASE 2
|
|
RETURN 90.0
|
|
BREAK
|
|
CASE 3
|
|
RETURN 250.0
|
|
BREAK
|
|
CASE 4
|
|
RETURN 300.0
|
|
BREAK
|
|
CASE 5
|
|
RETURN 160.0
|
|
BREAK
|
|
CASE 6
|
|
RETURN 180.0
|
|
BREAK
|
|
CASE 7
|
|
RETURN 340.0
|
|
BREAK
|
|
CASE 8
|
|
RETURN 90.0
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
RETURN 0.0
|
|
ENDFUNC
|
|
|
|
FUNC BOOL SHOULD_THIS_BE_OCCUPIED_GONDOLA(INT iGondola)
|
|
SWITCH iGondola
|
|
CASE 0
|
|
CASE 5
|
|
CASE 2
|
|
CASE 8
|
|
CASE 14
|
|
CASE 11
|
|
CASE 15
|
|
CASE 4
|
|
CASE 9
|
|
RETURN TRUE
|
|
ENDSWITCH
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
FUNC INT GET_GONDOLA_INDEX_FOR_OCCUPIED_GONDOLA(INT iGondola)
|
|
SWITCH iGondola
|
|
CASE 0
|
|
RETURN 0
|
|
BREAK
|
|
CASE 1
|
|
RETURN 5
|
|
BREAK
|
|
CASE 2
|
|
RETURN 2
|
|
BREAK
|
|
CASE 3
|
|
RETURN 8
|
|
BREAK
|
|
CASE 4
|
|
RETURN 14
|
|
BREAK
|
|
CASE 5
|
|
RETURN 11
|
|
BREAK
|
|
CASE 6
|
|
RETURN 15
|
|
BREAK
|
|
CASE 7
|
|
RETURN 4
|
|
BREAK
|
|
CASE 8
|
|
RETURN 9
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
RETURN -1
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Updates the wheel car
|
|
/// PARAMS:
|
|
/// w - wheel car reference
|
|
PROC UPDATE_WHEEL_CAR(WHEEL_CAR &w)
|
|
VECTOR v = CALCULATE_WHEEL_CAR_POSITION(w.iIndex)
|
|
|
|
IF IS_ENTITY_ALIVE(w.objectID)
|
|
SET_ENTITY_COORDS(w.objectID, v)
|
|
//SET_ENTITY_HEADING(w.objectID, fWheelRotation + ((w.iIndex % 2) * 180))
|
|
SET_ENTITY_LOD_DIST(w.objectID, WHEEL_CAR_LOD_DIST)
|
|
FREEZE_ENTITY_POSITION(w.objectID, TRUE)
|
|
ENDIF
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
FLOAT sx, sy
|
|
|
|
IF (bShowDebug)
|
|
IF GET_SCREEN_COORD_FROM_WORLD_COORD(v, sx, sy)
|
|
SET_TEXT_SCALE(1, 1)
|
|
|
|
IF (w.bOccupied)
|
|
SET_TEXT_COLOUR(0, 255, 0, 255)
|
|
ELSE
|
|
SET_TEXT_COLOUR(255, 0, 0, 255)
|
|
ENDIF
|
|
|
|
DISPLAY_TEXT_WITH_NUMBER(sx, sy, "NUMBER", w.iIndex)
|
|
ENDIF
|
|
ENDIF
|
|
#ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Cleanups up the wheel car
|
|
/// PARAMS:
|
|
/// w - car refernece
|
|
PROC CLEANUP_WHEEL_CAR(WHEEL_CAR &w)
|
|
INT i
|
|
IF (w.objectID = NULL)
|
|
EXIT
|
|
ENDIF
|
|
|
|
SAFE_DELETE_OBJECT(w.objectID)
|
|
|
|
REPEAT COUNT_OF(w.pedID) i
|
|
SAFE_DELETE_PED(w.pedID[i])
|
|
w.pedID[i] = NULL
|
|
ENDREPEAT
|
|
|
|
w.objectID = NULL
|
|
ENDPROC
|
|
|
|
PROC PUT_PLAYER_IN_WHEEL_CAR(WHEEL_CAR &w, FLOAT angle = 260.0)
|
|
STRING sAnim
|
|
|
|
IF IS_ENTITY_ATTACHED(PLAYER_PED_ID())
|
|
DETACH_ENTITY(PLAYER_PED_ID())
|
|
ENDIF
|
|
|
|
CLEAR_PED_TASKS(PLAYER_PED_ID())
|
|
w.iSyncSceneID = CREATE_SYNCHRONIZED_SCENE(<<0, 0, 0>>, <<0, 0, angle>>)
|
|
SET_SYNCHRONIZED_SCENE_ORIGIN(w.iSyncSceneID, <<0, 0, 0>>, <<0, 0, angle>>)
|
|
ATTACH_SYNCHRONIZED_SCENE_TO_ENTITY(w.iSyncSceneID, w.objectID, -1)
|
|
SET_SYNCHRONIZED_SCENE_LOOPED(w.iSyncSceneID, TRUE)
|
|
|
|
IF IS_ENTITY_OK(PLAYER_PED_ID())
|
|
SET_PED_KEEP_TASK(PLAYER_PED_ID(), TRUE)
|
|
SET_PED_CONFIG_FLAG(PLAYER_PED_ID(), PCF_RunFromFiresAndExplosions, FALSE)
|
|
SET_PED_CONFIG_FLAG(PLAYER_PED_ID(), PCF_DisableExplosionReactions, TRUE)
|
|
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(PLAYER_PED_ID(), TRUE)
|
|
SET_ENTITY_LOD_DIST(PLAYER_PED_ID(), WHEEL_CAR_LOD_DIST)
|
|
|
|
sAnim = GET_WHEEL_CAR_PED_ANIM(iPlayerWheelCarAnim)
|
|
IF NOT IS_STRING_NULL_OR_EMPTY(sAnim)
|
|
TASK_SYNCHRONIZED_SCENE(PLAYER_PED_ID(), w.iSyncSceneID, sWheelCarAnimDict, sAnim, INSTANT_BLEND_IN, NORMAL_BLEND_OUT)
|
|
FORCE_PED_AI_AND_ANIMATION_UPDATE(PLAYER_PED_ID())
|
|
ENDIF
|
|
ENDIF
|
|
|
|
EXIT
|
|
|
|
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(PLAYER_PED_ID(), TRUE)
|
|
SET_PED_KEEP_TASK(PLAYER_PED_ID(), TRUE)
|
|
SET_PED_CONFIG_FLAG(PLAYER_PED_ID(), PCF_RunFromFiresAndExplosions, FALSE)
|
|
SET_PED_CONFIG_FLAG(PLAYER_PED_ID(), PCF_DisableExplosionReactions, TRUE)
|
|
|
|
ATTACH_ENTITY_TO_ENTITY(PLAYER_PED_ID(), w.objectID, 0, CALCULATE_PED_WHEEL_CAR_OFFSET(angle), <<0, 0, angle>>)
|
|
TASK_PLAY_ANIM(PLAYER_PED_ID(), sWheelCarAnimDict, GET_WHEEL_CAR_PED_ANIM(iPlayerWheelCarAnim), INSTANT_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_LOOPING)
|
|
FORCE_PED_AI_AND_ANIMATION_UPDATE(PLAYER_PED_ID())
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Creates a wheel car
|
|
/// PARAMS:
|
|
/// w - wheel car reference
|
|
/// ind - number of car 0 to 11
|
|
/// bOccupied - whether it has people in it
|
|
PROC CREATE_WHEEL_CAR(WHEEL_CAR &w, INT ind, BOOL bOccupyPlayer = FALSE)
|
|
INT i
|
|
INT iVariant
|
|
MODEL_NAMES mdl
|
|
STRING sAnim
|
|
|
|
CLEANUP_WHEEL_CAR(w)
|
|
|
|
w.iIndex = ind
|
|
w.objectID = CREATE_OBJECT(wheelCarModel, <<0, 1, 2>>)
|
|
UPDATE_WHEEL_CAR(w)
|
|
|
|
|
|
IF (bOccupyPlayer = TRUE)
|
|
PUT_PLAYER_IN_WHEEL_CAR(w, fPlayerWheelCarAngle)
|
|
w.bOccupied = true
|
|
EXIT
|
|
ENDIF
|
|
|
|
// create synced scene index
|
|
IF (iOccupiedCount >= MAX_OCCUPIED_WHEEL_CARS)
|
|
EXIT
|
|
ENDIF
|
|
|
|
IF NOT SHOULD_THIS_BE_OCCUPIED_GONDOLA(w.iIndex)
|
|
EXIT
|
|
ENDIF
|
|
|
|
// create synced scene index
|
|
FLOAT fAnimRot = GET_ANIM_ROT_FOR_OCCUPIED_GONDOLA(iOccupiedCount)
|
|
w.iSyncSceneID = CREATE_SYNCHRONIZED_SCENE(<<0, 0, 0>>, <<0, 0, fAnimRot>>)
|
|
SET_SYNCHRONIZED_SCENE_ORIGIN(w.iSyncSceneID, <<0, 0, 0>>, <<0, 0, fAnimRot>>)
|
|
ATTACH_SYNCHRONIZED_SCENE_TO_ENTITY(w.iSyncSceneID, w.objectID, -1)
|
|
SET_SYNCHRONIZED_SCENE_LOOPED(w.iSyncSceneID, TRUE)
|
|
|
|
// create peds
|
|
REPEAT 2 i
|
|
mdl = GET_ENTITY_MODEL(PLAYER_PED_ID())
|
|
IF (mdl <> DUMMY_MODEL_FOR_SCRIPT)
|
|
w.pedID[i] = CREATE_RANDOM_PED(GET_ENTITY_COORDS(w.objectID))
|
|
|
|
|
|
IF IS_ENTITY_OK(w.pedID[i])
|
|
SET_PED_KEEP_TASK(w.pedID[i], TRUE)
|
|
SET_PED_CONFIG_FLAG(w.pedID[i], PCF_RunFromFiresAndExplosions, FALSE)
|
|
SET_PED_CONFIG_FLAG(w.pedID[i], PCF_DisableExplosionReactions, TRUE)
|
|
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(w.pedID[i], TRUE)
|
|
SET_ENTITY_LOD_DIST(w.pedID[i], WHEEL_CAR_LOD_DIST)
|
|
|
|
iVariant = GET_WHEEL_BYSTANDER_VARIANT(iOccupiedCount, i)
|
|
sAnim = GET_WHEEL_CAR_PED_ANIM(iVariant)
|
|
IF NOT IS_STRING_NULL_OR_EMPTY(sAnim)
|
|
TASK_SYNCHRONIZED_SCENE(w.pedID[i], w.iSyncSceneID, sWheelCarAnimDict, sAnim, INSTANT_BLEND_IN, NORMAL_BLEND_OUT)
|
|
FORCE_PED_AI_AND_ANIMATION_UPDATE(w.pedID[i])
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
w.bOccupied = true
|
|
iOccupiedCount ++
|
|
ENDPROC
|
|
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Create ferris wheel
|
|
PROC CREATE_FERRIS_WHEEL()
|
|
INT i
|
|
|
|
SET_BUILDING_STATE(BUILDINGNAME_IPL_FERRIS_WHEEL, BUILDINGSTATE_DESTROYED)
|
|
|
|
wheelObjectID = CREATE_OBJECT(wheelModel, <<0,1,2>>)
|
|
SET_ENTITY_COORDS(wheelObjectID, vWheelCenter)
|
|
SET_ENTITY_ROTATION(wheelObjectID, <<fWheelRotation, 0, 0>>)
|
|
FREEZE_ENTITY_POSITION(wheelObjectID, TRUE)
|
|
SET_ENTITY_LOD_DIST(wheelObjectID, WHEEL_CAR_LOD_DIST)
|
|
|
|
IF NOT IS_AUDIO_SCENE_ACTIVE("FAIRGROUND_RIDES_FERRIS_WHALE")
|
|
START_AUDIO_SCENE("FAIRGROUND_RIDES_FERRIS_WHALE")
|
|
ENDIF
|
|
|
|
iOccupiedCount = 0
|
|
REPEAT MAX_WHEEL_CARS i
|
|
CREATE_WHEEL_CAR(wheelCar[i], i, (i = PLAYER_WHEEL_CAR))
|
|
UPDATE_WHEEL_CAR(wheelCar[i])
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Create ferris wheel
|
|
PROC UPDATE_FERRIS_WHEEL()
|
|
INT i
|
|
VECTOR v
|
|
|
|
// rotate the wheel
|
|
fWheelRotation += fWheelRotationRate * TIMESTEP()
|
|
IF (fWheelRotation >= 360.0)
|
|
fWheelRotation -= 360.0
|
|
iRevolutions ++
|
|
ENDIF
|
|
|
|
IF IS_ENTITY_OK(wheelObjectID)
|
|
SET_ENTITY_COORDS(wheelObjectID, vWheelCenter)
|
|
SET_ENTITY_ROTATION(wheelObjectID, <<-fWheelRotation - (360.0 / 16.0), 0, 0>>)
|
|
FREEZE_ENTITY_POSITION(wheelObjectID, TRUE)
|
|
ENDIF
|
|
|
|
IF IS_AUDIO_SCENE_ACTIVE("FAIRGROUND_RIDES_FERRIS_WHALE")
|
|
IF IS_ENTITY_OK(PLAYER_PED_ID())
|
|
v = GET_ENTITY_COORDS(PLAYER_PED_ID())
|
|
ENDIF
|
|
SET_AUDIO_SCENE_VARIABLE("FAIRGROUND_RIDES_FERRIS_WHALE", "HEIGHT", v.z - fWheelGroundZ)
|
|
ENDIF
|
|
|
|
REPEAT MAX_WHEEL_CARS i
|
|
UPDATE_WHEEL_CAR(wheelCar[i])
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Cleanup ferris wheel
|
|
PROC CLEANUP_FERRIS_WHEEL()
|
|
INT i
|
|
|
|
REPEAT COUNT_OF(wheelCar) i
|
|
CLEANUP_WHEEL_CAR(wheelCar[i])
|
|
ENDREPEAT
|
|
|
|
IS_ENTITY_OK(PLAYER_PED_ID())
|
|
IF IS_ENTITY_ATTACHED(PLAYER_PED_ID())
|
|
DETACH_ENTITY(PLAYER_PED_ID())
|
|
ENDIF
|
|
|
|
IF IS_AUDIO_SCENE_ACTIVE("FAIRGROUND_RIDES_FERRIS_WHALE")
|
|
STOP_AUDIO_SCENE("FAIRGROUND_RIDES_FERRIS_WHALE")
|
|
ENDIF
|
|
|
|
IF IS_AUDIO_SCENE_ACTIVE("FAIRGROUND_RIDES_FERRIS_WHALE_ALTERNATIVE_VIEW")
|
|
STOP_AUDIO_SCENE("FAIRGROUND_RIDES_FERRIS_WHALE_ALTERNATIVE_VIEW")
|
|
ENDIF
|
|
|
|
SAFE_STOP_AND_RELEASE_SOUND_ID(iSqueakSoundID)
|
|
SAFE_STOP_AND_RELEASE_SOUND_ID(iSqueakSoundID)
|
|
SAFE_STOP_AND_RELEASE_SOUND_ID(iGeneratorSoundID)
|
|
SAFE_STOP_AND_RELEASE_SOUND_ID(iRattlingSoundID)
|
|
SET_ENTITY_COORDS_GROUNDED(PLAYER_PED_ID(), <<-1658.5, -1125.5, 13.0>>)
|
|
|
|
SAFE_DELETE_OBJECT(wheelObjectID)
|
|
SET_BUILDING_STATE(BUILDINGNAME_IPL_FERRIS_WHEEL, BUILDINGSTATE_NORMAL)
|
|
ENDPROC
|
|
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
|
|
/// PURPOSE:
|
|
/// Updates the Debug Widgers
|
|
PROC UPDATE_DEBUG_WIDGETS()
|
|
IF (bRespotPlayer)
|
|
PUT_PLAYER_IN_WHEEL_CAR(wheelCar[PLAYER_WHEEL_CAR], fPlayerWheelCarAngle)
|
|
bRespotPlayer = FALSE
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
#ENDIF
|
|
|
|
//----------------------
|
|
// MAIN
|
|
//----------------------
|
|
|
|
/// PURPOSE:
|
|
/// Setups up the script
|
|
PROC SCRIPT_SETUP()
|
|
#IF IS_DEBUG_BUILD
|
|
SETUP_DEBUG_WIDGETS()
|
|
#ENDIF
|
|
|
|
// Disable player control
|
|
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE)
|
|
|
|
//SAFE_FADE_SCREEN_OUT_TO_BLACK(500, TRUE)
|
|
DISABLE_CELLPHONE(TRUE)
|
|
|
|
// Load assets (moved to before cam cut, for b*1988487)
|
|
ADD_ASSET_REQUEST_FOR_MODEL(asRequest, 0, wheelModel)
|
|
ADD_ASSET_REQUEST_FOR_MODEL(asRequest, 1, wheelCarModel)
|
|
ADD_ASSET_REQUEST_FROM_STRING(asRequest, 2, ASSET_ANIMDICT, sWheelCarAnimDict)
|
|
ADD_ASSET_REQUEST_FROM_STRING(asRequest, 3, ASSET_AUDIOBANK, "SCRIPT\\FERRIS_WHALE_01")
|
|
ADD_ASSET_REQUEST_FROM_STRING(asRequest, 4, ASSET_AUDIOBANK, "SCRIPT\\FERRIS_WHALE_02")
|
|
|
|
CPRINTLN(DEBUG_MISSION, "[BIGWHEEL] - ASSETS REQUEST START ON - ", GET_FRAME_COUNT())
|
|
WHILE NOT HAVE_ASSET_REQUESTS_LOADED(asRequest)
|
|
WAIT(0)
|
|
ENDWHILE
|
|
|
|
CPRINTLN(DEBUG_MISSION, "[BIGWHEEL] - ASSETS REQUEST COMPLETE ON - ", GET_FRAME_COUNT())
|
|
|
|
// Start cutscene
|
|
RC_START_CUTSCENE_MODE(<<0, 0, 0>>)
|
|
|
|
CLEAR_AREA_OF_PROJECTILES(vWheelCenter, 60.0)
|
|
STOP_FIRE_IN_RANGE(vWheelCenter, 60.0)
|
|
|
|
IF NOT DOES_CAM_EXIST(initialCamera)
|
|
initialCamera = CREATE_CAM_WITH_PARAMS("DEFAULT_SCRIPTED_CAMERA", <<-1659.4457, -1120.8329, 12.9255>>, <<-3.6667, 0.0000, 56.0716>>, 50.1098, TRUE)
|
|
SET_CAM_PARAMS(initialCamera, <<-1659.4457, -1120.8329, 12.9255>>, <<-3.6667, 0.0000, 56.0716>>, 50.1098)
|
|
SET_CAM_ACTIVE(initialCamera, TRUE)
|
|
SET_CAM_PARAMS(initialCamera, <<-1659.1097, -1120.7518, 12.9489>>, <<-5.5053, -0.0000, 56.0716>>, 50.1098, 7000)
|
|
CPRINTLN(DEBUG_MISSION, "[BIGWHEEL] - INITIAL CAMERA ON - ", GET_FRAME_COUNT())
|
|
RENDER_SCRIPT_CAMS(TRUE, FALSE)
|
|
iCameraTimer = GET_GAME_TIMER() + 6000
|
|
ENDIF
|
|
|
|
IF IS_ENTITY_OK(GET_PLAYERS_LAST_VEHICLE())
|
|
CPRINTLN(DEBUG_AMBIENT, "[ROLLERCOASTER] - RESOLVE VEHICLE")
|
|
IF IS_ENTITY_SMALLER_THAN_MODEL(GET_PLAYERS_LAST_VEHICLE(), BAGGER)
|
|
RESOLVE_VEHICLES_INSIDE_ANGLED_AREA(<<-1663.739624,-1111.471558,11.591353>>, <<-1663.512329,-1139.947876,24.017221>>, 16.500000, <<-1673.8156, -1133.7450, 12.0226>>, 92.5556)
|
|
CPRINTLN(DEBUG_AMBIENT, "[ROLLERCOASTER] - RESOLVE VEHICLE - BAGGER SMALLER")
|
|
ELIF IS_ENTITY_SMALLER_THAN_MODEL(GET_PLAYERS_LAST_VEHICLE(), SANDKING)
|
|
RESOLVE_VEHICLES_INSIDE_ANGLED_AREA(<<-1663.739624,-1111.471558,11.591353>>, <<-1663.512329,-1139.947876,24.017221>>, 16.500000, <<-1684.3600, -1129.6064, 12.1347>>, 105.6507)
|
|
CPRINTLN(DEBUG_AMBIENT, "[ROLLERCOASTER] - RESOLVE VEHICLE - SANDKING SMALLER")
|
|
ELSE
|
|
RESOLVE_VEHICLES_INSIDE_ANGLED_AREA(<<-1663.739624,-1111.471558,11.591353>>, <<-1663.512329,-1139.947876,24.017221>>, 16.500000, <<-1570.8074, -1022.1135, 12.0180>>, 215.3015)
|
|
CPRINTLN(DEBUG_AMBIENT, "[ROLLERCOASTER] - RESOLVE VEHICLE - SILLY BIG VEHICLE")
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF IS_ENTITY_OK(PLAYER_PED_ID())
|
|
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
|
|
TASK_LEAVE_ANY_VEHICLE(PLAYER_PED_ID())
|
|
CPRINTLN(DEBUG_AMBIENT, "[ROLLERCOASTER] - FORCE PEDS OFF VEHICLE")
|
|
ENDIF
|
|
SET_ENTITY_VISIBLE(PLAYER_PED_ID(), FALSE)
|
|
SET_ENTITY_COORDS_GROUNDED(PLAYER_PED_ID(), <<-1668.4982, -1125.6273, 12.0699>>)
|
|
SET_ENTITY_HEADING(PLAYER_PED_ID(), 44.1132)
|
|
ENDIF
|
|
|
|
SET_BUILDING_STATE(BUILDINGNAME_IPL_FERRIS_WHEEL, BUILDINGSTATE_DESTROYED)
|
|
|
|
// NOTE: This is where assets were requested before changes for b*1988487, so if there's any problems, might need to put them back here.
|
|
|
|
SETUP_CAMERA_STRUCT(outerCamera, <<-1703.8540, -1082.2223, 42.0060>>, <<-8.3096, 0.0000, -111.8213>>)
|
|
|
|
// NOTE: This is where assets were waited for before changes for b*1988487, so if there's any problems, might need to put them back here.
|
|
|
|
CPRINTLN(DEBUG_MISSION, "[BIGWHEEL] - ASSETS REQUEST COMPLETE ON - ", GET_FRAME_COUNT())
|
|
//RESOLVE_VEHICLES_INSIDE_ANGLED_AREA(<<-1664.351929,-1143.552124,11.862814>>, <<-1663.885498,-1109.183228,23.357935>>, 16.000000, <<-1652.3408, -1121.9631, 12.0303>>, 320.2413)
|
|
|
|
|
|
|
|
CREATE_FERRIS_WHEEL()
|
|
IF IS_ENTITY_OK(PLAYER_PED_ID())
|
|
SET_ENTITY_VISIBLE(PLAYER_PED_ID(), TRUE)
|
|
ENDIF
|
|
|
|
WHILE (GET_GAME_TIMER() < iCameraTimer)
|
|
WAIT(0)
|
|
ENDWHILE
|
|
CPRINTLN(DEBUG_MISSION, "[BIGWHEEL] - WHEEL CREATED ON - ", GET_FRAME_COUNT())
|
|
|
|
WAIT(0)
|
|
|
|
CPRINTLN(DEBUG_MISSION, "[BIGWHEEL] - SWITCHING CAMERA TO PROPER MODE - ", GET_FRAME_COUNT())
|
|
IF GET_CAM_VIEW_MODE_FOR_CONTEXT(CAM_VIEW_MODE_CONTEXT_ON_FOOT) = CAM_VIEW_MODE_FIRST_PERSON
|
|
SWITCH_TO_FIRST_PERSON_MODE(FALSE)
|
|
ELSE
|
|
SWITCH_TO_EXTERNAL_MODE()
|
|
ENDIF
|
|
//WAIT(125)
|
|
//DO_SCREEN_FADE_IN(500)
|
|
PRINT_HELP("FGND_SWTCHCAM")
|
|
|
|
iGeneratorSoundID = GET_SOUND_ID()
|
|
PLAY_SOUND_FROM_ENTITY(iGeneratorSoundID, "GENERATOR", wheelObjectID, "THE_FERRIS_WHALE_SOUNDSET")
|
|
|
|
iSlowSqueakSoundID = GET_SOUND_ID()
|
|
PLAY_SOUND_FROM_ENTITY(iSlowSqueakSoundID, "SLOW_SQUEAK", wheelObjectID, "THE_FERRIS_WHALE_SOUNDSET")
|
|
|
|
iSqueakSoundID = GET_SOUND_ID()
|
|
PLAY_SOUND_FROM_ENTITY(iSqueakSoundID, "SLOW_SQUEAK", wheelCar[PLAYER_WHEEL_CAR].objectID, "THE_FERRIS_WHALE_SOUNDSET")
|
|
|
|
iRattlingSoundID = GET_SOUND_ID()
|
|
PLAY_SOUND_FROM_ENTITY(iRattlingSoundID, "CARRIAGE", wheelCar[PLAYER_WHEEL_CAR].objectID, "THE_FERRIS_WHALE_SOUNDSET")
|
|
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Cleanups Script and terminates thread - this should be the last function called
|
|
PROC SCRIPT_CLEANUP(BOOL bNice = FALSE)
|
|
|
|
IF (bNice)
|
|
CLEAR_HELP()
|
|
SAFE_FADE_SCREEN_OUT_TO_BLACK()
|
|
CLEAR_BIT(g_iRepeatPlayBits, ENUM_TO_INT(RPB_FROZEN_ON_FERRIS_WHEEL))
|
|
ENDIF
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
CLEANUP_DEBUG_WIDGETS()
|
|
#ENDIF
|
|
|
|
|
|
CLEANUP_FERRIS_WHEEL()
|
|
RC_END_CUTSCENE_MODE()
|
|
DISABLE_CELLPHONE(FALSE)
|
|
SHUTDOWN_CAMERA(cameraID)
|
|
SHUTDOWN_CAMERA(initialCamera)
|
|
CLEAR_FIRST_PERSON_CAMERA(fpsCam)
|
|
|
|
IF IS_AUDIO_SCENE_ACTIVE("FAIRGROUND_RIDES_FERRIS_WHALE")
|
|
STOP_AUDIO_SCENE("FAIRGROUND_RIDES_FERRIS_WHALE")
|
|
ENDIF
|
|
|
|
IS_ENTITY_OK(PLAYER_PED_ID())
|
|
|
|
IF IS_ENTITY_ATTACHED(PLAYER_PED_ID())
|
|
DETACH_ENTITY(PLAYER_PED_ID())
|
|
ENDIF
|
|
|
|
IF IS_ENTITY_OK(PLAYER_PED_ID())
|
|
SET_ENTITY_COORDS_GROUNDED(PLAYER_PED_ID(), <<-1668.4982, -1125.6273, 12.0699>>)
|
|
SET_ENTITY_HEADING(PLAYER_PED_ID(), 44.1132)
|
|
ENDIF
|
|
|
|
SET_ENTITY_VISIBLE(PLAYER_PED_ID(), TRUE)
|
|
|
|
IF (bNice)
|
|
CLEAR_HELP()
|
|
SET_GAMEPLAY_CAM_RELATIVE_HEADING()
|
|
SET_GAMEPLAY_CAM_RELATIVE_PITCH()
|
|
FORCE_PED_MOTION_STATE(PLAYER_PED_ID(), MS_ON_FOOT_WALK)
|
|
SIMULATE_PLAYER_INPUT_GAIT(PLAYER_ID(), PEDMOVE_WALK)
|
|
WAIT(125)
|
|
SAFE_FADE_SCREEN_IN_FROM_BLACK(500, FALSE)
|
|
CHARGE_CURRENT_PLAYER_PED_ACCOUNT_BALANCE(COST_BIGWHEEL)
|
|
ENDIF
|
|
|
|
UNLOAD_REQUESTED_ASSETS(asRequest)
|
|
REGISTER_SCRIPT_IN_COMPLETION_PERCENTAGE_TOTAL(CP_FAIRG)
|
|
REACTIVATE_NAMED_WORLD_BRAINS_WAITING_TILL_OUT_OF_RANGE("fairgroundHub")
|
|
TERMINATE_THIS_THREAD()
|
|
ENDPROC
|
|
|
|
//----------------------
|
|
// MAIN SCRIPT
|
|
//----------------------
|
|
SCRIPT
|
|
|
|
// Setup callback when player is killed, arrested or goes to multiplayer
|
|
IF HAS_FORCE_CLEANUP_OCCURRED(DEFAULT_FORCE_CLEANUP_FLAGS | FORCE_CLEANUP_FLAG_REPEAT_PLAY)
|
|
SCRIPT_CLEANUP()
|
|
ENDIF
|
|
|
|
CPRINTLN(DEBUG_MISSION, "BIGWHEEL SETUP - 102")
|
|
SET_MISSION_FLAG(TRUE)
|
|
SCRIPT_SETUP()
|
|
SET_BIT(g_iRepeatPlayBits, ENUM_TO_INT(RPB_FROZEN_ON_FERRIS_WHEEL))
|
|
|
|
// we load the props here
|
|
//SET_DEBUG_LINES_AND_SPHERES_DRAWING_ACTIVE(TRUE)
|
|
|
|
WHILE (TRUE)
|
|
IS_ENTITY_OK(PLAYER_PED_ID())
|
|
RC_DISABLE_CONTROL_ACTIONS_FOR_LEAD_IN()
|
|
DISABLE_SELECTOR_THIS_FRAME()
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
UPDATE_DEBUG_WIDGETS()
|
|
#ENDIF
|
|
|
|
UPDATE_FERRIS_WHEEL()
|
|
|
|
// handle quitting
|
|
IF (bSkipped = FALSE)
|
|
IF IS_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, INPUT_SKIP_CUTSCENE)
|
|
OR IS_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, INPUT_CONTEXT)
|
|
SAFE_FADE_SCREEN_OUT_TO_BLACK(500, FALSE)
|
|
bSkipped = TRUE
|
|
ENDIF
|
|
ELIF IS_SCREEN_FADED_OUT()
|
|
SCRIPT_CLEANUP(TRUE)
|
|
ENDIF
|
|
|
|
IF (iRevolutions >= 1)
|
|
SCRIPT_CLEANUP(TRUE)
|
|
ENDIF
|
|
|
|
IF IS_PLAYER_CONTROL_ON(PLAYER_ID())
|
|
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE)
|
|
ENDIF
|
|
|
|
IF GET_SCRIPT_TASK_STATUS(PLAYER_PED_ID(), SCRIPT_TASK_SYNCHRONIZED_SCENE) <> PERFORMING_TASK
|
|
CPRINTLN(DEBUG_AMBIENT, "[BIGWHEEL] PLAYER ISN'T DOING WHEEL STUFF - RESET HIM")
|
|
PUT_PLAYER_IN_WHEEL_CAR(wheelCar[PLAYER_WHEEL_CAR])
|
|
ENDIF
|
|
|
|
// camera malarky
|
|
IF IS_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, INPUT_SCRIPT_SELECT)
|
|
IF (bFPSMode = FALSE)
|
|
SWITCH_TO_FIRST_PERSON_MODE()
|
|
ELSE
|
|
SWITCH_TO_EXTERNAL_MODE()
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF (bFPSMode = TRUE)
|
|
|
|
IF (bStandardCamera = FALSE)
|
|
UPDATE_BASIC_CAMERA(fpsTestCam)
|
|
ELSE
|
|
UPDATE_FIRST_PERSON_CAMERA(fpsCam)
|
|
SET_CAM_ROT(fpsCam.theCam, GET_ENTITY_ROTATION(PLAYER_PED_ID()) + fpsCam.vCamRotOffsetCurrent)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
IF (bQuit)
|
|
SCRIPT_CLEANUP()
|
|
ENDIF
|
|
#ENDIF
|
|
|
|
WAIT(0)
|
|
ENDWHILE
|
|
ENDSCRIPT
|
|
|
|
|
|
|