Files
gtav-src/script/dev_ng/singleplayer/scripts/temp/charAnimTest.sc
T
2025-09-29 00:52:08 +02:00

1219 lines
36 KiB
Python
Executable File

// Includes
USING "rage_builtins.sch"
USING "globals.sch"
USING "commands_camera.sch"
USING "commands_pad.sch"
USING "commands_misc.sch"
USING "commands_script.sch"
USING "commands_streaming.sch"
USING "script_player.sch"
// *****************************************************************************************
// *****************************************************************************************
// *****************************************************************************************
//
// MISSION NAME : charAnimTest.sc
// AUTHOR :
// DESCRIPTION : Script tool to test character anims at specific phases.
//
// *****************************************************************************************
// *****************************************************************************************
// *****************************************************************************************
#IF IS_DEBUG_BUILD
// -----------------------------------------------------------------------------------------------------------
// Variable declaration
// -----------------------------------------------------------------------------------------------------------
// Includes
USING "charAnimTest.sch"
// Constants
CONST_INT MODEL_TIMEOUT 3000
// Anim widgets
WIDGET_GROUP_ID widgetGroup
BOOL bUseIdleAnims = TRUE
FLOAT fIdleTime = 5.0
FLOAT fIdleShot = 2.5
INT iIdleTimer = 0
TEXT_WIDGET_ID widgetAnimDict
TEXT_WIDGET_ID widgetAnimName
STRING sAnimDict = ""
STRING sAnimName = ""
FLOAT fAnimPhase = 0.0
FLOAT fPhaseMin = 0.0
FLOAT fPhaseMax = 1.0
// Prop widgets
OBJECT_INDEX propIndex
INT iPropModel
INT iLastModel
INT iPropAttachBone
VECTOR vPropOffset = <<0,0,0>>
VECTOR vPropRot = <<0,0,0>>
BOOL bUseProp = FALSE
BOOL bLiveUpdate = FALSE
// Screenshot widgets
TEXT_WIDGET_ID widgetFolderName
TEXT_WIDGET_ID widgetShotName
STRING sFolderName = "X:/GTA5/"
STRING sShotName = "testShot"
INT iScreenShot = 0
BOOL bScreenShot = FALSE
BOOL bUseScreenCount = TRUE
BOOL bUseModelName = TRUE
// Ped widgets
BOOL bToggleAllPeds = FALSE
BOOL bToggleAmbient = FALSE
BOOL bToggleGang = FALSE
BOOL bToggleUnique = FALSE
BOOL bToggledOn[4]
BOOL bShowAFM = FALSE
BOOL bShowAFO = FALSE
BOOL bShowAFY = FALSE
BOOL bShowAMM = FALSE
BOOL bShowAMO = FALSE
BOOL bShowAMY = FALSE
BOOL bShowGFY = FALSE
BOOL bShowGMM = FALSE
BOOL bShowGMY = FALSE
BOOL bShowUFM = FALSE
BOOL bShowUFO = FALSE
BOOL bShowUFY = FALSE
BOOL bShowUMM = FALSE
BOOL bShowUMO = FALSE
BOOL bShowUMY = FALSE
// Camera widgets
CAMERA_INDEX ciTestCamera
VECTOR vCameraPos = <<2013.4475, 2851.7219, 50.9609>>
VECTOR vCameraRot = <<-13.1265, -0.0000, 173.5950>>
FLOAT fCameraFOV = 50.0000
BOOL bGetCurrentCam = FALSE
// Control variables
BOOL bTestSceneOn = FALSE
BOOL bFullTestOn = FALSE
BOOL bTestActive = FALSE
// Character index
PED_INDEX piCharacter
// -----------------------------------------------------------------------------------------------------------
// Script Cleanup
// -----------------------------------------------------------------------------------------------------------
/// PURPOSE: Removes anim dictionary
PROC UNLOAD_ANIM_DICT()
IF NOT IS_STRING_NULL_OR_EMPTY(sAnimDict)
PRINTLN("charAnimTest: Unloaded animation dictionary...")
REMOVE_ANIM_DICT(sAnimDict)
ENDIF
ENDPROC
/// PURPOSE: Toggle specific camera for test
PROC TOGGLE_TEST_CAMERA(BOOL bOn, BOOL bResetCam=TRUE)
IF bOn
IF NOT DOES_CAM_EXIST(ciTestCamera)
PRINTLN("charAnimTest: Creating and setting camera...")
ciTestCamera = CREATE_CAMERA_WITH_PARAMS(CAMTYPE_SCRIPTED, vCameraPos, vCameraRot, fCameraFOV)
SET_CAM_ACTIVE(ciTestCamera, TRUE)
RENDER_SCRIPT_CAMS(TRUE, FALSE, 0)
ENDIF
ELSE
IF DOES_CAM_EXIST(ciTestCamera)
IF IS_CAM_ACTIVE(ciTestCamera)
SET_CAM_ACTIVE(ciTestCamera, FALSE)
ENDIF
DESTROY_CAM(ciTestCamera)
ENDIF
// Set camera behind player
IF bResetCam
PRINTLN("charAnimTest: Restoring normal camera...")
RENDER_SCRIPT_CAMS(FALSE, FALSE)
SET_GAMEPLAY_CAM_RELATIVE_HEADING()
ENDIF
ENDIF
ENDPROC
/// PURPOSE: Deletes widget box
PROC CLEANUP_TEST()
// Remove animation dictionary
UNLOAD_ANIM_DICT()
// Reset camera
TOGGLE_TEST_CAMERA(FALSE)
// Remove prop
IF DOES_ENTITY_EXIST(propIndex)
DELETE_OBJECT(propIndex)
ENDIF
// Remove ped
IF DOES_ENTITY_EXIST(piCharacter)
DELETE_PED(piCharacter)
ENDIF
// Cleanup widgets
IF DOES_WIDGET_GROUP_EXIST(widgetGroup)
DELETE_WIDGET_GROUP(widgetGroup)
ENDIF
ENDPROC
#ENDIF
/// PURPOSE: Removes any active models, anims and resets camera
PROC SCRIPT_CLEANUP()
#IF IS_DEBUG_BUILD PRINTLN("charAnimTest: Cleanup") #ENDIF
#IF IS_DEBUG_BUILD CLEANUP_TEST() #ENDIF
TERMINATE_THIS_THREAD()
ENDPROC
#IF IS_DEBUG_BUILD
/// PURPOSE: Checks for player pressing debug key to cancel script
PROC CHECK_DEBUG_CLEANUP()
IF (IS_KEYBOARD_KEY_JUST_PRESSED(KEY_S))
OR (IS_KEYBOARD_KEY_JUST_PRESSED(KEY_F))
OR (IS_KEYBOARD_KEY_JUST_PRESSED(KEY_J))
SCRIPT_CLEANUP()
ENDIF
ENDPROC
// -----------------------------------------------------------------------------------------------------------
// Initialisation
// -----------------------------------------------------------------------------------------------------------
/// PURPOSE: Initialise widgets with initial values
PROC SETUP_WIDGETS()
// Setup widget
widgetGroup = START_WIDGET_GROUP("Character Anim Test")
// Animation related widget
START_WIDGET_GROUP("Animation Settings")
// Idle animations
ADD_WIDGET_BOOL("Use Idle Animations", bUseIdleAnims)
ADD_WIDGET_FLOAT_SLIDER("Idle Time", fIdleTime, 0, 10, 0.1)
ADD_WIDGET_FLOAT_SLIDER("Screenshot Time", fIdleShot, 0, 10, 0.1)
// Specified animations
widgetAnimDict = ADD_TEXT_WIDGET("Animation Dictionary")
widgetAnimName = ADD_TEXT_WIDGET("Animation Name")
ADD_WIDGET_FLOAT_SLIDER("Start Phase", fPhaseMin, 0, 1, 0.01)
ADD_WIDGET_FLOAT_SLIDER("Screenshot Phase", fAnimPhase, 0, 1, 0.01)
ADD_WIDGET_FLOAT_SLIDER("End Phase", fPhaseMax, 0, 1, 0.01)
SET_CONTENTS_OF_TEXT_WIDGET(widgetAnimDict, sAnimDict)
SET_CONTENTS_OF_TEXT_WIDGET(widgetAnimName, sAnimName)
STOP_WIDGET_GROUP()
// Prop widget
START_WIDGET_GROUP("Prop Settings")
ADD_WIDGET_BOOL("Use Prop", bUseProp)
ADD_WIDGET_BOOL("Test Scene Update", bLiveUpdate)
// Prop list
START_NEW_WIDGET_COMBO()
ADD_TO_WIDGET_COMBO("P_AMB_COFFEECUP_01")
ADD_TO_WIDGET_COMBO("P_CS_JOINT_01")
ADD_TO_WIDGET_COMBO("PROP_CS_BEER_BOT_01")
ADD_TO_WIDGET_COMBO("PROP_CS_BEER_BOT_40OZ")
ADD_TO_WIDGET_COMBO("PROP_CS_CIGGY_01")
ADD_TO_WIDGET_COMBO("PROP_PHONE_ING")
ADD_TO_WIDGET_COMBO("PROP_PLASTIC_CUP_02")
STOP_WIDGET_COMBO("Prop Model", iPropModel)
// Ped bone attachment
START_NEW_WIDGET_COMBO()
ADD_TO_WIDGET_COMBO("Left Hand")
ADD_TO_WIDGET_COMBO("Right Hand")
STOP_WIDGET_COMBO("Prop Attachment", iPropAttachBone)
// Offset and Rotation
ADD_WIDGET_FLOAT_SLIDER("Offset X", vPropOffset.x, -1, 1, 0.01)
ADD_WIDGET_FLOAT_SLIDER("Offset Y", vPropOffset.y, -1, 1, 0.01)
ADD_WIDGET_FLOAT_SLIDER("Offset Z", vPropOffset.z, -1, 1, 0.01)
ADD_WIDGET_FLOAT_SLIDER("Rot X", vPropRot.x, -360, 360, 1)
ADD_WIDGET_FLOAT_SLIDER("Rot Y", vPropRot.y, -360, 360, 1)
ADD_WIDGET_FLOAT_SLIDER("Rot Z", vPropRot.z, -360, 360, 1)
STOP_WIDGET_GROUP()
// Screenshot settings
START_WIDGET_GROUP("Screenshot Settings")
widgetFolderName = ADD_TEXT_WIDGET("Folder Name")
widgetShotName = ADD_TEXT_WIDGET("Screenshot Name")
SET_CONTENTS_OF_TEXT_WIDGET(widgetFolderName, sFolderName)
SET_CONTENTS_OF_TEXT_WIDGET(widgetShotName, sShotName)
// Removed on request to simplify as this behaviour is wanted by default
// ADD_WIDGET_BOOL("Use Screenshot Numbering", bUseScreenCount)
// ADD_WIDGET_BOOL("Include Model Name", bUseModelName)
STOP_WIDGET_GROUP()
// Ped settings
START_WIDGET_GROUP("Ped Models")
ADD_WIDGET_BOOL("Toggle All Peds (On/Off)", bToggleAllPeds)
ADD_WIDGET_STRING("Ambient Peds")
ADD_WIDGET_BOOL("Toggle Ambient (On/Off)", bToggleAmbient)
ADD_WIDGET_BOOL("A_F_M", bShowAFM)
ADD_WIDGET_BOOL("A_F_O", bShowAFO)
ADD_WIDGET_BOOL("A_F_Y", bShowAFY)
ADD_WIDGET_BOOL("A_M_M", bShowAMM)
ADD_WIDGET_BOOL("A_M_O", bShowAMO)
ADD_WIDGET_BOOL("A_M_Y", bShowAMY)
ADD_WIDGET_STRING("Gang Peds")
ADD_WIDGET_BOOL("Toggle Gang (On/Off)", bToggleGang)
ADD_WIDGET_BOOL("G_F_Y", bShowGFY)
ADD_WIDGET_BOOL("G_M_M", bShowGMM)
ADD_WIDGET_BOOL("G_M_O", bShowGMY)
ADD_WIDGET_STRING("Unique Peds")
ADD_WIDGET_BOOL("Toggle Unique (On/Off)", bToggleUnique)
ADD_WIDGET_BOOL("U_F_M", bShowUFM)
ADD_WIDGET_BOOL("U_F_O", bShowUFO)
ADD_WIDGET_BOOL("U_F_Y", bShowUFY)
ADD_WIDGET_BOOL("U_M_M", bShowUMM)
ADD_WIDGET_BOOL("U_M_O", bShowUMO)
ADD_WIDGET_BOOL("U_M_Y", bShowUMY)
STOP_WIDGET_GROUP()
// Camera related settings
START_WIDGET_GROUP("Camera Settings")
ADD_WIDGET_FLOAT_SLIDER("Cam X", vCameraPos.x, -5000, 5000, 1)
ADD_WIDGET_FLOAT_SLIDER("Cam Y", vCameraPos.y, -5000, 5000, 1)
ADD_WIDGET_FLOAT_SLIDER("Cam Z", vCameraPos.z, -5000, 5000, 1)
ADD_WIDGET_FLOAT_SLIDER("Rot X", vCameraRot.x, -5000, 5000, 1)
ADD_WIDGET_FLOAT_SLIDER("Rot Y", vCameraRot.y, -5000, 5000, 1)
ADD_WIDGET_FLOAT_SLIDER("Rot Z", vCameraRot.z, -5000, 5000, 1)
ADD_WIDGET_FLOAT_SLIDER("F.O.V", fCameraFOV, -360, 360, 1)
ADD_WIDGET_BOOL("Update with Current Debug Cam", bGetCurrentCam)
STOP_WIDGET_GROUP()
// START!!!
ADD_WIDGET_STRING("CHARACTER ANIMATION TEST")
ADD_WIDGET_BOOL("Start Test Scene", bTestSceneOn)
ADD_WIDGET_BOOL("Start Full Run", bFullTestOn)
STOP_WIDGET_GROUP()
// Initialise ped toggles
INT i
FOR i = 0 TO 3
bToggledOn[i] = FALSE
ENDFOR
// Load model enums into array
INIT_MODEL_ENUMS()
INIT_PROP_ENUMS()
ENDPROC
/// PURPOSE: Loads animation dictionary into memory
PROC LOAD_ANIM_DICT()
IF NOT bUseIdleAnims
IF NOT IS_STRING_NULL_OR_EMPTY(sAnimDict)
AND NOT IS_STRING_NULL_OR_EMPTY(sAnimName)
PRINTLN("charAnimTest: Requesting animation dictionary: ", sAnimDict)
REQUEST_ANIM_DICT(sAnimDict)
WHILE NOT HAS_ANIM_DICT_LOADED(sAnimDict)
WAIT(0)
ENDWHILE
PRINTLN("charAnimTest: Loaded animation dictionary...")
ELSE
PRINTLN("charAnimTest: No dictionary or anim name specified...")
ENDIF
ELSE
PRINTLN("charAnimTest: No need to load animations...")
ENDIF
ENDPROC
// -----------------------------------------------------------------------------------------------------------
// Character functions
// -----------------------------------------------------------------------------------------------------------
/// PURPOSE: Has this ped model been selected in the RAG widget?
FUNC BOOL HAS_CHARACTER_MODEL_BEEN_SELECTED(INT iIndex)
// Ambient peds
IF bShowAFM IF (iIndex >= A_F_M_START AND iIndex <= A_F_M_END) RETURN TRUE ENDIF ENDIF
IF bShowAFO IF (iIndex >= A_F_O_START AND iIndex <= A_F_O_END) RETURN TRUE ENDIF ENDIF
IF bShowAFY IF (iIndex >= A_F_Y_START AND iIndex <= A_F_Y_END) RETURN TRUE ENDIF ENDIF
IF bShowAMM IF (iIndex >= A_M_M_START AND iIndex <= A_M_M_END) RETURN TRUE ENDIF ENDIF
IF bShowAMO IF (iIndex >= A_M_O_START AND iIndex <= A_M_O_END) RETURN TRUE ENDIF ENDIF
IF bShowAMY IF (iIndex >= A_M_Y_START AND iIndex <= A_M_Y_END) RETURN TRUE ENDIF ENDIF
// Gang peds
IF bShowGFY IF (iIndex >= G_F_Y_START AND iIndex <= G_F_Y_END) RETURN TRUE ENDIF ENDIF
IF bShowGMM IF (iIndex >= G_M_M_START AND iIndex <= G_M_M_END) RETURN TRUE ENDIF ENDIF
IF bShowGMY IF (iIndex >= G_M_Y_START AND iIndex <= G_M_Y_END) RETURN TRUE ENDIF ENDIF
// Unique peds
IF bShowUFM IF (iIndex >= U_F_M_START AND iIndex <= U_F_M_END) RETURN TRUE ENDIF ENDIF
IF bShowUFO IF (iIndex >= U_F_O_START AND iIndex <= U_F_O_END) RETURN TRUE ENDIF ENDIF
IF bShowUFY IF (iIndex >= U_F_Y_START AND iIndex <= U_F_Y_END) RETURN TRUE ENDIF ENDIF
IF bShowUMM IF (iIndex >= U_M_M_START AND iIndex <= U_M_M_END) RETURN TRUE ENDIF ENDIF
IF bShowUMO IF (iIndex >= U_M_O_START AND iIndex <= U_M_O_END) RETURN TRUE ENDIF ENDIF
IF bShowUMY IF (iIndex >= U_M_Y_START AND iIndex <= U_M_Y_END) RETURN TRUE ENDIF ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE: Create character for anim test
FUNC BOOL CREATE_CHARACTER(INT iIndex, BOOL bOn)
IF bOn
// Locals
MODEL_NAMES thisModel = DUMMY_MODEL_FOR_SCRIPT
INT iTimeOut = GET_GAME_TIMER() + MODEL_TIMEOUT
// Set model based on index or test scene model
IF bTestSceneOn = TRUE AND bFullTestOn = FALSE
thisModel = A_M_Y_BEACH_01
ELSE
thisModel = eModelName[iIndex]
ENDIF
PRINTLN("charAnimTest: Requesting ped model...")
REQUEST_MODEL(thisModel)
WHILE NOT HAS_MODEL_LOADED(thisModel)
// Have we taken too long to load model (e.g. missing from datafile)
IF GET_GAME_TIMER() > iTimeOut
PRINTLN("charAnimTest: Timeout on model load for ", GET_MODEL_NAME_FOR_DEBUG(thisModel))
RETURN FALSE
ENDIF
WAIT(0)
ENDWHILE
IF bUseProp
PRINTLN("charAnimTest: Requesting prop model...")
REQUEST_MODEL(ePropName[iPropModel])
WHILE NOT HAS_MODEL_LOADED(ePropName[iPropModel])
// Have we taken too long to load prop...
IF GET_GAME_TIMER() > iTimeOut
PRINTLN("charAnimTest: Timeout on model load for ", GET_MODEL_NAME_FOR_DEBUG(ePropName[iPropModel]))
RETURN FALSE
ENDIF
WAIT(0)
ENDWHILE
// Store this so we know if it has been altered for Live Update...
iLastModel = iPropModel
ENDIF
// Get ground coords
FLOAT fZ
GET_GROUND_Z_FOR_3D_COORD(<<2013.12, 2848.46, 50.25>>, fZ)
PRINTLN("charAnimTest: Creating ped model: ", GET_MODEL_NAME_FOR_DEBUG(thisModel))
WHILE NOT DOES_ENTITY_EXIST(piCharacter)
piCharacter = CREATE_PED(PEDTYPE_MISSION, thisModel, <<2013.12, 2848.46, fZ>>, -23.49, FALSE, FALSE)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(piCharacter, TRUE)
ENDWHILE
IF bUseProp
PRINTLN("charAnimTest: Creating prop model: ", GET_MODEL_NAME_FOR_DEBUG(ePropName[iPropModel]))
IF DOES_ENTITY_EXIST(piCharacter)
propIndex = CREATE_OBJECT(ePropName[iPropModel], GET_ENTITY_COORDS(piCharacter))
IF (iPropAttachBone = 0)
ATTACH_ENTITY_TO_ENTITY(propIndex, piCharacter, GET_PED_BONE_INDEX(piCharacter, BONETAG_PH_L_HAND), vPropOffset, vPropRot)
ELSE
ATTACH_ENTITY_TO_ENTITY(propIndex, piCharacter, GET_PED_BONE_INDEX(piCharacter, BONETAG_PH_R_HAND), vPropOffset, vPropRot)
ENDIF
ELSE
PRINTLN("charAnimTest: Character didn't exist - unable to create and attach prop... ")
ENDIF
PRINTLN("charAnimTest: Prop created... ")
SET_MODEL_AS_NO_LONGER_NEEDED(ePropName[iPropModel])
ENDIF
PRINTLN("charAnimTest: Ped created...")
SET_MODEL_AS_NO_LONGER_NEEDED(thisModel)
RETURN TRUE
ELSE
PRINTLN("charAnimTest: Cleaning up ped...")
IF DOES_ENTITY_EXIST(propIndex)
DELETE_OBJECT(propIndex)
ENDIF
IF DOES_ENTITY_EXIST(piCharacter)
DELETE_PED(piCharacter)
ENDIF
RETURN TRUE
ENDIF
ENDFUNC
/// PURPOSE: Play animation on a specified ped
PROC PLAY_ANIM_ON_CHARACTER()
IF DOES_ENTITY_EXIST(piCharacter)
AND NOT IS_ENTITY_DEAD(piCharacter)
IF bUseIdleAnims
PRINTLN("charAnimTest: Playing idle animation on ped...")
bScreenShot = FALSE
ELSE
IF NOT IS_STRING_NULL_OR_EMPTY(sAnimDict)
AND NOT IS_STRING_NULL_OR_EMPTY(sAnimName)
IF HAS_ANIM_DICT_LOADED(sAnimDict)
PRINTLN("charAnimTest: Playing animation on ped...")
IF bFullTestOn
TASK_PLAY_ANIM(piCharacter, sAnimDict, sAnimName, INSTANT_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_DEFAULT, fPhaseMin)
ELSE
TASK_PLAY_ANIM(piCharacter, sAnimDict, sAnimName, NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_LOOPING)
ENDIF
bScreenShot = FALSE
ELSE
PRINTLN("charAnimTest: Specified animation dictionary isn't loaded...")
ENDIF
ELSE
PRINTLN("charAnimTest: Animation and/or dictionary haven't been defined...")
ENDIF
ENDIF
ELSE
PRINTLN("charAnimTest: Ped isn't valid or dead when attempting to play animation...")
ENDIF
ENDPROC
/// PURPOSE: Waits for animation to play on specified ped
FUNC BOOL HAS_ANIM_STARTED_ON_CHARACTER()
IF DOES_ENTITY_EXIST(piCharacter)
AND NOT IS_ENTITY_DEAD(piCharacter)
IF bUseIdleAnims
PRINTLN("charAnimTest: Ped started idle animation...")
iIdleTimer = GET_GAME_TIMER()
RETURN TRUE
ENDIF
IF ((GET_SCRIPT_TASK_STATUS(piCharacter, SCRIPT_TASK_PLAY_ANIM) = PERFORMING_TASK)
OR (GET_SCRIPT_TASK_STATUS(piCharacter, SCRIPT_TASK_PLAY_ANIM) = WAITING_TO_START_TASK))
PRINTLN("charAnimTest: Ped started animation...")
RETURN TRUE
ELSE
RETURN FALSE
ENDIF
ELSE
PRINTLN("charAnimTest: Ped no longer valid or dead...")
RETURN FALSE
ENDIF
ENDFUNC
// -----------------------------------------------------------------------------------------------------------
// Screenshot functions
// -----------------------------------------------------------------------------------------------------------
/// PURPOSE: Build screenshot name from model name and save to file
PROC TAKE_SCREENSHOT(INT iIndex)
// Check widget for screenshot name
sFolderName = GET_CONTENTS_OF_TEXT_WIDGET(widgetFolderName)
sShotName = GET_CONTENTS_OF_TEXT_WIDGET(widgetShotName)
// Build screenshot name and directory
TEXT_LABEL_63 sTemp = sFolderName
sTemp += sShotName
IF bUseScreenCount
IF iScreenShot < 10
sTemp += "_0"
ELSE
sTemp += "_"
ENDIF
sTemp += iScreenShot
ENDIF
IF bUseModelName
sTemp += "_"
sTemp += GET_MODEL_NAME_FOR_DEBUG(eModelName[iIndex])
ENDIF
// Take screenshot
SAVE_SCREENSHOT(sTemp)
bScreenShot = TRUE
ENDPROC
/// PURPOSE: Take screenshot at specified time during idle animation
FUNC BOOL TAKE_SCREENSHOT_AT_TIME(INT iIndex)
IF DOES_ENTITY_EXIST(piCharacter)
AND NOT IS_ENTITY_DEAD(piCharacter)
INT iCurrentAnimTime = GET_GAME_TIMER() - iIdleTimer
// Check for screenshot
IF NOT bScreenShot
IF (iCurrentAnimTime > fIdleShot*1000)
TAKE_SCREENSHOT(iIndex)
ENDIF
ENDIF
// Finished idle duration
IF (iCurrentAnimTime > fIdleTime*1000)
PRINTLN("charAnimTest: Ped finished idle animation after specified duration.")
RETURN TRUE
ENDIF
ELSE
PRINTLN("charAnimTest: Ped died during idle animation...")
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE: Take screenshot at specified phase
FUNC BOOL TAKE_SCREENSHOT_AT_PHASE(INT iIndex)
IF DOES_ENTITY_EXIST(piCharacter)
AND NOT IS_ENTITY_DEAD(piCharacter)
// Ped is either playing or getting ready to play anim
IF ((GET_SCRIPT_TASK_STATUS(piCharacter, SCRIPT_TASK_PLAY_ANIM) = PERFORMING_TASK)
OR (GET_SCRIPT_TASK_STATUS(piCharacter, SCRIPT_TASK_PLAY_ANIM) = WAITING_TO_START_TASK))
// Ped is definitely playing animation
IF GET_SCRIPT_TASK_STATUS(piCharacter, SCRIPT_TASK_PLAY_ANIM) = PERFORMING_TASK
// Get current animation phase
FLOAT fCurrentPhase = GET_ENTITY_ANIM_CURRENT_TIME(piCharacter, sAnimDict, sAnimName)
// Check for screenshot
IF NOT bScreenShot
IF (fCurrentPhase >= fAnimPhase)
TAKE_SCREENSHOT(iIndex)
ENDIF
ENDIF
// Need to exit before animation has finished?
IF fPhaseMax < 1.0
IF (fCurrentPhase >= fPhaseMax)
PRINTLN("charAnimTest: Ped finished animation early at specified phase ", fPhaseMax)
RETURN TRUE
ENDIF
ENDIF
ENDIF
ELSE
PRINTLN("charAnimTest: Ped finished animation...")
RETURN TRUE
ENDIF
ELSE
PRINTLN("charAnimTest: Ped died during animation...")
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
// -----------------------------------------------------------------------------------------------------------
// Widget functions
// -----------------------------------------------------------------------------------------------------------
/// PURPOSE: Caps the idle time if min or max values are updated
PROC CHECK_IDLE_TIME_VALUES
IF (fIdleTime < fIdleShot) fIdleShot = fIdleTime ENDIF
IF (fIdleShot > fIdleTime) fIdleShot = fIdleTime ENDIF
ENDPROC
/// PURPOSE: Caps the animation phase if min or max values are updated
PROC CHECK_ANIM_PHASE_VALUES
IF (fPhaseMin > fPhaseMax) fPhaseMax = fPhaseMin ENDIF
IF (fPhaseMin > fAnimPhase) fAnimPhase = fPhaseMin ENDIF
IF (fPhaseMax < fAnimPhase) fAnimPhase = fPhaseMax ENDIF
ENDPROC
/// PURPOSE: Toggles ped models either on or off
PROC TOGGLE_PEDS(BOOL bOn, BOOL bAmbient, BOOL bGang, BOOL bUnique)
// Ambient peds
IF bAmbient
bShowAFM = bOn
bShowAFO = bOn
bShowAFY = bOn
bShowAMM = bOn
bShowAMO = bOn
bShowAMY = bOn
ENDIF
// Gang peds
IF bGang
bShowGFY = bOn
bShowGMM = bOn
bShowGMY = bOn
ENDIF
// Unique peds
IF bUnique
bShowUFM = bOn
bShowUFO = bOn
bShowUFY = bOn
bShowUMM = bOn
bShowUMO = bOn
bShowUMY = bOn
ENDIF
ENDPROC
/// PURPOSE: Checks for prop settings being updated
PROC CHECK_FOR_PROP_UPDATE()
IF bUseProp
IF bLiveUpdate
IF DOES_ENTITY_EXIST(piCharacter)
AND DOES_ENTITY_EXIST(propIndex)
IF NOT IS_ENTITY_DEAD(piCharacter)
// Model has been updated
IF iPropModel != iLastModel
// Request new model
REQUEST_MODEL(ePropName[iPropModel])
WHILE NOT HAS_MODEL_LOADED(ePropName[iPropModel])
WAIT(0)
ENDWHILE
// Delete old prop...
IF DOES_ENTITY_EXIST(propIndex)
DELETE_OBJECT(propIndex)
ENDIF
// And create new prop...
propIndex = CREATE_OBJECT(ePropName[iPropModel], GET_ENTITY_COORDS(piCharacter))
// Update reference to last model
iLastModel = iPropModel
ELSE
// Need to reattach current prop to new position
IF IS_ENTITY_ATTACHED_TO_ENTITY(propIndex, piCharacter)
DETACH_ENTITY(propIndex)
ENDIF
ENDIF
// Attach to relevant hand
IF (iPropAttachBone = 0)
ATTACH_ENTITY_TO_ENTITY(propIndex, piCharacter, GET_PED_BONE_INDEX(piCharacter, BONETAG_PH_L_HAND), vPropOffset, vPropRot)
ELSE
ATTACH_ENTITY_TO_ENTITY(propIndex, piCharacter, GET_PED_BONE_INDEX(piCharacter, BONETAG_PH_R_HAND), vPropOffset, vPropRot)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE: Checks the widget that handles the ped toggle
PROC CHECK_FOR_PED_TOGGLE()
// Ambient toggle is switched on
IF bToggledOn[1]
// Check for player unticking all ambient peds
IF NOT bShowAFM AND NOT bShowAFO AND NOT bShowAFY
AND NOT bShowAMM AND NOT bShowAMO AND NOT bShowAMY
bToggleAmbient = FALSE
bToggledOn[1] = FALSE
ENDIF
ELSE
// Check for player ticking all ambient peds
IF bShowAFM AND bShowAFO AND bShowAFY
AND bShowAMM AND bShowAMO AND bShowAMY
bToggleAmbient = TRUE
bToggledOn[1] = TRUE
ENDIF
ENDIF
// Gang toggle is switched on
IF bToggledOn[2]
// Check for player unticking all gang peds
IF NOT bShowGFY AND NOT bShowGMM AND NOT bShowGMY
bToggleGang = FALSE
bToggledOn[2] = FALSE
ENDIF
ELSE
// Check for player ticking all gang peds
IF bShowGFY AND bShowGMM AND bShowGMY
bToggleGang = TRUE
bToggledOn[2] = TRUE
ENDIF
ENDIF
// Unique toggle is switched on
IF bToggledOn[3]
// Check for player unticking all gang peds
IF NOT bShowUFM AND NOT bShowUFO AND NOT bShowUFY
AND NOT bShowUMM AND NOT bShowUMO AND NOT bShowUMY
bToggleUnique = FALSE
bToggledOn[3] = FALSE
ENDIF
ELSE
// Check for player ticking all gang peds
IF bShowUFM AND bShowUFO AND bShowUFY
AND bShowUMM AND bShowUMO AND bShowUMY
bToggleUnique = TRUE
bToggledOn[3] = TRUE
ENDIF
ENDIF
// Check whether we need to update the ALL toggle
IF bToggledOn[0]
IF NOT bToggleAmbient AND NOT bToggleGang AND NOT bToggleUnique
bToggleAllPeds = FALSE
bToggledOn[0] = FALSE
ENDIF
ELSE
IF bToggleAmbient AND bToggleGang AND bToggleUnique
bToggleAllPeds = TRUE
bToggledOn[0] = TRUE
ENDIF
ENDIF
// Toggle all ped models
IF bToggleAllPeds
IF NOT bToggledOn[0]
PRINTLN("charAnimTest: Toggling all peds on...")
TOGGLE_PEDS(TRUE, TRUE, TRUE, TRUE)
bToggleAmbient = TRUE
bToggleGang = TRUE
bToggleUnique = TRUE
INT i
FOR i = 0 TO 3
bToggledOn[i] = TRUE
ENDFOR
EXIT
ENDIF
ELSE
IF bToggledOn[0]
PRINTLN("charAnimTest: Toggling all peds off...")
TOGGLE_PEDS(FALSE, TRUE, TRUE, TRUE)
bToggleAmbient = FALSE
bToggleGang = FALSE
bToggleUnique = FALSE
INT i
FOR i = 0 TO 3
bToggledOn[i] = FALSE
ENDFOR
ENDIF
ENDIF
// Toggle all ambient models
IF bToggleAmbient
IF NOT bToggledOn[1]
PRINTLN("charAnimTest: Toggling all ambient peds on...")
TOGGLE_PEDS(TRUE, TRUE, FALSE, FALSE)
bToggledOn[1] = TRUE
EXIT
ENDIF
ELSE
IF bToggledOn[1]
PRINTLN("charAnimTest: Toggling all ambient peds off...")
TOGGLE_PEDS(FALSE, TRUE, FALSE, FALSE)
bToggledOn[1] = FALSE
EXIT
ENDIF
ENDIF
// Toggle all gang models
IF bToggleGang
IF NOT bToggledOn[2]
PRINTLN("charAnimTest: Toggling all gang peds on...")
TOGGLE_PEDS(TRUE, FALSE, TRUE, FALSE)
bToggledOn[2] = TRUE
EXIT
ENDIF
ELSE
IF bToggledOn[2]
PRINTLN("charAnimTest: Toggling all gang peds off...")
TOGGLE_PEDS(FALSE, FALSE, TRUE, FALSE)
bToggledOn[2] = FALSE
EXIT
ENDIF
ENDIF
// Toggle all unique models
IF bToggleUnique
IF NOT bToggledOn[3]
PRINTLN("charAnimTest: Toggling all unique peds on...")
TOGGLE_PEDS(TRUE, FALSE, FALSE, TRUE)
bToggledOn[3] = TRUE
EXIT
ENDIF
ELSE
IF bToggledOn[3]
PRINTLN("charAnimTest: Toggling all unique peds off...")
TOGGLE_PEDS(FALSE, FALSE, FALSE, TRUE)
bToggledOn[3] = FALSE
EXIT
ENDIF
ENDIF
ENDPROC
/// PURPOSE: Checks to see whether camera settings has been updated via widget
PROC CHECK_FOR_CAMERA_UPDATE()
// Update camera with current view settings
IF bGetCurrentCam
// Check for debug camera being active
IF DOES_CAM_EXIST(GET_RENDERING_CAM())
// Get current settings
PRINTLN("charAnimTest: Grabbing current camera info...")
VECTOR vCurrentCamPos = GET_CAM_COORD(GET_RENDERING_CAM())
VECTOR vCurrentCamRot = GET_CAM_ROT(GET_RENDERING_CAM())
FLOAT fCurrentCamFOV = GET_CAM_FOV(GET_RENDERING_CAM())
// Position
vCameraPos.x = vCurrentCamPos.x
vCameraPos.y = vCurrentCamPos.y
vCameraPos.z = vCurrentCamPos.z
// Rotation
vCameraRot.x = vCurrentCamRot.x
vCameraRot.y = vCurrentCamRot.y
vCameraRot.z = vCurrentCamRot.z
// Field of view
fCameraFOV = fCurrentCamFOV
// Apply camera settings during "Test Scene"
IF bTestSceneOn
TOGGLE_TEST_CAMERA(FALSE)
TOGGLE_TEST_CAMERA(TRUE)
ENDIF
ELSE
PRINTLN("charAnimTest: Debug Cam is not active...")
ENDIF
// Done!
bGetCurrentCam = FALSE
ENDIF
ENDPROC
// -----------------------------------------------------------------------------------------------------------
// Test Functions/States
// -----------------------------------------------------------------------------------------------------------
/// PURPOSE: Handles the test scene when active
PROC PROCESS_TEST_SCENE()
// Start test scene
IF bTestSceneOn
// Don't run if the full test is running
IF NOT bFullTestOn
IF NOT bTestActive
PRINTLN("charAnimTest: Starting Test Scene...")
bTestActive = TRUE
// Get anims from widgets
sAnimDict = GET_CONTENTS_OF_TEXT_WIDGET(widgetAnimDict)
sAnimName = GET_CONTENTS_OF_TEXT_WIDGET(widgetAnimName)
// Setup camera position
TOGGLE_TEST_CAMERA(TRUE)
// Load anim dictionary
LOAD_ANIM_DICT()
// Attempt to create character - will timeout if failed to create within 5 seconds...
IF CREATE_CHARACTER(0, TRUE)
PRINTLN("charAnimTest: Waiting for ped to be visible...")
WAIT(1000)
// Play looping animation
PLAY_ANIM_ON_CHARACTER()
// Play animation
WHILE bTestSceneOn
// "Full Test" cannot be selected whilst "Test Scene" runs...
IF bFullTestOn
bFullTestOn = FALSE
ENDIF
// Allow prop to be updated whilst test is running...
CHECK_FOR_PROP_UPDATE()
// Allow toggles and updates (doesn't affect test)
CHECK_FOR_PED_TOGGLE()
CHECK_FOR_CAMERA_UPDATE()
// Check debug exit
CHECK_DEBUG_CLEANUP()
WAIT(0)
ENDWHILE
// Remove character
CREATE_CHARACTER(0, FALSE)
ENDIF
// Unload animations
UNLOAD_ANIM_DICT()
// Restore normal game camera
TOGGLE_TEST_CAMERA(FALSE)
// Reset variables
bTestActive = FALSE
PRINTLN("charAnimTest: Ending Test Scene")
ENDIF
ELSE
// Reset widget box
bTestSceneOn = FALSE
ENDIF
ENDIF
ENDPROC
// PURPOSE: Common checks whilst processing the test - returns FALSE if the test should abort
FUNC BOOL DO_TEST_WAIT(INT i)
// Ensure test scene tickbox cannot be enabled
IF bTestSceneOn
bTestSceneOn = FALSE
ENDIF
// Check for debug quit/pass
CHECK_DEBUG_CLEANUP()
// Check for cancelling the test
IF NOT bFullTestOn
WAIT(0)
RETURN FALSE
ELSE
WAIT(i)
RETURN TRUE
ENDIF
ENDFUNC
// PURPOSE: Handles the full test when active
PROC PROCESS_FULL_TEST()
// Start Full Anim Test
IF bFullTestOn
IF NOT bTestActive
PRINTLN("charAnimTest: Starting Full Test...")
bTestActive = TRUE
// Get anims from widgets
sAnimDict = GET_CONTENTS_OF_TEXT_WIDGET(widgetAnimDict)
sAnimName = GET_CONTENTS_OF_TEXT_WIDGET(widgetAnimName)
// Check animations
IF IS_STRING_NULL_OR_EMPTY(sAnimDict)
AND IS_STRING_NULL_OR_EMPTY(sAnimName)
AND bUseIdleAnims = FALSE
// Cancel test if no animations have been defined
PRINTLN("charAnimTest: Animations not defined - Test Aborted...")
bFullTestOn = FALSE
bTestActive = FALSE
ELSE
// Specify whether using idles or defined animations
IF bUseIdleAnims
PRINTLN("charAnimTest: Starting Full Test - Using Idle Anims...")
ELSE
PRINTLN("charAnimTest: Starting Full Test - Using Specified Anims...")
ENDIF
// Setup camera position
TOGGLE_TEST_CAMERA(TRUE)
// Load anim dictionary
LOAD_ANIM_DICT()
// Cycle through character list
INT iIndex = 0
FOR iIndex = 0 TO MAX_NUM_CHARACTERS
// Check to see whether we want to create this ped model
IF HAS_CHARACTER_MODEL_BEEN_SELECTED(iIndex)
// Attempt to create character - will timeout if failed to create within 3 seconds...
IF CREATE_CHARACTER(iIndex, TRUE)
PRINTLN("charAnimTest: Waiting for ped to be visible...")
IF NOT DO_TEST_WAIT(1000)
PRINTLN("charAnimTest: Aborting test whilst waiting for ped to be visible...")
EXIT
ENDIF
// Play animation
PLAY_ANIM_ON_CHARACTER()
WHILE NOT HAS_ANIM_STARTED_ON_CHARACTER()
IF NOT DO_TEST_WAIT(0)
PRINTLN("charAnimTest: Aborting test whilst waiting for anim to start on character...")
EXIT
ENDIF
ENDWHILE
// Wait for screenshot
IF bUseIdleAnims
WHILE NOT TAKE_SCREENSHOT_AT_TIME(iIndex)
IF NOT DO_TEST_WAIT(0)
PRINTLN("charAnimTest: Aborting test whilst waiting for idle screenshot...")
EXIT
ENDIF
ENDWHILE
ELSE
WHILE NOT TAKE_SCREENSHOT_AT_PHASE(iIndex)
IF NOT DO_TEST_WAIT(0)
PRINTLN("charAnimTest: Aborting test whilst waiting for specified anim screenshot...")
EXIT
ENDIF
ENDWHILE
ENDIF
// Remove character
CREATE_CHARACTER(iIndex, FALSE)
ENDIF
ENDIF
ENDFOR
// Unload animations
UNLOAD_ANIM_DICT()
// Restore normal game camera
TOGGLE_TEST_CAMERA(FALSE)
// Increment screenshot counter
iScreenShot++
// Reset variables
bFullTestOn = FALSE
bTestActive = FALSE
PRINTLN("charAnimTest: Complete")
ENDIF
ENDIF
ELSE
// Stop animation test
IF bTestActive
// Remove character and restore camera
CREATE_CHARACTER(0, FALSE)
TOGGLE_TEST_CAMERA(FALSE)
bTestActive = FALSE
iScreenShot++
PRINTLN("charAnimTest: Cancelled")
ENDIF
ENDIF
ENDPROC
/// PURPOSE: Updates widgets and tests
PROC UPDATE_TEST_SCRIPT()
// Update idle times if min/max change
CHECK_IDLE_TIME_VALUES()
// Update anim phase if min/max change
CHECK_ANIM_PHASE_VALUES()
// Have all ped models been toggled on/off
CHECK_FOR_PED_TOGGLE()
// Check to see whether camera values are updated
CHECK_FOR_CAMERA_UPDATE()
// Check and update test scene when active
PROCESS_TEST_SCENE()
// Check and update full test when active
PROCESS_FULL_TEST()
ENDPROC
#ENDIF
/// Main script loop
SCRIPT
// Fade in screen if necessary
#IF IS_DEBUG_BUILD PRINTLN("charAnimTest: Launched") #ENDIF
IF IS_SCREEN_FADED_OUT()
DO_SCREEN_FADE_IN(500)
ENDIF
// Check for force cleanup of script
IF HAS_FORCE_CLEANUP_OCCURRED(FORCE_CLEANUP_FLAG_DEBUG_MENU|FORCE_CLEANUP_FLAG_SP_TO_MP)
#IF IS_DEBUG_BUILD PRINTLN("charAnimTest: Force Cleanup") #ENDIF
SCRIPT_CLEANUP()
ENDIF
// Create anim widgets
#IF IS_DEBUG_BUILD
SETUP_WIDGETS()
#ENDIF
// Main loop
WHILE (TRUE)
#IF IS_DEBUG_BUILD
// Only display instruction text when tests aren't running
IF NOT bTestActive
// Display 'Placeholder Mission'
SET_TEXT_COLOUR(255, 255, 255, 255)
SET_TEXT_SCALE(0.75, 0.9)
SET_TEXT_WRAP(0.0, 1.0)
DISPLAY_TEXT(0.05, 0.63, "PLCHLD_MISS")
// Display Pass and Fail instructions
SET_TEXT_COLOUR(255, 255, 255, 255)
SET_TEXT_SCALE(0.4, 0.45)
SET_TEXT_WRAP(0.0, 1.0)
DISPLAY_TEXT(0.05, 0.7, "PLCHLD_PASS")
ENDIF
// Update anim test
UPDATE_TEST_SCRIPT()
// Check for player debug quitting the script
CHECK_DEBUG_CLEANUP()
#ENDIF
WAIT(0)
ENDWHILE
// Script should never reach here. Always terminate with cleanup function.
ENDSCRIPT