////////////////////////////////////////////////////////////////////////////////////////// // // // SCRIPT NAME : stats_controller.sc // // AUTHOR : Kenneth Ross, Imran Scriptmaster making a comeback Sarwar // // DESCRIPTION : Sets up the default stat data for each player character. // // Displays stat updates whenever a player RPG stat has been // // modified. // // // ////////////////////////////////////////////////////////////////////////////////////////// USING "rage_builtins.sch" USING "globals.sch" USING "commands_script.sch" USING "stats_public.sch" USING "stats_private.sch" USING "player_ped_public.sch" USING "context_control_public.sch" USING "ambient_common.sch" USING "net_rank_rewards.sch" TWEAK_INT STAT_UPDATE_ALL_WHEELS_COOL_DOWN_TIME 1000 TWEAK_INT STAT_UPDATE_ALL_WHEELS_AIR_TIME 1500 TWEAK_INT STAT_UPDATE_ALL_WHEELS_LAND_TIME 20 ENUM STAS_INIT_ENUM INITIALISED_IN_SP, #IF FEATURE_COPS_N_CROOKS INITIALISED_IN_MP_ARCADE_CNC, #ENDIF #IF FEATURE_ENDLESS_WINTER INITIALISED_IN_MP_ARCADE_ENDLESS_WINTER, #ENDIF INITIALISED_IN_MP_FREEMODE, NOT_INITIALISED ENDENUM STAS_INIT_ENUM eInit = NOT_INITIALISED ENUM STAGE_CONTROL_ENUM SC_STAGE_INIT = 0, SC_STAGE_UPDATE, SC_STAGE_RESET ENDENUM STAGE_CONTROL_ENUM eStage = SC_STAGE_INIT INT iCurrentStat INT iStatUpdateDelay TIME_DATATYPE tdStatUpdateDelay enumCharacterList eCurrentStatPed BOOL bProcessAllStatsThisFrame BOOL bBlockStatIncrement BOOL bProcessFeed enumCharacterList eFeedChar PLAYER_STATS_ENUM eFeedStat INT iFeedTotal INT iFeedCurrent // Landing on all 4s check BOOL bPlayerLanding_CheckLand BOOL bPlayerLanding_CheckLand2 INT iPlayerLanding_AirTimer TIME_DATATYPE tdPlayerLanding_AirTimer INT iPlayerLanding_LandTimer TIME_DATATYPE tdPlayerLanding_LandTimer INT iPlayerLanding_CoolDownTimer TIME_DATATYPE tdPlayerLanding_CoolDownTimer // Top speed BOOL bTopSpeed_Check INT iTopSpeed_CoolDownTimer TIME_DATATYPE tdTopSpeed_CoolDownTimer // Wheelies INT iWheelieStatAtStartOfDay INT iWheelieStatUpdates INT iWheelieDayTimer BOOL bWheelieStartTimeSet BOOL bWheelieTrackAllowed /* Vehicle repair script - vehicle repair is to be removed INT iVehicleRepairControl BOOL bVehicleRepairScriptRequested INT iVehicleRepairContextID = NEW_CONTEXT_INTENTION VEHICLE_INDEX vehID_Repair */ BOOL bFeedDelayTimerSet INT iFeedDelayTimer TIME_DATATYPE tdFeedDelayTimer #IF IS_DEBUG_BUILD BOOL bKillPlayerCar = FALSE BOOL bUndrivePlayerCar = FALSE BOOL bBoostDrivingStat = FALSE BOOL bBashBoostDrivingStat = FALSE #ENDIF /// PURPOSE: Works out what the stat value should be based on code stats FUNC BOOL HAS_PLAYER_STAT_VALUE_INCREASED(enumCharacterList ePed, PLAYER_STATS_ENUM ePlayerStat, INT iCurrentStatValue, INT &iNewStatValue) iNewStatValue = CALCULATE_PLAYER_STAT_VALUE(ePed, ePlayerStat, FALSE) IF iNewStatValue > iCurrentStatValue RETURN TRUE ENDIF RETURN FALSE ENDFUNC PROC STAT_CHECK_4_WHEEL_LANDING(VEHICLE_INDEX &vehID, BOOL &bVehicleSafe) BOOL bClearFlagsAndSetCoolDown = FALSE IF bVehicleSafe IF bPlayerLanding_CheckLand // Player no longer in the air so check how long they were up for IF NOT IS_ENTITY_IN_AIR(vehID) IF (NOT NETWORK_IS_GAME_IN_PROGRESS() AND (GET_GAME_TIMER() - iPlayerLanding_AirTimer > STAT_UPDATE_ALL_WHEELS_AIR_TIME)) OR (NETWORK_IS_GAME_IN_PROGRESS() AND IS_TIME_MORE_THAN(GET_NETWORK_TIME(), GET_TIME_OFFSET(tdPlayerLanding_AirTimer, STAT_UPDATE_ALL_WHEELS_AIR_TIME))) iPlayerLanding_LandTimer = GET_GAME_TIMER() IF NETWORK_IS_GAME_IN_PROGRESS() tdPlayerLanding_LandTimer = GET_NETWORK_TIME() ENDIF bPlayerLanding_CheckLand2 = TRUE ENDIF bPlayerLanding_CheckLand = FALSE ENDIF ENDIF IF bPlayerLanding_CheckLand2 IF NOT IS_ENTITY_IN_AIR(vehID) IF IS_VEHICLE_ON_ALL_WHEELS(vehID) IF (NOT NETWORK_IS_GAME_IN_PROGRESS() AND (GET_GAME_TIMER() - iPlayerLanding_LandTimer > STAT_UPDATE_ALL_WHEELS_LAND_TIME)) OR (NOT NETWORK_IS_GAME_IN_PROGRESS() AND (GET_GAME_TIMER() - iPlayerLanding_LandTimer = 0)) OR (NETWORK_IS_GAME_IN_PROGRESS() AND IS_TIME_MORE_THAN(GET_NETWORK_TIME(), GET_TIME_OFFSET(tdPlayerLanding_LandTimer, STAT_UPDATE_ALL_WHEELS_LAND_TIME))) OR (NETWORK_IS_GAME_IN_PROGRESS() AND IS_TIME_EQUAL_TO(GET_NETWORK_TIME(), tdPlayerLanding_LandTimer)) // Failed to land in specified time ELSE // Managed to land in specificed time, woohoo INCREMENT_PLAYER_PED_STAT(eCurrentStatPed, PS_DRIVING_ABILITY, 1) ENDIF TEXT_LABEL_63 tlTimeToLand = "Player landed on all wheels in " tlTimeToLand += (GET_GAME_TIMER() - iPlayerLanding_LandTimer) tlTimeToLand += "ms" PRINTLN(tlTimeToLand) bClearFlagsAndSetCoolDown = TRUE ENDIF ELSE bClearFlagsAndSetCoolDown = TRUE ENDIF ENDIF IF NOT bPlayerLanding_CheckLand AND NOT bPlayerLanding_CheckLand2 IF (NOT NETWORK_IS_GAME_IN_PROGRESS() AND (GET_GAME_TIMER() - iPlayerLanding_CoolDownTimer > STAT_UPDATE_ALL_WHEELS_COOL_DOWN_TIME)) OR (NETWORK_IS_GAME_IN_PROGRESS() AND IS_TIME_MORE_THAN(GET_NETWORK_TIME(), GET_TIME_OFFSET(tdPlayerLanding_CoolDownTimer, STAT_UPDATE_ALL_WHEELS_COOL_DOWN_TIME))) IF IS_ENTITY_IN_AIR(vehID) // Player is in air so take a time stamp IF NOT bPlayerLanding_CheckLand iPlayerLanding_AirTimer = GET_GAME_TIMER() IF NETWORK_IS_GAME_IN_PROGRESS() tdPlayerLanding_AirTimer = GET_NETWORK_TIME() ENDIF bPlayerLanding_CheckLand = TRUE ENDIF ENDIF ENDIF ENDIF ELSE IF bPlayerLanding_CheckLand OR bPlayerLanding_CheckLand2 bClearFlagsAndSetCoolDown = TRUE ENDIF ENDIF IF bClearFlagsAndSetCoolDown iPlayerLanding_CoolDownTimer = GET_GAME_TIMER() IF NETWORK_IS_GAME_IN_PROGRESS() tdPlayerLanding_CoolDownTimer = GET_NETWORK_TIME() ENDIF bPlayerLanding_CheckLand = FALSE bPlayerLanding_CheckLand2 = FALSE ENDIF ENDPROC PROC STAT_CHECK_TOP_SPEED(VEHICLE_INDEX &vehID, BOOL &bVehicleSafe) IF bTopSpeed_Check BOOL bResetFlag = TRUE IF NOT IS_PED_INJURED(PLAYER_PED_ID()) AND bVehicleSafe AND NOT IS_ENTITY_IN_AIR(vehID) bResetFlag = FALSE IF GET_ENTITY_SPEED(vehID) >= 53.0 INCREMENT_PLAYER_PED_STAT(eCurrentStatPed, PS_DRIVING_ABILITY, 2) bResetFlag = TRUE ENDIF ENDIF IF bResetFlag bTopSpeed_Check = FALSE iTopSpeed_CoolDownTimer = GET_GAME_TIMER() IF NETWORK_IS_GAME_IN_PROGRESS() tdTopSpeed_CoolDownTimer = GET_NETWORK_TIME() ENDIF ENDIF ELSE IF NOT IS_PED_INJURED(PLAYER_PED_ID()) AND bVehicleSafe AND GET_ENTITY_SPEED(vehID) < 20.0 AND NOT IS_ENTITY_IN_AIR(vehID) IF (NOT NETWORK_IS_GAME_IN_PROGRESS() AND (GET_GAME_TIMER() - iTopSpeed_CoolDownTimer > 10000)) OR (NETWORK_IS_GAME_IN_PROGRESS() AND IS_TIME_MORE_THAN(GET_NETWORK_TIME(), GET_TIME_OFFSET(tdTopSpeed_CoolDownTimer, 10000))) bTopSpeed_Check = TRUE ENDIF ENDIF ENDIF ENDPROC PROC STAT_CHECK_WHEELIE() IF NOT bWheelieStartTimeSet IF eCurrentStatPed = CHAR_MULTIPLAYER IF g_savedMPGlobalsNew.g_savedMPGlobals[GET_SAVE_GAME_ARRAY_SLOT()].MpSavedGeneral.bGrabCurrentWheelieTime iWheelieStatAtStartOfDay = GET_TOTAL_NUMBER_OF_SECONDS_FOR_UNSIGNED_INT_STAT(GET_STAT_FROM_MP_INT_CHARACTER_STAT(MP_STAT_TOTAL_WHEELIE_TIME)) g_savedMPGlobalsNew.g_savedMPGlobals[GET_SAVE_GAME_ARRAY_SLOT()].MpSavedGeneral.bGrabCurrentWheelieTime = FALSE ELSE iWheelieStatAtStartOfDay = g_savedMPGlobalsNew.g_savedMPGlobals[GET_SAVE_GAME_ARRAY_SLOT()].MpSavedGeneral.iWheelieTimeAtStartOfDay ENDIF IF g_savedMPGlobalsNew.g_savedMPGlobals[GET_SAVE_GAME_ARRAY_SLOT()].MpSavedGeneral.iWheelieDayTimer = 0 g_savedMPGlobalsNew.g_savedMPGlobals[GET_SAVE_GAME_ARRAY_SLOT()].MpSavedGeneral.iWheelieDayTimer = GET_CLOUD_TIME_AS_INT() ENDIF iWheelieDayTimer = g_savedMPGlobalsNew.g_savedMPGlobals[GET_SAVE_GAME_ARRAY_SLOT()].MpSavedGeneral.iWheelieDayTimer iWheelieStatUpdates = g_savedMPGlobalsNew.g_savedMPGlobals[GET_SAVE_GAME_ARRAY_SLOT()].MpSavedGeneral.iWheelieUpdatesThisDay ELSE IF g_savedGlobals.sPlayerData.sInfo.bGrabCurrentWheelieTime[eCurrentStatPed] SWITCH eCurrentStatPed CASE CHAR_MICHAEL iWheelieStatAtStartOfDay = GET_TOTAL_NUMBER_OF_SECONDS_FOR_UNSIGNED_INT_STAT(SP0_TOTAL_WHEELIE_TIME) BREAK CASE CHAR_FRANKLIN iWheelieStatAtStartOfDay = GET_TOTAL_NUMBER_OF_SECONDS_FOR_UNSIGNED_INT_STAT(SP1_TOTAL_WHEELIE_TIME) BREAK CASE CHAR_TREVOR iWheelieStatAtStartOfDay = GET_TOTAL_NUMBER_OF_SECONDS_FOR_UNSIGNED_INT_STAT(SP2_TOTAL_WHEELIE_TIME) BREAK ENDSWITCH g_savedGlobals.sPlayerData.sInfo.bGrabCurrentWheelieTime[eCurrentStatPed] = FALSE ELSE iWheelieStatAtStartOfDay = g_savedGlobals.sPlayerData.sInfo.iWheelieTimeAtStartOfDay[eCurrentStatPed] ENDIF IF g_savedGlobals.sPlayerData.sInfo.iWheelieDayTimer[eCurrentStatPed] = 0 g_savedGlobals.sPlayerData.sInfo.iWheelieDayTimer[eCurrentStatPed] = GET_CLOUD_TIME_AS_INT() ENDIF iWheelieDayTimer = g_savedGlobals.sPlayerData.sInfo.iWheelieDayTimer[eCurrentStatPed] iWheelieStatUpdates = g_savedGlobals.sPlayerData.sInfo.iWheelieUpdatesThisDay[eCurrentStatPed] ENDIF bWheelieStartTimeSet = TRUE bWheelieTrackAllowed = TRUE ELSE #IF IS_DEBUG_BUILD IF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_PLUS) iWheelieDayTimer -= (60*60) ELIF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_MINUS) iWheelieDayTimer += (60*60) ENDIF #ENDIF // Reset some stats each time a day passes IF (GET_CLOUD_TIME_AS_INT() - iWheelieDayTimer) > (86400) bWheelieStartTimeSet = FALSE bWheelieTrackAllowed = FALSE iWheelieDayTimer = GET_CLOUD_TIME_AS_INT() iWheelieStatUpdates = 0 IF eCurrentStatPed = CHAR_MULTIPLAYER g_savedMPGlobalsNew.g_savedMPGlobals[GET_SAVE_GAME_ARRAY_SLOT()].MpSavedGeneral.bGrabCurrentWheelieTime = TRUE ELSE g_savedGlobals.sPlayerData.sInfo.bGrabCurrentWheelieTime[eCurrentStatPed] = TRUE ENDIF ENDIF ENDIF IF bWheelieTrackAllowed INT iWheelieStatCurrent SWITCH eCurrentStatPed CASE CHAR_MICHAEL iWheelieStatCurrent = GET_TOTAL_NUMBER_OF_SECONDS_FOR_UNSIGNED_INT_STAT(SP0_TOTAL_WHEELIE_TIME) BREAK CASE CHAR_FRANKLIN iWheelieStatCurrent = GET_TOTAL_NUMBER_OF_SECONDS_FOR_UNSIGNED_INT_STAT(SP1_TOTAL_WHEELIE_TIME) BREAK CASE CHAR_TREVOR iWheelieStatCurrent = GET_TOTAL_NUMBER_OF_SECONDS_FOR_UNSIGNED_INT_STAT(SP2_TOTAL_WHEELIE_TIME) BREAK CASE CHAR_MULTIPLAYER iWheelieStatCurrent = GET_TOTAL_NUMBER_OF_SECONDS_FOR_UNSIGNED_INT_STAT(GET_STAT_FROM_MP_INT_CHARACTER_STAT(MP_STAT_TOTAL_WHEELIE_TIME)) BREAK ENDSWITCH INT iStatDifference = (iWheelieStatCurrent-iWheelieStatAtStartOfDay) INT iStatIncrememnt = FLOOR((TO_FLOAT(iStatDifference)/15))-iWheelieStatUpdates // Give 1% boost for every 15 seconds of wheelie IF (iStatIncrememnt > 0) INCREMENT_PLAYER_PED_STAT(eCurrentStatPed, PS_DRIVING_ABILITY, iStatIncrememnt) iWheelieStatUpdates += iStatIncrememnt ENDIF // Only allow the player to get this stat for 1 in-game hour worth of wheelie IF (iWheelieStatCurrent > (iWheelieStatAtStartOfDay+((GET_MILLISECONDS_PER_GAME_MINUTE()/1000)*60))) bWheelieTrackAllowed = FALSE ENDIF ENDIF // Update save data IF eCurrentStatPed = CHAR_MULTIPLAYER g_savedMPGlobalsNew.g_savedMPGlobals[GET_SAVE_GAME_ARRAY_SLOT()].MpSavedGeneral.iWheelieDayTimer = iWheelieDayTimer g_savedMPGlobalsNew.g_savedMPGlobals[GET_SAVE_GAME_ARRAY_SLOT()].MpSavedGeneral.iWheelieUpdatesThisDay = iWheelieStatUpdates ELSE g_savedGlobals.sPlayerData.sInfo.iWheelieDayTimer[eCurrentStatPed] = iWheelieDayTimer g_savedGlobals.sPlayerData.sInfo.iWheelieUpdatesThisDay[eCurrentStatPed] = iWheelieStatUpdates ENDIF ENDPROC PROC DO_PROCESS_SCRIPT_STAT_UPDATES() VEHICLE_INDEX vehID BOOL bVehicleSafe = FALSE IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) vehID = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()) IF DOES_ENTITY_EXIST(vehID) AND IS_VEHICLE_DRIVEABLE(vehID) AND GET_PED_IN_VEHICLE_SEAT(vehID, VS_DRIVER) = PLAYER_PED_ID() AND (IS_THIS_MODEL_A_CAR(GET_ENTITY_MODEL(vehID)) OR IS_THIS_MODEL_A_BIKE(GET_ENTITY_MODEL(vehID)) OR IS_THIS_MODEL_A_BICYCLE(GET_ENTITY_MODEL(vehID)) OR IS_THIS_MODEL_A_QUADBIKE(GET_ENTITY_MODEL(vehID))) bVehicleSafe = TRUE ENDIF ENDIF STAT_CHECK_4_WHEEL_LANDING(vehID, bVehicleSafe) STAT_CHECK_TOP_SPEED(vehID, bVehicleSafe) STAT_CHECK_WHEELIE() ENDPROC /// PURPOSE: Reset data and make copy of current stat values PROC DO_INITIALISE() IF GET_INDEX_OF_CURRENT_LEVEL() != LEVEL_GTA5 #IF IS_DEBUG_BUILD IF g_bDisplayShopDebug PRINTSTRING("\n stats_controller: Init - not in LEVEL_GTA5.")PRINTNL() ENDIF #ENDIF EXIT ENDIF // Wait for MP player to be in main game IF NETWORK_IS_GAME_IN_PROGRESS() IF NOT IS_PLAYER_ACTIVE_IN_MP_LAUNCH_SCRIPT(PLAYER_ID()) EXIT ENDIF IF GET_CURRENT_GAMEMODE() != GAMEMODE_FM EXIT ENDIF ENDIF IF NETWORK_IS_GAME_IN_PROGRESS() IF GET_CURRENT_GAMEMODE() = GAMEMODE_FM #IF FEATURE_FREEMODE_ARCADE IF IS_FREEMODE_ARCADE() SWITCH GET_ARCADE_MODE() #IF FEATURE_COPS_N_CROOKS CASE ARC_COPS_CROOKS eInit = INITIALISED_IN_MP_ARCADE_CNC PRINTSTRING("\n stats_controller: INITIALISING in FM Arcade - CNC")PRINTNL() BREAK #ENDIF #IF FEATURE_ENDLESS_WINTER CASE ARC_ENDLESS_WINTER eInit = INITIALISED_IN_MP_ARCADE_ENDLESS_WINTER PRINTSTRING("\n stats_controller: INITIALISING in FM Arcade - Endless winter")PRINTNL() BREAK #ENDIF DEFAULT SCRIPT_ASSERT("DO_INITIALISE - Unknown arcade mode!") BREAK ENDSWITCH ELSE #ENDIF eInit = INITIALISED_IN_MP_FREEMODE PRINTSTRING("\n stats_controller: INITIALISING in FM")PRINTNL() #IF FEATURE_FREEMODE_ARCADE ENDIF #ENDIF ENDIF ELSE eInit = INITIALISED_IN_SP PRINTSTRING("\n stats_controller: INITIALISING in SP")PRINTNL() ENDIF IF NOT HAVE_DEFAULT_PLAYER_STATS_BEEN_SET() SETUP_DEFAULT_PLAYER_STATS() ENDIF iCurrentStat = 0 iStatUpdateDelay = 0 IF NETWORK_IS_GAME_IN_PROGRESS() tdStatUpdateDelay = GET_NETWORK_TIME() ENDIF iPlayerLanding_CoolDownTimer = GET_GAME_TIMER() IF NETWORK_IS_GAME_IN_PROGRESS() tdPlayerLanding_CoolDownTimer = GET_NETWORK_TIME() ENDIF // Fix for Strength stat getting reset back to 0 IF NETWORK_IS_GAME_IN_PROGRESS() IF NOT IS_BIT_SET(g_savedMPGlobalsNew.g_savedMPGlobals[GET_SAVE_GAME_ARRAY_SLOT()].MpSavedGeneral.iGeneralBS,MP_SAVE_GENERAL_BS_STRENGTH_PATCHED) FLOAT fFinalStatValue = (TO_FLOAT(GET_MP_INT_CHARACTER_STAT(MP_STAT_UNARMED_HITS)) / 20) INT iFinalStatValue = FLOOR(fFinalStatValue) iFinalStatValue = CLAMP_INT(iFinalStatValue, 0, 100) INCREMENT_PLAYER_PED_STAT(CHAR_MULTIPLAYER, PS_STRENGTH, iFinalStatValue) SET_BIT(g_savedMPGlobalsNew.g_savedMPGlobals[GET_SAVE_GAME_ARRAY_SLOT()].MpSavedGeneral.iGeneralBS,MP_SAVE_GENERAL_BS_STRENGTH_PATCHED) PRINTLN("STRENGTH STAT HAS BEEN PATCHED - ", iFinalStatValue) ENDIF ENDIF bProcessAllStatsThisFrame = TRUE eStage = SC_STAGE_UPDATE ENDPROC PROC DO_FEED_UPDATE_FOR_STAT() IF bProcessFeed IF eFeedChar != eCurrentStatPed bProcessFeed = FALSE EXIT ENDIF STRING sChar = "CHAR_DEFAULT" SWITCH eFeedChar CASE CHAR_MICHAEL sChar = "CHAR_MICHAEL" BREAK CASE CHAR_FRANKLIN sChar = "CHAR_FRANKLIN" BREAK CASE CHAR_TREVOR sChar = "CHAR_TREVOR" BREAK CASE CHAR_MULTIPLAYER PEDHEADSHOT_ID theHeadshotID theHeadshotID = Get_HeadshotID_For_Player(PLAYER_ID()) IF (theHeadshotID = NULL) // wait for this to generate... EXIT ELSE sChar = GET_PEDHEADSHOT_TXD_STRING(theHeadshotID) ENDIF BREAK ENDSWITCH PRINTLN("DO_FEED_UPDATE_FOR_STAT") PRINTLN("...iFeedTotal = ", iFeedTotal) PRINTLN("...iFeedCurrent = ", iFeedCurrent) BEGIN_TEXT_COMMAND_THEFEED_POST("PS_UPDATE") ADD_TEXT_COMPONENT_INTEGER(iFeedCurrent) END_TEXT_COMMAND_THEFEED_POST_STATS(GET_PLAYER_STAT_FEED_NAME(eFeedStat), GET_PLAYER_STAT_FEED_ICON(eFeedStat), iFeedTotal, iFeedCurrent-iFeedTotal, FALSE, sChar, sChar) // Fix fo bug #1370214 - Can we have it so the stats don't increase all at the same time. // Default time is 3000ms so make sure we have a 6000ms delay between feed updates. bFeedDelayTimerSet = TRUE iFeedDelayTimer = GET_GAME_TIMER()+5000 IF NETWORK_IS_GAME_IN_PROGRESS() tdFeedDelayTimer = GET_TIME_OFFSET(GET_NETWORK_TIME(), 5000) ENDIF bProcessFeed = FALSE ENDIF ENDPROC /// PURPOSE: Check for any player RPG stats getting updated PROC DO_CHECK_FOR_STAT_UPDATE() // We only process one stat per frame so increment IF bBlockStatIncrement bBlockStatIncrement = FALSE ELSE iCurrentStat++ ENDIF bProcessAllStatsThisFrame = FALSE // Determine which character we need to process enumCharacterList ePedToProcess IF NETWORK_IS_GAME_IN_PROGRESS() ePedToProcess = CHAR_MULTIPLAYER ELSE ePedToProcess = GET_CURRENT_PLAYER_PED_ENUM() ENDIF IF ePedToProcess != eCurrentStatPed eCurrentStatPed = ePedToProcess // Process all stats now bProcessAllStatsThisFrame = TRUE // Clear some flags bPlayerLanding_CheckLand = FALSE bPlayerLanding_CheckLand2 = FALSE bTopSpeed_Check = FALSE bWheelieStartTimeSet = FALSE ENDIF // Switching sessions so wait. IF eCurrentStatPed = NO_CHARACTER EXIT ENDIF // Bail out if it's not safe to process stats BOOL bIgnoreBailChecks = FALSE IF ((iCurrentStat = ENUM_TO_INT(PS_SHOOTING_ABILITY)) AND IS_SHOOTING_RANGE_UNSAVED_BITFLAG_SET(SRB_RangeInSession)) OR ((iCurrentStat = ENUM_TO_INT(PS_FLYING_ABILITY)) AND GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("pilot_school")) > 0) bIgnoreBailChecks = TRUE bBlockStatIncrement = TRUE ENDIF // See if we can increment stats #IF FEATURE_FREEMODE_ARCADE IF NOT IS_FREEMODE_ARCADE() #ENDIF DO_PROCESS_SCRIPT_STAT_UPDATES() #IF FEATURE_FREEMODE_ARCADE ENDIF #ENDIF // Perform any routine updates IF (g_bPerformCustomStatUpdate) OR (g_bPerformCustomStatUpdateWhenMissionEnds AND NOT IS_CURRENTLY_ON_MISSION_TO_TYPE()) IF NOT IS_PED_INJURED(PLAYER_PED_ID()) INT iCustomStatUpdate REPEAT NUMBER_OF_PLAYER_STATS iCustomStatUpdate UPDATE_PLAYER_STAT_SETTINGS(eCurrentStatPed, INT_TO_ENUM(PLAYER_STATS_ENUM, iCustomStatUpdate)) ENDREPEAT g_bPerformCustomStatUpdate = FALSE ENDIF ENDIF IF NOT bIgnoreBailChecks IF IS_PED_INJURED(PLAYER_PED_ID()) OR (NOT NETWORK_IS_GAME_IN_PROGRESS() AND NOT IS_PLAYER_PED_PLAYABLE(eCurrentStatPed)) OR IS_PLAYER_SWITCH_IN_PROGRESS() OR IS_PLAYER_PED_SWITCH_IN_PROGRESS() OR IS_CUTSCENE_PLAYING() OR IS_SCREEN_FADED_OUT() OR NOT IS_PLAYER_CONTROL_ON(PLAYER_ID()) OR g_bScriptsSetSafeForCutscene OR g_bDisableStatUpdatesThisFrame OR bProcessFeed /*IF IS_PED_INJURED(PLAYER_PED_ID()) PRINTLN("Not safe to display stats - ped injured") ELIF (NOT NETWORK_IS_GAME_IN_PROGRESS() AND NOT IS_PLAYER_PED_PLAYABLE(eCurrentStatPed)) PRINTLN("Not safe to display stats - not playable character") ELIF IS_PLAYER_SWITCH_IN_PROGRESS() PRINTLN("Not safe to display stats - switching (code)") ELIF IS_PLAYER_PED_SWITCH_IN_PROGRESS() PRINTLN("Not safe to display stats - switching (script)") ELIF IS_CUTSCENE_PLAYING() PRINTLN("Not safe to display stats - cutscene playing") ELIF NOT IS_PLAYER_CONTROL_ON(PLAYER_ID()) PRINTLN("Not safe to display stats - no player control") ELIF g_bScriptsSetSafeForCutscene PRINTLN("Not safe to display stats - cutscene flag set") ENDIF*/ bFeedDelayTimerSet = TRUE iFeedDelayTimer = GET_GAME_TIMER() IF NETWORK_IS_GAME_IN_PROGRESS() tdFeedDelayTimer = GET_NETWORK_TIME() ENDIF EXIT ENDIF IF (bFeedDelayTimerSet) IF (NOT NETWORK_IS_GAME_IN_PROGRESS() AND GET_GAME_TIMER() - iFeedDelayTimer > 3000) OR (NETWORK_IS_GAME_IN_PROGRESS() AND IS_TIME_MORE_THAN(GET_NETWORK_TIME(), GET_TIME_OFFSET(tdFeedDelayTimer, 3000))) bFeedDelayTimerSet = FALSE ELSE //PRINTLN("Not safe to display stats - timer delay set") EXIT ENDIF ENDIF ENDIF // Wait for the delay to pass IF (NOT NETWORK_IS_GAME_IN_PROGRESS() AND ((GET_GAME_TIMER() - iStatUpdateDelay) > 2000)) OR (NETWORK_IS_GAME_IN_PROGRESS() AND (IS_TIME_MORE_THAN(GET_NETWORK_TIME(), GET_TIME_OFFSET(tdStatUpdateDelay, 2000)))) OR bProcessAllStatsThisFrame // If we have done a loop, delay the next stat process. IF iCurrentStat >= NUMBER_OF_PLAYER_STATS iCurrentStat = 0 iStatUpdateDelay = GET_GAME_TIMER() IF NETWORK_IS_GAME_IN_PROGRESS() tdStatUpdateDelay = GET_NETWORK_TIME() ENDIF ENDIF INT iCurrentStatValue, iNewStatValue, iCurrentStatValuePreClamp STATSENUM eSPStat MP_INT_STATS eMPStat PLAYER_STATS_ENUM eStatToProcess STATSENUM eSPMaxTimeStat INT iTime INT iStatsToProcess = 1 IF bProcessAllStatsThisFrame iStatsToProcess = NUMBER_OF_PLAYER_STATS ENDIF INT iStatLoop REPEAT iStatsToProcess iStatLoop BOOL bDisplayStatUpdate = TRUE IF bProcessAllStatsThisFrame eStatToProcess = INT_TO_ENUM(PLAYER_STATS_ENUM, iStatLoop) ELSE eStatToProcess = INT_TO_ENUM(PLAYER_STATS_ENUM, iCurrentStat) ENDIF // Grab the stat value GET_PLAYER_PED_STAT_ENUM(eCurrentStatPed, eStatToProcess, eSPStat, eMPStat) IF NETWORK_IS_GAME_IN_PROGRESS() iCurrentStatValue = GET_MP_INT_CHARACTER_STAT(eMPStat) ELSE IF eStatToProcess = PS_SPECIAL_ABILITY iCurrentStatValue = g_savedGlobals.sPlayerData.sInfo.iTrackedSpecialAbilityUnlock[eCurrentStatPed] ELSE STAT_GET_INT(eSPStat, iCurrentStatValue) ENDIF ENDIF // Keep value in the range of 0-100 iCurrentStatValuePreClamp = iCurrentStatValue iCurrentStatValue = CLAMP_INT(iCurrentStatValue, 0, 100) // Update stat if it has changed IF HAS_PLAYER_STAT_VALUE_INCREASED(eCurrentStatPed, eStatToProcess, iCurrentStatValue, iNewStatValue) IF NETWORK_IS_GAME_IN_PROGRESS() SET_MP_INT_CHARACTER_STAT(eMPStat, iNewStatValue) ELSE IF eStatToProcess = PS_SPECIAL_ABILITY IF g_savedGlobals.sPlayerData.sInfo.iTrackedSpecialAbilityUnlock[eCurrentStatPed] = 0 // Ignore first speical ability stat update. bDisplayStatUpdate = FALSE ENDIF g_savedGlobals.sPlayerData.sInfo.iTrackedSpecialAbilityUnlock[eCurrentStatPed] = iNewStatValue ELSE STAT_SET_INT(eSPStat, iNewStatValue) ENDIF ENDIF #IF IS_DEBUG_BUILD PRINTLN(GET_STRING_FROM_TEXT_FILE(GET_PLAYER_STAT_FEED_NAME(eStatToProcess)), " has increased from ", iCurrentStatValue, " to ", iNewStatValue, " for ", GET_PLAYER_PED_STRING(eCurrentStatPed)) #ENDIF // Display on the feed IF iNewStatValue > GET_INITIAL_STAT_VALUE(eCurrentStatPed, eStatToProcess) IF NETWORK_IS_GAME_IN_PROGRESS() #IF FEATURE_FREEMODE_ARCADE IF IS_FREEMODE_ARCADE() bDisplayStatUpdate = FALSE ENDIF #ENDIF IF NETWORK_IS_ACTIVITY_SESSION() AND IS_BIT_SET(g_FMMC_STRUCT.iOptionsMenuBitSetTwentyNine, ciOptionsBS29_SimulateSinglePlayerHUD) bDisplayStatUpdate = FALSE ENDIF ELSE IF (NOT g_savedGlobals.sFlow.isGameflowActive AND NOT IS_REPEAT_PLAY_ACTIVE()) OR NOT IS_BIT_SET(g_savedGlobals.sFlow.strandSavedVars[STRAND_PROLOGUE].savedBitflags,SAVED_BITS_STRAND_TERMINATED) bDisplayStatUpdate = FALSE ENDIF ENDIF // Only display in feed if we have reached a milestone. INT iFinalStatValue = iNewStatValue INT iNextStep = (iFinalStatValue-((iFinalStatValue%GET_FEED_UPDATE_FREQ(eCurrentStatPed, eStatToProcess)))) IF (iFinalStatValue%GET_FEED_UPDATE_FREQ(eCurrentStatPed, eStatToProcess) >= 0) iNextStep += GET_FEED_UPDATE_FREQ(eCurrentStatPed, eStatToProcess) ENDIF IF iFinalStatValue >= iNextStep iFinalStatValue = iNextStep ELSE iFinalStatValue = (iNextStep-GET_FEED_UPDATE_FREQ(eCurrentStatPed, eStatToProcess)) ENDIF IF iNewStatValue > iFinalStatValue bDisplayStatUpdate = FALSE ENDIF IF IS_GOON_ELIGABLE_FOR_STAT_BOOST() // disable feed if its for bonus gang boss stat increase (bug 2595234) PRINTLN("DO_CHECK_FOR_STAT_UPDATE disable feed if its for bonus gang boss stat increase (bug 2595234) bDisplayStatUpdate = FALSE ") bDisplayStatUpdate = FALSE ENDIF IF bDisplayStatUpdate IF NOT bProcessAllStatsThisFrame IF NETWORK_IS_GAME_IN_PROGRESS() IF GET_MP_BOOL_CHARACTER_STAT(MP_STAT_FM_CHAR_STATS1) = FALSE IF NOT IS_HELP_MESSAGE_BEING_DISPLAYED() AND CAN_DRAW_UNLOCKS_SCALEFORM() PRINT_HELP("STAT_HELP2") PRINTLN("PRINT_HELP(CHECK_AND_DISPLAY_HELP_TEXT_FOR_STATS STAT_HELP2)") SET_MP_BOOL_CHARACTER_STAT(MP_STAT_FM_CHAR_STATS1, TRUE) ENDIF ENDIF ENDIF bProcessFeed = TRUE iFeedTotal = iNewStatValue-iCurrentStatValue // Fix for bug 1541985 - flash the whole bar iFeedTotal += (iCurrentStatValue%GET_FEED_UPDATE_FREQ(eCurrentStatPed, eStatToProcess)) iFeedCurrent = iNewStatValue eFeedChar = eCurrentStatPed eFeedStat = eStatToProcess ENDIF ENDIF // Maxed out? IF iNewStatValue >= 100 IF GET_PLAYER_PED_MAXED_STAT_ENUM(eCurrentStatPed, eStatToProcess, eSPMaxTimeStat) #IF IS_DEBUG_BUILD PRINTLN(GET_STRING_FROM_TEXT_FILE(GET_PLAYER_STAT_FEED_NAME(eStatToProcess)), " has maxed out for ", GET_PLAYER_PED_STRING(eCurrentStatPed)) #ENDIF IF eCurrentStatPed = CHAR_MICHAEL STAT_GET_INT(SP0_TOTAL_PLAYING_TIME, iTime) STAT_SET_INT(eSPMaxTimeStat, iTime) ELIF eCurrentStatPed = CHAR_FRANKLIN STAT_GET_INT(SP1_TOTAL_PLAYING_TIME, iTime) STAT_SET_INT(eSPMaxTimeStat, iTime) ELIF eCurrentStatPed = CHAR_TREVOR STAT_GET_INT(SP2_TOTAL_PLAYING_TIME, iTime) STAT_SET_INT(eSPMaxTimeStat, iTime) ELIF eCurrentStatPed = CHAR_MULTIPLAYER ENDIF ENDIF ENDIF ENDIF UPDATE_PLAYER_STAT_SETTINGS(eCurrentStatPed, eStatToProcess) // If the stat has reduced, set it but do not display on feed ELIF iNewStatValue < iCurrentStatValuePreClamp BOOL bUpdateStatSettings = TRUE IF NETWORK_IS_GAME_IN_PROGRESS() SET_MP_INT_CHARACTER_STAT(eMPStat, iNewStatValue) ELSE IF eStatToProcess = PS_SPECIAL_ABILITY g_savedGlobals.sPlayerData.sInfo.iTrackedSpecialAbilityUnlock[eCurrentStatPed] = iNewStatValue bUpdateStatSettings = FALSE ELSE STAT_SET_INT(eSPStat, iNewStatValue) ENDIF ENDIF IF bUpdateStatSettings #IF IS_DEBUG_BUILD PRINTLN(GET_STRING_FROM_TEXT_FILE(GET_PLAYER_STAT_FEED_NAME(eStatToProcess)), " has decreased from ", iCurrentStatValue, " to ", iNewStatValue, " for ", GET_PLAYER_PED_STRING(eCurrentStatPed)) #ENDIF UPDATE_PLAYER_STAT_SETTINGS(eCurrentStatPed, eStatToProcess) ENDIF ENDIF ENDREPEAT ELSE bBlockStatIncrement = TRUE ENDIF ENDPROC /* [AG]: VEHICLE REPAIR IS BEING REMOVED /// PURPOSE: Launch the vehicle repair minigame when player is trying to interact with a broken down vehicle PROC DO_VEHICLE_REPAIR_PROCESSING() BOOL bDisplayContext = FALSE BOOL bVehicleRepairScriptRequired = FALSE SWITCH iVehicleRepairControl CASE 0 IF NOT IS_PED_INJURED(PLAYER_PED_ID()) AND NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) vehID_Repair = GET_CLOSEST_VEHICLE(GET_ENTITY_COORDS(PLAYER_PED_ID()), 5.0, DUMMY_MODEL_FOR_SCRIPT, VEHICLE_SEARCH_FLAG_RETURN_MISSION_VEHICLES | VEHICLE_SEARCH_FLAG_RETURN_RANDOM_VEHICLES) IF DOES_ENTITY_EXIST(vehID_Repair) AND NOT IS_VEHICLE_DRIVEABLE(vehID_Repair) AND NOT IS_ENTITY_ON_FIRE(vehID_Repair) AND GET_VEHICLE_ENGINE_HEALTH(vehID_Repair) >= 0 AND IS_VEHICLE_ON_ALL_WHEELS(vehID_Repair) AND GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) = 0 AND NOT IS_PED_RAGDOLL(PLAYER_PED_ID()) AND NOT IS_ENTITY_IN_WATER(PLAYER_PED_ID()) AND NOT IS_ENTITY_IN_WATER(vehID_Repair) AND NOT IS_VEHICLE_MODEL_ON_REPAIR_BLACKLIST(GET_ENTITY_MODEL(vehID_Repair)) AND IS_PLAYER_CONTROL_ON(PLAYER_ID()) REQUEST_SCRIPT("vehicleRepair") bVehicleRepairScriptRequested = TRUE bVehicleRepairScriptRequired = TRUE IF HAS_SCRIPT_LOADED("vehicleRepair") START_NEW_SCRIPT("vehicleRepair", SPECIAL_ABILITY_STACK_SIZE) iVehicleRepairControl++ ENDIF ENDIF ENDIF BREAK CASE 1 // Wait for the script to terminate IF GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("vehicleRepair")) = 0 iVehicleRepairControl = 0 ENDIF BREAK ENDSWITCH IF NOT bDisplayContext IF iVehicleRepairContextID != NEW_CONTEXT_INTENTION RELEASE_CONTEXT_INTENTION(iVehicleRepairContextID) iVehicleRepairContextID = NEW_CONTEXT_INTENTION ENDIF ENDIF IF NOT bVehicleRepairScriptRequired AND bVehicleRepairScriptRequested SET_SCRIPT_AS_NO_LONGER_NEEDED("vehicleRepair") bVehicleRepairScriptRequested = FALSE ENDIF ENDPROC */ PROC DO_RESET() eStage = SC_STAGE_INIT PRINTSTRING("\n stats_controller: RESET")PRINTNL() ENDPROC /// PURPOSE: Checks to see if the stats controller should be re-initialised PROC CHECK_CONTROLLER_RESET() IF eStage != SC_STAGE_INIT AND eInit != NOT_INITIALISED // Reset if we have changed game modes IF eInit = INITIALISED_IN_SP IF NETWORK_IS_GAME_IN_PROGRESS() eInit = NOT_INITIALISED ENDIF IF NOT HAVE_DEFAULT_PLAYER_STATS_BEEN_SET() eInit = NOT_INITIALISED ENDIF ELIF eInit = INITIALISED_IN_MP_FREEMODE #IF FEATURE_COPS_N_CROOKS OR eInit = INITIALISED_IN_MP_ARCADE_CNC #ENDIF IF NOT NETWORK_IS_GAME_IN_PROGRESS() OR NOT IS_PLAYER_ACTIVE_IN_MP_LAUNCH_SCRIPT(PLAYER_ID()) OR GET_CURRENT_GAMEMODE() != GAMEMODE_FM eInit = NOT_INITIALISED ENDIF ENDIF // Jump back to the initialisation stage if we have switched game modes IF eInit = NOT_INITIALISED eStage = SC_STAGE_RESET ENDIF ENDIF ENDPROC SCRIPT PRINTSTRING("\nStarting stats controller")PRINTNL() NETWORK_SET_SCRIPT_IS_SAFE_FOR_NETWORK_GAME() // This script needs to cleanup only when run the magdemo IF (HAS_FORCE_CLEANUP_OCCURRED(FORCE_CLEANUP_FLAG_MAGDEMO)) PRINTSTRING("...stats_controller.sc has been forced to cleanup (MAGDEMO)") PRINTNL() TERMINATE_THIS_THREAD() ENDIF #IF IS_DEBUG_BUILD START_WIDGET_GROUP("Stats Controller") ADD_WIDGET_INT_SLIDER("Cool down time", STAT_UPDATE_ALL_WHEELS_COOL_DOWN_TIME, 0, 10000, 100) ADD_WIDGET_INT_SLIDER("Air time", STAT_UPDATE_ALL_WHEELS_AIR_TIME, 0, 10000, 100) ADD_WIDGET_INT_SLIDER("Land time", STAT_UPDATE_ALL_WHEELS_LAND_TIME, 0, 10000, 1) INT iTempStat PLAYER_STATS_ENUM eTempStat REPEAT NUMBER_OF_PLAYER_STATS iTempStat eTempStat = INT_TO_ENUM(PLAYER_STATS_ENUM, iTempStat) g_iDebugPlayerStatOffset[iTempStat] = -1 IF eTempStat != PS_SPECIAL_ABILITY ADD_WIDGET_INT_SLIDER(GET_STRING_FROM_TEXT_FILE(GET_PLAYER_STAT_DISPLAY_NAME(eTempStat)), g_iDebugPlayerStatOffset[iTempStat], -1, 100, 1) ENDIF ENDREPEAT ADD_WIDGET_BOOL("Default stats set", g_savedGlobals.sPlayerData.sInfo.bDefaultStatsSet) ADD_WIDGET_BOOL("Undrive Player Car", bUndrivePlayerCar) ADD_WIDGET_BOOL("Kill Player Car", bKillPlayerCar) ADD_WIDGET_BOOL("Driving Stat +1", bBoostDrivingStat) ADD_WIDGET_BOOL("Driving Stat -1", bBashBoostDrivingStat) STOP_WIDGET_GROUP() #ENDIF WHILE (TRUE) CHECK_CONTROLLER_RESET() #IF IS_DEBUG_BUILD IF bBoostDrivingStat INCREMENT_PLAYER_PED_STAT(eCurrentStatPed, PS_DRIVING_ABILITY, 1) bBoostDrivingStat = FALSE ENDIF IF bBashBoostDrivingStat INCREMENT_PLAYER_PED_STAT(eCurrentStatPed, PS_DRIVING_ABILITY, -1) bBashBoostDrivingStat = FALSE ENDIF IF bKillPlayerCar IF NOT IS_PED_INJURED(PLAYER_PED_ID()) IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) SET_VEHICLE_ENGINE_HEALTH(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), 0) ENDIF ENDIF bKillPlayerCar = FALSE ENDIF IF bUndrivePlayerCar IF NOT IS_PED_INJURED(PLAYER_PED_ID()) IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) SET_VEHICLE_UNDRIVEABLE(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), TRUE) ENDIF ENDIF bUndrivePlayerCar = FALSE ENDIF #ENDIF SWITCH eStage CASE SC_STAGE_INIT DO_INITIALISE() BREAK CASE SC_STAGE_UPDATE DO_FEED_UPDATE_FOR_STAT() DO_CHECK_FOR_STAT_UPDATE() g_bDisableStatUpdatesThisFrame = FALSE // [AG] - vehicle repair needs to be removed // DO_VEHICLE_REPAIR_PROCESSING() BREAK CASE SC_STAGE_RESET DO_RESET() BREAK ENDSWITCH WAIT(0) ENDWHILE ENDSCRIPT