Files
gtav-src/script/dev_ng/shared/script_metrics.sc
T
2025-09-29 00:52:08 +02:00

988 lines
30 KiB
Python
Executable File

//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 "commands_datafile.sch"
USING "net_mission.sch"
USING "net_transition_sessions.sch"
#IF IS_DEBUG_BUILD
USING "script_metrics_public.sch"
#ENDIF
#IF NOT IS_DEBUG_BUILD
SCRIPT
ENDSCRIPT
#ENDIF
#IF IS_DEBUG_BUILD
BOOL bRender
BOOL bRenderNumbers = FALSE
BOOL bRenderPeaks = TRUE
BOOL bUploadToCloud
BOOL bUploadingToCloud
//BOOL bSuccessfulUploadToCloud
BOOL bDownloadFromCloud
//BOOL bDownloadingFromCloud
//BOOL bSuccessfulDowloadFromCloud
BOOL bEnableCloudUploading
BOOL bTurnOnFileWriting = TRUE
FLOAT fWindowX = 0.103
FLOAT fWindowY = 0.08
FLOAT fWindowMinH = 0.021
FLOAT fWindowW = 0.749
FLOAT fTextScale = 0.267
FLOAT fTextIndentX = 0.005
FLOAT fTextIndentY = -0.004
FLOAT fLineSpacerY = 0.015
FLOAT fNoPlayersIntX = 0.086
FLOAT fNoBotsStringX = 0.12
FLOAT fNoBotsIntX = 0.185
FLOAT fBarWidthPerMS = 0.03
FLOAT fBarHeight = 0.01
FLOAT fTimeBarX = 0.131
FLOAT fCurrentTimeX = 0.089
FLOAT fAverageTimeX = 0.078
FLOAT fPeakTimeX = 0.106
TEXT_LABEL_63 sFileName
TEXT_LABEL_63 sFilePath
TEXT_LABEL_63 ScriptName
TEXT_LABEL_63 ExeVersion
TEXT_LABEL_63 ScriptVersion
//TEXT_LABEL_63 CloudFilename
//TEXT_LABEL_63 CloudPathName
STRING strVersionName
INT iNoPlayers
INT iNoBots
INT iPlayerNumber
INT iPlayerTeam
INT iRecordingInterval = 11000
INT iTotal
INT iTotalNoPlayers
INT iTotalNoBots
INT iTotalPlayerNumber
INT iTotalPlayerTeam
INT iTotalNetworkTime
INT iTotalThreadDuration
// for recording
BOOL bStartRecording
BOOL bRecordAllThreads = TRUE
BOOL bRecordSpecificThreadOnly = FALSE
BOOL bRenderStoredPeaks
TEXT_WIDGET_ID TextWidget
STRING SpecificScript
DATAFILE_ARRAY ScriptInfoArray
DATAFILE_DICT DataFileDict
DATAFILE_DICT GeneralInfoDict
FLOAT fCurrentTime
FLOAT fAverageTime
FLOAT fPeakTime
FLOAT fTotalCurrentTime2
FLOAT fTotalAverageTime2
FLOAT fTotalPeakTime2
FLOAT fTotalCurrentTime
FLOAT fTotalAverageTime
FLOAT fTotalPeakTime
CONST_INT MAX_NO_THREADS 64
FLOAT fStoredPeakTime[MAX_NO_THREADS]
INT iTotalThreadsLastFrame
FUNC BOOL SHOULD_IGNORE_THREAD(THREADID Thread_ID)
IF (bRecordAllThreads)
IF ARE_STRINGS_EQUAL(GET_NAME_OF_SCRIPT_WITH_THIS_ID(Thread_ID), "net_bot_brain")
OR (Thread_ID = GET_ID_OF_THIS_THREAD())
RETURN(TRUE)
ENDIF
ELSE
IF ARE_STRINGS_EQUAL(GET_NAME_OF_SCRIPT_WITH_THIS_ID(Thread_ID), SpecificScript)
RETURN(FALSE)
ELSE
RETURN(TRUE)
ENDIF
ENDIF
RETURN(FALSE)
ENDFUNC
FUNC INT GET_NUMBER_OF_BOTS()
IF NETWORK_IS_GAME_IN_PROGRESS()
RETURN(NETWORK_BOT_GET_NUMBER_OF_ACTIVE_BOTS())
ENDIF
RETURN(0)
ENDFUNC
FUNC INT GET_NUMBER_OF_REAL_PLAYERS()
IF NETWORK_IS_GAME_IN_PROGRESS()
INT i
INT iCount
PLAYER_INDEX PlayerID
REPEAT NUM_NETWORK_PLAYERS i
PlayerID = INT_TO_NATIVE(PLAYER_INDEX, i)
IF NETWORK_IS_PLAYER_ACTIVE(playerID)
iCount += 1
ENDIF
ENDREPEAT
iCount -= NETWORK_BOT_GET_NUMBER_OF_ACTIVE_BOTS()
RETURN(iCount)
ENDIF
RETURN(1)
ENDFUNC
PROC PRINT_METRIC_STRING(STRING sString)
SAVE_STRING_TO_NAMED_DEBUG_FILE(sString, sFilePath, sFileName)
PRINTSTRING(sString)
ENDPROC
PROC PRINT_METRIC_NEWLINE()
SAVE_NEWLINE_TO_NAMED_DEBUG_FILE(sFilePath, sFileName)
PRINTNL()
ENDPROC
PROC PRINT_METRIC_INT(INT iInt)
SAVE_INT_TO_NAMED_DEBUG_FILE(iInt, sFilePath, sFileName)
PRINTINT(iInt)
ENDPROC
PROC PRINT_METRIC_FLOAT(FLOAT fFloat)
SAVE_FLOAT_TO_NAMED_DEBUG_FILE(fFloat, sFilePath, sFileName)
PRINTFLOAT(fFloat)
ENDPROC
PROC STORE_GENERAL_DETAILS()
// IF IS_DEBUG_KEY_JUST_PRESSED(KEY_1,KEYBOARD_MODIFIER_SHIFT, "Dump script metric data to file")
// ExeVersion = "Beta"
// ENDIF
// IF IS_DEBUG_KEY_JUST_PRESSED(KEY_2,KEYBOARD_MODIFIER_SHIFT, "Dump script metric data to file")
// ExeVersion = "BankRel"
// ENDIF
// IF IS_DEBUG_KEY_JUST_PRESSED(KEY_3,KEYBOARD_MODIFIER_SHIFT, "Dump script metric data to file")
// ExeVersion = "Release"
// ENDIF
strVersionName = GET_GAME_VERSION_NAME()
iNoPlayers = GET_NUMBER_OF_REAL_PLAYERS()
iNoBots = GET_NUMBER_OF_BOTS()
iPlayerNumber = NATIVE_TO_INT(GET_PLAYER_INDEX())
IF NETWORK_IS_GAME_IN_PROGRESS()
iPlayerTeam = GET_PLAYER_TEAM(GET_PLAYER_INDEX())
ELSE
iPlayerTeam = -1
ENDIF
ScriptVersion = "Debug"
ENDPROC
PROC GENERATE_FILE_NAME()
// generate the file name
sFileName = "SM_"
sFileName += strVersionName
sFileName += "_"
sFileName += iNoPlayers
sFileName += "_"
sFileName += iNoBots
sFileName += "_"
sFileName += ExeVersion
sFileName += "_"
sFileName += GET_REAL_WORLD_TIME()
sFileName += ".txt"
ENDPROC
PROC PRINT_TOTAL_METRIC_DETAILS()
INT iAvNoPlayer = ROUND(TO_FLOAT(iTotalNoPlayers) / TO_FLOAT(iTotal))
INT iAvNoBots = ROUND(TO_FLOAT(iTotalNoBots) / TO_FLOAT(iTotal))
INT iAvPlayerNumber = ROUND(TO_FLOAT(iTotalPlayerNumber) / TO_FLOAT(iTotal))
INT iAvPlayerTeam = ROUND(TO_FLOAT(iTotalPlayerTeam) / TO_FLOAT(iTotal))
INT iAvNetworkTime = ROUND(TO_FLOAT(iTotalNetworkTime) / TO_FLOAT(iTotal))
INT iAvThreadDuration = ROUND(TO_FLOAT(iTotalThreadDuration) / TO_FLOAT(iTotal))
TEXT_LABEL_63 strNetworkTime
strNetworkTime = "NetworkTime:"
strNetworkTime += iAvNetworkTime
strNetworkTime += ";"
TEXT_LABEL_63 strGeneralInfo
strGeneralInfo = "V:"
strGeneralInfo += strVersionName
strGeneralInfo += ";Plyrs:"
strGeneralInfo += iAvNoPlayer
strGeneralInfo += ";Bots:"
strGeneralInfo += iAvNoBots
strGeneralInfo += ";Exe:"
strGeneralInfo += ExeVersion
strGeneralInfo += ";SV:"
strGeneralInfo += ScriptVersion
strGeneralInfo += ";"
TEXT_LABEL_63 strPlayerInfo
strPlayerInfo = "PID:"
strPlayerInfo += iAvPlayerNumber
strPlayerInfo += ";Team:"
strPlayerInfo += iAvPlayerTeam
strPlayerInfo += ";"
TEXT_LABEL_63 strScriptInfo
strScriptInfo = "Script:"
strScriptInfo += "TOTAL"
strScriptInfo += ";"
strScriptInfo += "Host:0;"
TEXT_LABEL_63 strDuration
strDuration = "Duration:"
strDuration += iAvThreadDuration
strDuration += ";"
CPRINTLN(DEBUG_METRIC_DATA, "Writing TOTAL script metrics...")
// write to external file
IF (bTurnOnFileWriting)
SAVE_STRING_TO_NAMED_DEBUG_FILE(strNetworkTime, DebugFilePath, DebugFileName)
SAVE_STRING_TO_NAMED_DEBUG_FILE(strGeneralInfo, DebugFilePath, DebugFileName)
SAVE_STRING_TO_NAMED_DEBUG_FILE(strPlayerInfo, DebugFilePath, DebugFileName)
SAVE_STRING_TO_NAMED_DEBUG_FILE(strScriptInfo, DebugFilePath, DebugFileName)
SAVE_STRING_TO_NAMED_DEBUG_FILE(strDuration, DebugFilePath, DebugFileName)
SAVE_STRING_TO_NAMED_DEBUG_FILE("Current:", DebugFilePath, DebugFileName)
SAVE_FLOAT_TO_NAMED_DEBUG_FILE(fTotalCurrentTime2, DebugFilePath, DebugFileName)
SAVE_STRING_TO_NAMED_DEBUG_FILE(";Average:", DebugFilePath, DebugFileName)
SAVE_FLOAT_TO_NAMED_DEBUG_FILE(fTotalAverageTime2, DebugFilePath, DebugFileName)
SAVE_STRING_TO_NAMED_DEBUG_FILE(";Peak:", DebugFilePath, DebugFileName)
SAVE_FLOAT_TO_NAMED_DEBUG_FILE(fTotalPeakTime2, DebugFilePath, DebugFileName)
SAVE_STRING_TO_NAMED_DEBUG_FILE(";", DebugFilePath, DebugFileName)
SAVE_NEWLINE_TO_NAMED_DEBUG_FILE(DebugFilePath, DebugFileName)
ENDIF
ENDPROC
ENUM SCRIPT_METRIC_FLAGS
SMF_NULL,
SMF_ON_MISSION,
SMF_OFF_MISSION,
SMF_DM,
SMF_RACE,
SMF_MISSION
ENDENUM
PROC PRINT_METRIC_DETAILS_FOR_THREAD(THREADID Thread_ID, SCRIPT_METRIC_FLAGS MetricFlag=SMF_NULL)
INT iNetworkTime = NATIVE_TO_INT(GET_NETWORK_TIME())
TEXT_LABEL_63 strNetworkTime
strNetworkTime = "NetworkTime:"
strNetworkTime += iNetworkTime
strNetworkTime += ";"
TEXT_LABEL_63 strGeneralInfo
strGeneralInfo = "V:"
strGeneralInfo += strVersionName
strGeneralInfo += ";Plyrs:"
strGeneralInfo += iNoPlayers
strGeneralInfo += ";Bots:"
strGeneralInfo += iNoBots
strGeneralInfo += ";Exe:"
strGeneralInfo += ExeVersion
strGeneralInfo += ";SV:"
strGeneralInfo += ScriptVersion
strGeneralInfo += ";"
TEXT_LABEL_63 strPlayerInfo
strPlayerInfo = "PID:"
strPlayerInfo += iPlayerNumber
strPlayerInfo += ";Team:"
strPlayerInfo += iPlayerTeam
strPlayerInfo += ";"
TEXT_LABEL_63 strScriptInfo
strScriptInfo = "Script:"
IF (MetricFlag = SMF_NULL)
strScriptInfo += GET_NAME_OF_SCRIPT_WITH_THIS_ID(Thread_ID)
ELSE
IF NETWORK_IS_GAME_IN_PROGRESS()
SWITCH MetricFlag
CASE SMF_DM
strScriptInfo += "UGC_D "
strScriptInfo += GlobalplayerBD_MissionName[NATIVE_TO_INT(PLAYER_ID())].tl63MissionName
BREAK
CASE SMF_RACE
strScriptInfo += "UGC_R "
strScriptInfo += GlobalplayerBD_MissionName[NATIVE_TO_INT(PLAYER_ID())].tl63MissionName
BREAK
CASE SMF_MISSION
strScriptInfo += "UGC_M "
strScriptInfo += GlobalplayerBD_MissionName[NATIVE_TO_INT(PLAYER_ID())].tl63MissionName
BREAK
CASE SMF_ON_MISSION
strScriptInfo += "ON_MISS "
strScriptInfo += GET_NAME_OF_SCRIPT_WITH_THIS_ID(Thread_ID)
BREAK
CASE SMF_OFF_MISSION
strScriptInfo += "OFF_MISS "
strScriptInfo += GET_NAME_OF_SCRIPT_WITH_THIS_ID(Thread_ID)
BREAK
ENDSWITCH
ENDIF
ENDIF
strScriptInfo += ";"
IF AM_I_HOST_OF_THREAD(Thread_ID)
strScriptInfo += "Host:1;"
ELSE
strScriptInfo += "Host:0;"
ENDIF
INT iThreadDuration = GET_THREAD_DURATION(Thread_ID)
TEXT_LABEL_63 strDuration
strDuration = "Duration:"
strDuration += iThreadDuration
strDuration += ";"
fCurrentTime = METRICS_GET_UPDATE_TIME_FOR_THREAD(Thread_ID)
fAverageTime = METRICS_GET_AVERAGE_UPDATE_TIME_FOR_THREAD(Thread_ID)
fPeakTime = METRICS_GET_PEAK_UPDATE_TIME_FOR_THREAD(Thread_ID)
CPRINTLN(DEBUG_METRIC_DATA, "Writing script metrics...")
// write to external file
IF (bTurnOnFileWriting)
SAVE_STRING_TO_NAMED_DEBUG_FILE(strNetworkTime, DebugFilePath, DebugFileName)
SAVE_STRING_TO_NAMED_DEBUG_FILE(strGeneralInfo, DebugFilePath, DebugFileName)
SAVE_STRING_TO_NAMED_DEBUG_FILE(strPlayerInfo, DebugFilePath, DebugFileName)
SAVE_STRING_TO_NAMED_DEBUG_FILE(strScriptInfo, DebugFilePath, DebugFileName)
SAVE_STRING_TO_NAMED_DEBUG_FILE(strDuration, DebugFilePath, DebugFileName)
SAVE_STRING_TO_NAMED_DEBUG_FILE("Current:", DebugFilePath, DebugFileName)
SAVE_FLOAT_TO_NAMED_DEBUG_FILE(fCurrentTime, DebugFilePath, DebugFileName)
SAVE_STRING_TO_NAMED_DEBUG_FILE(";Average:", DebugFilePath, DebugFileName)
SAVE_FLOAT_TO_NAMED_DEBUG_FILE(fAverageTime, DebugFilePath, DebugFileName)
SAVE_STRING_TO_NAMED_DEBUG_FILE(";Peak:", DebugFilePath, DebugFileName)
SAVE_FLOAT_TO_NAMED_DEBUG_FILE(fPeakTime, DebugFilePath, DebugFileName)
SAVE_STRING_TO_NAMED_DEBUG_FILE(";", DebugFilePath, DebugFileName)
SAVE_NEWLINE_TO_NAMED_DEBUG_FILE(DebugFilePath, DebugFileName)
ENDIF
iTotal += 1
iTotalNoPlayers += iNoPlayers
iTotalNoBots += iNoBots
iTotalPlayerNumber += iPlayerNumber
iTotalPlayerTeam += iPlayerTeam
iTotalNetworkTime += iNetworkTime
iTotalThreadDuration += iThreadDuration
fTotalCurrentTime2 += fCurrentTime
fTotalAverageTime2 += fAverageTime
fTotalPeakTime2 += fPeakTime
CPRINTLN(DEBUG_METRIC_DATA, "Finished writing script metrics")
ENDPROC
PROC PRINT_ALL_METRIC_INFO_TO_CHANNEL()
STORE_GENERAL_DETAILS()
// write general details
IF (bEnableCloudUploading)
IF NOT (bUploadToCloud)
DATAFILE_CREATE()
DataFileDict = DATAFILE_GET_FILE_DICT()
GeneralInfoDict = DATADICT_CREATE_DICT(DataFileDict, "GeneralInfo")
DATADICT_SET_STRING(GeneralInfoDict, "V", strVersionName)
DATADICT_SET_INT(GeneralInfoDict, "Plyrs", iNoPlayers)
DATADICT_SET_INT(GeneralInfoDict, "Bots", iNoBots)
DATADICT_SET_STRING(GeneralInfoDict, "Exe", ExeVersion)
DATADICT_SET_STRING(GeneralInfoDict, "SV", ScriptVersion)
DATADICT_SET_INT(GeneralInfoDict, "PID", iPlayerNumber)
DATADICT_SET_INT(GeneralInfoDict, "Team", iPlayerTeam)
VECTOR vCoords
IF DOES_ENTITY_EXIST(PLAYER_PED_ID())
vCoords = GET_ENTITY_COORDS(PLAYER_PED_ID(), FALSE)
ENDIF
DATADICT_SET_FLOAT(GeneralInfoDict, "PlayerX", vCoords.x)
DATADICT_SET_FLOAT(GeneralInfoDict, "PlayerY", vCoords.y)
DATADICT_SET_FLOAT(GeneralInfoDict, "PlayerZ", vCoords.z)
IF NETWORK_IS_GAME_IN_PROGRESS()
DATADICT_SET_STRING(GeneralInfoDict, "GameTime", GET_TIME_AS_STRING(GET_NETWORK_TIME()))
ELSE
DATADICT_SET_INT(GeneralInfoDict, "GameTime", GET_GAME_TIMER())
ENDIF
ScriptInfoArray = DATADICT_CREATE_ARRAY(DataFileDict, "ScriptThreadTimes")
ENDIF
ENDIF
// reset totals
iTotal = 0
iTotalNoPlayers = 0
iTotalNoBots = 0
iTotalPlayerNumber = 0
iTotalPlayerTeam = 0
iTotalNetworkTime = 0
iTotalThreadDuration = 0
fTotalCurrentTime2 = 0.0
fTotalAverageTime2 = 0.0
fTotalPeakTime2 = 0.0
THREADID Thread_ID
STRING strScriptName
SCRIPT_THREAD_ITERATOR_RESET()
Thread_ID = SCRIPT_THREAD_ITERATOR_GET_NEXT_THREAD_ID()
WHILE IS_THREAD_ACTIVE(Thread_ID)
IF NOT SHOULD_IGNORE_THREAD(Thread_ID)
strScriptName = GET_NAME_OF_SCRIPT_WITH_THIS_ID(Thread_ID)
// is player on mission and this is the mission script thread
IF NETWORK_IS_GAME_IN_PROGRESS()
PRINT_METRIC_DETAILS_FOR_THREAD(Thread_ID)
// main lauch script is recorded for on and off mission
IF (ARE_STRINGS_EQUAL(strScriptName, FREEMODE_SCRIPT())
OR ARE_STRINGS_EQUAL(strScriptName, "fmmc_launcher"))
IF IS_PLAYER_ON_ANY_FM_MISSION(PLAYER_ID(), FALSE)
PRINT_METRIC_DETAILS_FOR_THREAD(Thread_ID, SMF_ON_MISSION)
ELSE
PRINT_METRIC_DETAILS_FOR_THREAD(Thread_ID, SMF_OFF_MISSION)
ENDIF
ENDIF
// ugc controller scripts get recorded with their content mission names
IF IS_PLAYER_ON_ANY_FM_MISSION(PLAYER_ID(), FALSE)
IF ARE_STRINGS_EQUAL(strScriptName, "fm_deathmatch_controler")
PRINT_METRIC_DETAILS_FOR_THREAD(Thread_ID, SMF_DM)
ELIF ARE_STRINGS_EQUAL(strScriptName, "fm_race_controler")
PRINT_METRIC_DETAILS_FOR_THREAD(Thread_ID, SMF_RACE)
ELIF ARE_STRINGS_EQUAL(strScriptName, GET_FM_MISSION_CONTROLLER_SCRIPT_NAME())
PRINT_METRIC_DETAILS_FOR_THREAD(Thread_ID, SMF_MISSION)
ENDIF
ENDIF
ELSE
PRINT_METRIC_DETAILS_FOR_THREAD(Thread_ID)
ENDIF
IF (bEnableCloudUploading)
IF NOT (bUploadToCloud)
DATAARRAY_ADD_STRING(ScriptInfoArray, GET_NAME_OF_SCRIPT_WITH_THIS_ID(Thread_ID))
DATAARRAY_ADD_FLOAT(ScriptInfoArray, fCurrentTime)
DATAARRAY_ADD_FLOAT(ScriptInfoArray, fAverageTime)
DATAARRAY_ADD_FLOAT(ScriptInfoArray, fPeakTime)
ENDIF
ENDIF
ENDIF
Thread_ID = SCRIPT_THREAD_ITERATOR_GET_NEXT_THREAD_ID()
ENDWHILE
PRINT_TOTAL_METRIC_DETAILS()
// IF (bEnableCloudUploading)
// IF NOT (bUploadToCloud)
// CloudFilename = CloudPathName
// CloudFilename += "SM_"
// CloudFilename += GET_GAME_TIMER()
// CloudFilename +=".json"
// bUploadToCloud = TRUE
// ENDIF
// ENDIF
ENDPROC
SCRIPT
#IF IS_DEBUG_BUILD
PRINTSTRING("script_metrics.sc started...")
PRINTNL()
#ENDIF
// This script needs to cleanup only when the game runs the MAGDEMO
IF HAS_FORCE_CLEANUP_OCCURRED(FORCE_CLEANUP_FLAG_MAGDEMO)
#IF IS_DEBUG_BUILD
PRINTSTRING("...script_metrics.sc has been forced to cleanup (MAGDEMO)")
PRINTNL()
#ENDIF
TERMINATE_THIS_THREAD()
ENDIF
//INT iCount
INT iRowCount
INT iNumberOfRows
THREADID Thread_ID
FLOAT fWindowH
FLOAT fThisTime
FLOAT fThisWidth
FLOAT fThisPeakTime
FLOAT fTextX
FLOAT fTextY
FLOAT fThisHeight
INT i
INT iThreadCount
INIT_THREAD_METRIC_RECORDINGS()
NETWORK_SET_SCRIPT_IS_SAFE_FOR_NETWORK_GAME()
START_WIDGET_GROUP("Script Metrics")
ADD_WIDGET_INT_SLIDER("Recording Interval", iRecordingInterval, 0 , HIGHEST_INT, 1)
ADD_WIDGET_BOOL("Record All Threads", bRecordAllThreads)
ADD_WIDGET_BOOL("Record Specific Script", bRecordSpecificThreadOnly)
TextWidget = ADD_TEXT_WIDGET("Specific script to record")
ADD_WIDGET_BOOL("Start / Stop Recording", bStartRecording)
ADD_WIDGET_BOOL("bUploadingToCloud", bUploadingToCloud)
ADD_WIDGET_BOOL("bDownloadFromCloud", bDownloadFromCloud)
// ADD_WIDGET_BOOL("bEnableCloudUploading", bEnableCloudUploading)
START_WIDGET_GROUP("Debug")
ADD_WIDGET_BOOL("bRender", bRender)
ADD_WIDGET_BOOL("bRenderNumbers", bRenderNumbers)
ADD_WIDGET_BOOL("bRenderPeaks", bRenderPeaks)
ADD_WIDGET_BOOL("bRenderStoredPeaks", bRenderStoredPeaks)
ADD_WIDGET_FLOAT_SLIDER("fWindowX", fWindowX, -1.0, 1.0, 0.001)
ADD_WIDGET_FLOAT_SLIDER("fWindowY", fWindowY, -1.0, 1.0, 0.001)
ADD_WIDGET_FLOAT_SLIDER("fWindowMinH", fWindowMinH, -1.0, 1.0, 0.001)
ADD_WIDGET_FLOAT_SLIDER("fWindowW", fWindowW, -1.0, 1.0, 0.001)
ADD_WIDGET_FLOAT_SLIDER("fTextScale", fTextScale, -1.0, 1.0, 0.001)
ADD_WIDGET_FLOAT_SLIDER("fTextIndentX", fTextIndentX, -1.0, 1.0, 0.001)
ADD_WIDGET_FLOAT_SLIDER("fTextIndentY", fTextIndentY, -1.0, 1.0, 0.001)
ADD_WIDGET_FLOAT_SLIDER("fLineSpacerY", fLineSpacerY, -1.0, 1.0, 0.001)
ADD_WIDGET_FLOAT_SLIDER("fNoPlayersIntX", fNoPlayersIntX, -1.0, 1.0, 0.001)
ADD_WIDGET_FLOAT_SLIDER("fNoBotsStringX", fNoBotsStringX, -1.0, 1.0, 0.001)
ADD_WIDGET_FLOAT_SLIDER("fNoBotsIntX", fNoBotsIntX, -1.0, 1.0, 0.001)
ADD_WIDGET_FLOAT_SLIDER("fBarWidthPerMS", fBarWidthPerMS, -1.0, 1.0, 0.001)
ADD_WIDGET_FLOAT_SLIDER("fBarHeight", fBarHeight, -1.0, 1.0, 0.001)
ADD_WIDGET_FLOAT_SLIDER("fTimeBarX", fTimeBarX, -1.0, 1.0, 0.001)
ADD_WIDGET_FLOAT_SLIDER("fCurrentTimeX", fCurrentTimeX, -1.0, 1.0, 0.001)
ADD_WIDGET_FLOAT_SLIDER("fAverageTimeX", fAverageTimeX, -1.0, 1.0, 0.001)
ADD_WIDGET_FLOAT_SLIDER("fPeakTimeX", fPeakTimeX, -1.0, 1.0, 0.001)
ADD_WIDGET_BOOL("bStartRecording", bStartRecording)
ADD_WIDGET_BOOL("b_ScriptMetricsAreRecording", b_ScriptMetricsAreRecording)
ADD_WIDGET_BOOL("bTurnOnFileWriting", bTurnOnFileWriting)
STOP_WIDGET_GROUP()
STOP_WIDGET_GROUP()
// CloudPathName = "share/gta5/script_metrics/"
// CloudPathName += GET_GAME_VERSION_NAME()
// CloudPathName += "_"
// CloudPathName += GET_GAME_TIMER()
// CloudPathName += "/"
WHILE (TRUE)
// record a specific script only
IF (bRecordSpecificThreadOnly)
bRecordAllThreads = FALSE
SpecificScript = GET_CONTENTS_OF_TEXT_WIDGET(TextWidget)
bRecordSpecificThreadOnly = FALSE
ENDIF
// wait to be switched on
IF IS_DEBUG_KEY_JUST_PRESSED(KEY_F12, KEYBOARD_MODIFIER_NONE, "Script Metrics")
IF (bRender)
bRender = FALSE
ELSE
bRender = TRUE
ENDIF
ENDIF
// start recording
IF IS_DEBUG_KEY_JUST_PRESSED(KEY_5,KEYBOARD_MODIFIER_SHIFT, "Start / Stop Recording Script Metrics")
IF NOT NETWORK_IS_GAME_IN_PROGRESS()
IF NOT (bStartRecording)
bStartRecording = TRUE
ELSE
bStartRecording = FALSE
PRINTSTRING("[SCRIPT METRICS] bStartRecording = FALSE, network game not in progress after KEY_5 press ") PRINTNL()
ENDIF
ELSE
IF (b_ScriptMetricsAreRecording)
BROADCAST_GENERAL_EVENT(GENERAL_EVENT_TYPE_STOP_RECORDING_METRICS, ALL_PLAYERS())
ELSE
BROADCAST_GENERAL_EVENT(GENERAL_EVENT_TYPE_START_RECORDING_METRICS, ALL_PLAYERS())
ENDIF
ENDIF
ENDIF
// render screen
IF (bRender)
fWindowH = TO_FLOAT(iNumberOfRows) * fLineSpacerY
fWindowH += fWindowMinH
fTextX = fWindowX + fTextIndentX
fTextY = fWindowY + (fWindowMinH * 0.5) + fTextIndentY
// back ground
DRAW_RECT_FROM_CORNER(fWindowX, fWindowY , fWindowW, fWindowH, 0, 0, 0, 128)
// title
iRowCount = 0
SET_TEXT_SCALE(0.0000, fTextScale)
SET_TEXT_COLOUR(128,128,128, 255)
DISPLAY_TEXT_WITH_PLAYER_NAME(fTextX, fTextY + (iRowCount * fLineSpacerY), "STRING", "SCRIPT METRICS", HUD_COLOUR_GREY)
iRowCount += 1
// Info
SET_TEXT_SCALE(0.0000, fTextScale)
SET_TEXT_COLOUR(128,128,128, 255)
DISPLAY_TEXT_WITH_PLAYER_NAME(fTextX, fTextY + (iRowCount * fLineSpacerY), "STRING", "Number of Players: ", HUD_COLOUR_GREY)
SET_TEXT_SCALE(0.0000, fTextScale)
SET_TEXT_COLOUR(128,128,128, 255)
DISPLAY_TEXT_WITH_NUMBER(fTextX + fNoPlayersIntX, fTextY + (iRowCount * fLineSpacerY), "NUMBER", GET_NUMBER_OF_REAL_PLAYERS())
SET_TEXT_SCALE(0.0000, fTextScale)
SET_TEXT_COLOUR(128,128,128, 255)
DISPLAY_TEXT_WITH_PLAYER_NAME(fTextX + fNoBotsStringX, fTextY + (iRowCount * fLineSpacerY), "STRING", "Number of Bots: ", HUD_COLOUR_GREY)
SET_TEXT_SCALE(0.0000, fTextScale)
SET_TEXT_COLOUR(128,128,128, 255)
DISPLAY_TEXT_WITH_NUMBER(fTextX + fNoBotsIntX, fTextY + (iRowCount * fLineSpacerY), "NUMBER", GET_NUMBER_OF_BOTS())
iRowCount += 1
// draw time bars
fThisHeight = ((iNumberOfRows - 2) * fLineSpacerY)
SET_TEXT_SCALE(0.0000, fTextScale)
SET_TEXT_COLOUR(128,128,128, 64)
DISPLAY_TEXT_WITH_PLAYER_NAME(fTextX + fTimeBarX + (fBarWidthPerMS * -0.5), fTextY + ((iNumberOfRows+1)*fLineSpacerY), "STRING", "ms", HUD_COLOUR_GREY)
REPEAT 21 i
SET_TEXT_SCALE(0.0000, fTextScale)
SET_TEXT_COLOUR(128,128,128, 128)
DISPLAY_TEXT_WITH_NUMBER(fTextX + fTimeBarX + (fBarWidthPerMS * TO_FLOAT(i)), fTextY + ((iNumberOfRows+1)*fLineSpacerY), "NUMBER", i)
DRAW_RECT_FROM_CORNER(fTextX + fTimeBarX + (fBarWidthPerMS * TO_FLOAT(i)), fTextY + (2*fLineSpacerY) , 0.001, fThisHeight, 128, 128, 128, 64)
ENDREPEAT
// each script
fTotalCurrentTime = 0.0
fTotalAverageTime = 0.0
iThreadCount = 0
// iterate through each script
SCRIPT_THREAD_ITERATOR_RESET()
Thread_ID = SCRIPT_THREAD_ITERATOR_GET_NEXT_THREAD_ID()
WHILE IS_THREAD_ACTIVE(Thread_ID)
IF NOT SHOULD_IGNORE_THREAD(Thread_ID)
// thread name
ScriptName = GET_NAME_OF_SCRIPT_WITH_THIS_ID(Thread_ID)
SET_TEXT_SCALE(0.0000, fTextScale)
SET_TEXT_COLOUR(128,128,128, 255)
DISPLAY_TEXT_WITH_PLAYER_NAME(fTextX, fTextY + (iRowCount * fLineSpacerY), "STRING", ScriptName, HUD_COLOUR_GREY)
// current time - bar
fThisTime = METRICS_GET_UPDATE_TIME_FOR_THREAD(Thread_ID)
fTotalCurrentTime += fThisTime
fThisWidth = fThisTime * fBarWidthPerMS
DRAW_RECT_FROM_CORNER(fTextX + fTimeBarX, fTextY + (iRowCount * fLineSpacerY) + (fBarHeight * 0.5), fThisWidth, fBarHeight, 255, 216, 0, 255)
// average time
SET_TEXT_SCALE(0.0000, fTextScale)
SET_TEXT_COLOUR(255, 255, 0, 255)
fThisTime = METRICS_GET_AVERAGE_UPDATE_TIME_FOR_THREAD(Thread_ID)
fTotalAverageTime += fThisTime
IF (bRenderNumbers)
DISPLAY_TEXT_WITH_FLOAT(fTextX + fAverageTimeX, fTextY + (iRowCount * fLineSpacerY), "NUMBER", fThisTime, 2)
ENDIF
// Peak time
fThisPeakTime = METRICS_GET_PEAK_UPDATE_TIME_FOR_THREAD(Thread_ID)
fThisWidth = fThisPeakTime * fBarWidthPerMS
SET_TEXT_SCALE(0.0000, fTextScale)
IF ((fThisPeakTime - fThisTime) > 1.0)
SET_TEXT_COLOUR(255, 0, 0, 255)
DRAW_RECT_FROM_CORNER(fTextX + fTimeBarX + fThisWidth, fTextY + (iRowCount * fLineSpacerY) + (fBarHeight * 0.5), 0.001, fBarHeight, 255, 0, 0, 255)
IF (bRenderPeaks)
DISPLAY_TEXT_WITH_FLOAT(fTextX + fPeakTimeX , fTextY + (iRowCount * fLineSpacerY), "NUMBER", fThisPeakTime, 2)
ENDIF
ELSE
SET_TEXT_COLOUR(255, 106, 0, 255)
DRAW_RECT_FROM_CORNER(fTextX + fTimeBarX + fThisWidth, fTextY + (iRowCount * fLineSpacerY) + (fBarHeight * 0.5), 0.001, fBarHeight, 255, 106, 0, 255)
IF (bRenderNumbers)
//DISPLAY_TEXT_WITH_FLOAT(fTextX + fPeakTimeX , fTextY + (iRowCount * fLineSpacerY), "NUMBER", fThisPeakTime, 2)
ENDIF
ENDIF
// stored peak time
IF (bRenderStoredPeaks)
IF (fThisPeakTime > fStoredPeakTime[iThreadCount])
PRINTSTRING("[SCRIPT METRICS] New highest peak recorded for ")
PRINTSTRING(ScriptName)
PRINTSTRING(" of ")
PRINTFLOAT(fThisPeakTime)
PRINTNL()
fStoredPeakTime[iThreadCount] = fThisPeakTime
ENDIF
IF (fStoredPeakTime[iThreadCount] > 0.0)
fThisWidth = fStoredPeakTime[iThreadCount] * fBarWidthPerMS
DRAW_RECT_FROM_CORNER(fTextX + fTimeBarX + fThisWidth, fTextY + (iRowCount * fLineSpacerY) + (fBarHeight * 0.5), 0.001, fBarHeight, 255, 0, 255, 255)
ENDIF
ENDIF
iRowCount += 1
iThreadCount += 1
ENDIF
Thread_ID = SCRIPT_THREAD_ITERATOR_GET_NEXT_THREAD_ID()
ENDWHILE
IF (bRenderStoredPeaks)
IF NOT (iTotalThreadsLastFrame = 0)
IF NOT (iTotalThreadsLastFrame = iThreadCount)
REPEAT MAX_NO_THREADS i
fStoredPeakTime[i] = 0.0
ENDREPEAT
ENDIF
ENDIF
IF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_NUMPAD5)
REPEAT MAX_NO_THREADS i
fStoredPeakTime[i] = 0.0
ENDREPEAT
ENDIF
iTotalThreadsLastFrame = iThreadCount
ENDIF
// draw totals
IF (fTotalCurrentTime > fTotalPeakTime)
fTotalPeakTime = fTotalCurrentTime
SETTIMERB(0)
ELSE
IF TIMERB() > 10000
fTotalPeakTime = fTotalCurrentTime
ENDIF
ENDIF
// current
SET_TEXT_SCALE(0.0000, fTextScale)
SET_TEXT_COLOUR(128,128,128, 255)
fThisWidth = fTotalCurrentTime * fBarWidthPerMS
DISPLAY_TEXT_WITH_PLAYER_NAME(fTextX, fTextY + (iRowCount * fLineSpacerY), "STRING", "TOTAL", HUD_COLOUR_GREY)
DRAW_RECT_FROM_CORNER(fTextX + fTimeBarX, fTextY + (iRowCount * fLineSpacerY) + (fBarHeight * 0.5), fThisWidth, fBarHeight, 255, 216, 0, 255)
// average
SET_TEXT_SCALE(0.0000, fTextScale)
SET_TEXT_COLOUR(255, 255, 0, 255)
IF (bRenderNumbers)
DISPLAY_TEXT_WITH_FLOAT(fTextX + fTotalAverageTime, fTextY + (iRowCount * fLineSpacerY), "NUMBER", fTotalAverageTime, 2)
ENDIF
// peak time
fThisWidth = fTotalPeakTime * fBarWidthPerMS
SET_TEXT_SCALE(0.0000, fTextScale)
IF ((fTotalPeakTime - fTotalAverageTime) > 1.0)
SET_TEXT_COLOUR(255, 0, 0, 255)
DRAW_RECT_FROM_CORNER(fTextX + fTimeBarX + fThisWidth, fTextY + (iRowCount * fLineSpacerY) + (fBarHeight * 0.5), 0.001, fBarHeight, 255, 0, 0, 255)
IF (bRenderPeaks)
DISPLAY_TEXT_WITH_FLOAT(fTextX + fPeakTimeX , fTextY + (iRowCount * fLineSpacerY), "NUMBER", fTotalPeakTime, 2)
ENDIF
ELSE
SET_TEXT_COLOUR(255, 106, 0, 255)
DRAW_RECT_FROM_CORNER(fTextX + fTimeBarX + fThisWidth, fTextY + (iRowCount * fLineSpacerY) + (fBarHeight * 0.5), 0.001, fBarHeight, 255, 106, 0, 255)
IF (bRenderNumbers)
//DISPLAY_TEXT_WITH_FLOAT(fTextX + fPeakTimeX , fTextY + (iRowCount * fLineSpacerY), "NUMBER", fTotalPeakTime, 2)
ENDIF
ENDIF
iRowCount += 1
iNumberOfRows = iRowCount
ENDIF
// check if sever wants us to record
IF NETWORK_IS_GAME_IN_PROGRESS()
IF (GlobalServerBD.g_bRecordScriptMetrics)
IF NOT (bStartRecording)
bStartRecording = TRUE
ENDIF
ELSE
IF NOT IS_TRANSITION_SESSION_LAUNCHING()
AND NOT IS_TRANSITION_SESSION_KILLING_SESSION()
IF (bStartRecording)
bStartRecording = FALSE
PRINTSTRING("[SCRIPT METRICS] bStartRecording = FALSE, network game not in progress ") PRINTNL()
ENDIF
ENDIF
ENDIF
ENDIF
// output
IF NOT (bStartRecording)
IF (b_ScriptMetricsAreRecording)
PRINTSTRING("script_metrics - stopping recording") PRINTNL()
PRINT_NOW("SM_STOP", 5000, 1)
b_ScriptMetricsAreRecording = FALSE
CLOSE_DEBUG_FILE()
ENDIF
ELSE
IF NOT (b_ScriptMetricsAreRecording)
PRINT_ALL_METRIC_INFO_TO_CHANNEL()
b_ScriptMetricsAreRecording = TRUE
PRINT_NOW("SM_START", 5000, 1)
SETTIMERA(0)
OPEN_NAMED_DEBUG_FILE(DebugFilePath, DebugFileName)
CLEAR_NAMED_DEBUG_FILE(DebugFilePath, DebugFileName)
ELSE
IF (iRecordingInterval > 0)
IF (TIMERA() > iRecordingInterval)
IF (bTurnOnFileWriting)
ADD_SCRIPT_METRIC_MARKER("Grabbing metric info")
ENDIF
PRINT_ALL_METRIC_INFO_TO_CHANNEL()
SETTIMERA(0)
ENDIF
ELSE
PRINT_ALL_METRIC_INFO_TO_CHANNEL()
ENDIF
ENDIF
ENDIF
// IF (bEnableCloudUploading)
// IF (bUploadToCloud)
//
// IF NOT (bUploadingToCloud)
// IF DATAFILE_START_SAVE_TO_CLOUD(CloudFilename)
// bUploadingToCloud = TRUE
// NET_PRINT("[script_metrics] Started to upload to cloud") NET_NL()
// ELSE
// NET_PRINT("[script_metrics] Starting to upload to cloud...") NET_NL()
// ENDIF
// ELSE
// NET_PRINT("[script_metrics] Uploading to cloud...") NET_NL()
// IF DATAFILE_UPDATE_SAVE_TO_CLOUD(bSuccessfulUploadToCloud)
// IF (bSuccessfulUploadToCloud)
// NET_PRINT("[script_metrics] Successfully uploaded to cloud") NET_NL()
// ELSE
// NET_PRINT("[script_metrics] Failed uploading to cloud") NET_NL()
// ENDIF
// IF DATAFILE_GET_FILE_DICT() != NULL
// DATAFILE_DELETE()
// ENDIF
// bUploadToCloud = FALSE
// bUploadingToCloud = FALSE
// bDownloadFromCloud = TRUE
// ENDIF
// ENDIF
//
// ENDIF
//
// IF (bDownloadFromCloud)
//
// IF NOT (bDownloadingFromCloud)
// IF DATAFILE_GET_FILE_DICT() != NULL
// NET_PRINT("[script_metrics] deleting existing datfile...") NET_NL()
// DATAFILE_DELETE()
// ELSE
// IF DATAFILE_START_LOAD_FROM_CLOUD(CloudFilename)
// bDownloadingFromCloud = TRUE
// NET_PRINT("[script_metrics] Started to download from cloud") NET_NL()
// ELSE
// NET_PRINT("[script_metrics] Starting to download from cloud...") NET_NL()
// ENDIF
// ENDIF
// ELSE
// IF DATAFILE_UPDATE_LOAD_FROM_CLOUD(bSuccessfulDowloadFromCloud)
// IF (bSuccessfulDowloadFromCloud)
// NET_PRINT("[script_metrics] Successful download from cloud.") NET_NL()
// ELSE
// NET_PRINT("[script_metrics] Failed to download from cloud.") NET_NL()
// ENDIF
// bDownloadFromCloud = FALSE
// bDownloadingFromCloud = FALSE
// ELSE
// NET_PRINT("[script_metrics] Downloading from cloud...") NET_NL()
// ENDIF
// ENDIF
// ENDIF
// ENDIF
WAIT(0)
ENDWHILE
ENDSCRIPT
#ENDIF