Files
gtav-src/script/dev_ng/singleplayer/include/private/stats_private.sch
T
2025-09-29 00:52:08 +02:00

894 lines
35 KiB
Scheme
Executable File

//////////////////////////////////////////////////////////////////////////////////////////
// //
// SCRIPT NAME : stats_private.sch //
// AUTHOR : Kenneth Ross //
// DESCRIPTION : Holds functionality to initialises the global stat data //
// for each player character, display the stats on screen, //
// and set up debug widgets. //
// //
//////////////////////////////////////////////////////////////////////////////////////////
USING "rage_builtins.sch"
USING "globals.sch"
USING "player_ped_public.sch"
USING "stats_public.sch"
USING "commands_stats.sch"
USING "range_public.sch"
USING "pilotschool_public.sch"
/// PURPOSE: Stat order for display list
FUNC PLAYER_STATS_ENUM GET_PLAYER_STAT_FOR_DISPLAY_SLOT(INT iSlot)
SWITCH iSlot
CASE 0 RETURN PS_SPECIAL_ABILITY BREAK
CASE 1 RETURN PS_STAMINA BREAK
CASE 2 RETURN PS_SHOOTING_ABILITY BREAK
CASE 3 RETURN PS_STRENGTH BREAK
CASE 4 RETURN PS_STEALTH_ABILITY BREAK
CASE 5 RETURN PS_FLYING_ABILITY BREAK
CASE 6 RETURN PS_DRIVING_ABILITY BREAK
CASE 7 RETURN PS_LUNG_CAPACITY BREAK
ENDSWITCH
RETURN PS_SPECIAL_ABILITY
ENDFUNC
FUNC INT GET_STAT_UPDATES_FROM_SCRIPT(enumCharacterList ePed, PLAYER_STATS_ENUM ePlayerStat #IF USE_TU_CHANGES , INT iSlot = -1 #ENDIF )
SWITCH ePed
CASE CHAR_MICHAEL
CASE CHAR_FRANKLIN
CASE CHAR_TREVOR
SWITCH ePlayerStat
CASE PS_STAMINA
CASE PS_LUNG_CAPACITY
CASE PS_STRENGTH
CASE PS_DRIVING_ABILITY
CASE PS_FLYING_ABILITY
CASE PS_SHOOTING_ABILITY
CASE PS_STEALTH_ABILITY
RETURN g_savedGlobals.sPlayerData.sInfo.iPlayerStatScript[ePlayerStat][ePed]
BREAK
ENDSWITCH
BREAK
CASE CHAR_MULTIPLAYER
SWITCH ePlayerStat
CASE PS_STAMINA RETURN GET_MP_INT_CHARACTER_STAT(MP_STAT_SCRIPT_INCREASE_STAM #IF USE_TU_CHANGES , iSlot #ENDIF ) BREAK
CASE PS_LUNG_CAPACITY RETURN GET_MP_INT_CHARACTER_STAT(MP_STAT_SCRIPT_INCREASE_LUNG #IF USE_TU_CHANGES , iSlot #ENDIF ) BREAK
CASE PS_STRENGTH RETURN GET_MP_INT_CHARACTER_STAT(MP_STAT_SCRIPT_INCREASE_STRN #IF USE_TU_CHANGES , iSlot #ENDIF ) BREAK
CASE PS_DRIVING_ABILITY RETURN GET_MP_INT_CHARACTER_STAT(MP_STAT_SCRIPT_INCREASE_DRIV #IF USE_TU_CHANGES , iSlot #ENDIF ) BREAK
CASE PS_FLYING_ABILITY RETURN GET_MP_INT_CHARACTER_STAT(MP_STAT_SCRIPT_INCREASE_FLY #IF USE_TU_CHANGES , iSlot #ENDIF ) BREAK
CASE PS_SHOOTING_ABILITY RETURN GET_MP_INT_CHARACTER_STAT(MP_STAT_SCRIPT_INCREASE_SHO #IF USE_TU_CHANGES , iSlot #ENDIF ) BREAK
CASE PS_STEALTH_ABILITY RETURN GET_MP_INT_CHARACTER_STAT(MP_STAT_SCRIPT_INCREASE_STL #IF USE_TU_CHANGES , iSlot #ENDIF ) BREAK
ENDSWITCH
BREAK
ENDSWITCH
RETURN 0
ENDFUNC
#IF FEATURE_FREEMODE_ARCADE
FUNC INT GET_FM_ARCADE_PLAYER_STAT_VALUE(PLAYER_STATS_ENUM ePlayerStat)
SWITCH GET_ARCADE_MODE()
#IF FEATURE_COPS_N_CROOKS
CASE ARC_COPS_CROOKS
SWITCH ePlayerStat
CASE PS_SPECIAL_ABILITY RETURN 0 BREAK
CASE PS_STAMINA RETURN 0 BREAK
CASE PS_STRENGTH RETURN 0 BREAK
CASE PS_LUNG_CAPACITY RETURN 0 BREAK
CASE PS_DRIVING_ABILITY RETURN 0 BREAK
CASE PS_FLYING_ABILITY RETURN 0 BREAK
CASE PS_SHOOTING_ABILITY RETURN 0 BREAK
CASE PS_STEALTH_ABILITY RETURN 0 BREAK
ENDSWITCH
BREAK
#ENDIF
#IF FEATURE_ENDLESS_WINTER
CASE ARC_ENDLESS_WINTER
SWITCH ePlayerStat
CASE PS_SPECIAL_ABILITY RETURN 0 BREAK
CASE PS_STAMINA RETURN 0 BREAK
CASE PS_STRENGTH RETURN 0 BREAK
CASE PS_LUNG_CAPACITY RETURN 0 BREAK
CASE PS_DRIVING_ABILITY RETURN 0 BREAK
CASE PS_FLYING_ABILITY RETURN 0 BREAK
CASE PS_SHOOTING_ABILITY RETURN 0 BREAK
CASE PS_STEALTH_ABILITY RETURN 0 BREAK
ENDSWITCH
BREAK
#ENDIF
DEFAULT
SCRIPT_ASSERT("GET_FM_ARCADE_PLAYER_STAT_VALUE - Unknown arcade mode!")
BREAK
ENDSWITCH
RETURN 0
ENDFUNC
#ENDIF
/// PURPOSE: What the player stat starts at when we start a new game
FUNC INT GET_INITIAL_STAT_VALUE(enumCharacterList ePed, PLAYER_STATS_ENUM ePlayerStat #IF USE_TU_CHANGES , INT iSlot = -1 #ENDIF )
// Max out stats in debug mode...
#IF IS_DEBUG_BUILD
IF NOT NETWORK_IS_GAME_IN_PROGRESS()
IF (NOT g_savedGlobals.sFlow.isGameflowActive AND NOT IS_REPEAT_PLAY_ACTIVE())
AND NOT g_bMagDemoActive
RETURN 100
ENDIF
ENDIF
#ENDIF
//B* 2201835: Fake 100% stats in Director Mode
IF NOT NETWORK_IS_GAME_IN_PROGRESS()
IF IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_DIRECTOR)
RETURN 100
ENDIF
ENDIF
//Default to 0 for arcade mode so we can set to mode balanced values
#IF FEATURE_FREEMODE_ARCADE
IF ePed = CHAR_MULTIPLAYER
AND IS_FREEMODE_ARCADE()
RETURN GET_FM_ARCADE_PLAYER_STAT_VALUE(ePlayerStat)
ENDIF
#ENDIF
SWITCH ePed
CASE CHAR_MICHAEL
SWITCH ePlayerStat
CASE PS_SPECIAL_ABILITY RETURN 0 BREAK
CASE PS_STAMINA RETURN 47 BREAK
CASE PS_LUNG_CAPACITY RETURN 22 BREAK
CASE PS_STRENGTH RETURN 21 BREAK
CASE PS_DRIVING_ABILITY RETURN 54 BREAK
CASE PS_FLYING_ABILITY RETURN 31 BREAK
CASE PS_SHOOTING_ABILITY RETURN 79 BREAK
CASE PS_STEALTH_ABILITY RETURN 81 BREAK
ENDSWITCH
BREAK
CASE CHAR_FRANKLIN
SWITCH ePlayerStat
CASE PS_SPECIAL_ABILITY RETURN 0 BREAK
CASE PS_STAMINA RETURN 51 BREAK
CASE PS_LUNG_CAPACITY RETURN 46 BREAK
CASE PS_STRENGTH RETURN 49 BREAK
CASE PS_DRIVING_ABILITY RETURN 71 BREAK
CASE PS_FLYING_ABILITY RETURN 19 BREAK
CASE PS_SHOOTING_ABILITY RETURN 24 BREAK
CASE PS_STEALTH_ABILITY RETURN 21 BREAK
ENDSWITCH
BREAK
CASE CHAR_TREVOR
SWITCH ePlayerStat
CASE PS_SPECIAL_ABILITY RETURN 0 BREAK
CASE PS_STAMINA RETURN 23 BREAK
CASE PS_LUNG_CAPACITY RETURN 28 BREAK
CASE PS_STRENGTH RETURN 79 BREAK
CASE PS_DRIVING_ABILITY RETURN 31 BREAK
CASE PS_FLYING_ABILITY RETURN 82 BREAK
CASE PS_SHOOTING_ABILITY RETURN 69 BREAK
CASE PS_STEALTH_ABILITY RETURN 49 BREAK
ENDSWITCH
BREAK
CASE CHAR_MULTIPLAYER
SWITCH ePlayerStat
CASE PS_STAMINA RETURN GET_MP_INT_CHARACTER_STAT(MP_STAT_CHAR_CREATOR_STAMINA #IF USE_TU_CHANGES , iSlot #ENDIF ) BREAK
CASE PS_LUNG_CAPACITY RETURN GET_MP_INT_CHARACTER_STAT(MP_STAT_CHAR_CREATOR_LUNG #IF USE_TU_CHANGES , iSlot #ENDIF ) BREAK
CASE PS_STRENGTH RETURN GET_MP_INT_CHARACTER_STAT(MP_STAT_CHAR_CREATOR_STRENGTH #IF USE_TU_CHANGES , iSlot #ENDIF ) BREAK
CASE PS_DRIVING_ABILITY RETURN GET_MP_INT_CHARACTER_STAT(MP_STAT_CHAR_CREATOR_BIKE #IF USE_TU_CHANGES , iSlot #ENDIF ) BREAK
CASE PS_FLYING_ABILITY RETURN GET_MP_INT_CHARACTER_STAT(MP_STAT_CHAR_CREATOR_FLYING #IF USE_TU_CHANGES , iSlot #ENDIF ) BREAK
CASE PS_SHOOTING_ABILITY RETURN GET_MP_INT_CHARACTER_STAT(MP_STAT_CHAR_CREATOR_SHOOTING #IF USE_TU_CHANGES , iSlot #ENDIF ) BREAK
CASE PS_STEALTH_ABILITY RETURN GET_MP_INT_CHARACTER_STAT(MP_STAT_CHAR_CREATOR_STEALTH #IF USE_TU_CHANGES , iSlot #ENDIF ) BREAK
ENDSWITCH
BREAK
ENDSWITCH
RETURN 0
ENDFUNC
/// PURPOSE: How much the player stat has to increase for it to be displayed on the feed
FUNC INT GET_FEED_UPDATE_FREQ(enumCharacterList ePed, PLAYER_STATS_ENUM ePlayerStat)
SWITCH ePed
CASE CHAR_MICHAEL
SWITCH ePlayerStat
CASE PS_SPECIAL_ABILITY RETURN 20 BREAK
CASE PS_STAMINA RETURN 20 BREAK
CASE PS_LUNG_CAPACITY RETURN 20 BREAK
CASE PS_STRENGTH RETURN 20 BREAK
CASE PS_DRIVING_ABILITY RETURN 20 BREAK
CASE PS_FLYING_ABILITY RETURN 20 BREAK
CASE PS_SHOOTING_ABILITY RETURN 20 BREAK
CASE PS_STEALTH_ABILITY RETURN 20 BREAK
ENDSWITCH
BREAK
CASE CHAR_FRANKLIN
SWITCH ePlayerStat
CASE PS_SPECIAL_ABILITY RETURN 20 BREAK
CASE PS_STAMINA RETURN 20 BREAK
CASE PS_LUNG_CAPACITY RETURN 20 BREAK
CASE PS_STRENGTH RETURN 20 BREAK
CASE PS_DRIVING_ABILITY RETURN 20 BREAK
CASE PS_FLYING_ABILITY RETURN 20 BREAK
CASE PS_SHOOTING_ABILITY RETURN 20 BREAK
CASE PS_STEALTH_ABILITY RETURN 20 BREAK
ENDSWITCH
BREAK
CASE CHAR_TREVOR
SWITCH ePlayerStat
CASE PS_SPECIAL_ABILITY RETURN 20 BREAK
CASE PS_STAMINA RETURN 20 BREAK
CASE PS_LUNG_CAPACITY RETURN 20 BREAK
CASE PS_STRENGTH RETURN 20 BREAK
CASE PS_DRIVING_ABILITY RETURN 20 BREAK
CASE PS_FLYING_ABILITY RETURN 20 BREAK
CASE PS_SHOOTING_ABILITY RETURN 20 BREAK
CASE PS_STEALTH_ABILITY RETURN 20 BREAK
ENDSWITCH
BREAK
CASE CHAR_MULTIPLAYER
SWITCH ePlayerStat
CASE PS_SPECIAL_ABILITY RETURN 20 BREAK
CASE PS_STAMINA RETURN 20 BREAK
CASE PS_LUNG_CAPACITY RETURN 20 BREAK
CASE PS_STRENGTH RETURN 20 BREAK
CASE PS_DRIVING_ABILITY RETURN 20 BREAK
CASE PS_FLYING_ABILITY RETURN 20 BREAK
CASE PS_SHOOTING_ABILITY RETURN 20 BREAK
CASE PS_STEALTH_ABILITY RETURN 20 BREAK
ENDSWITCH
BREAK
ENDSWITCH
RETURN 1
ENDFUNC
FUNC BOOL IS_GOON_ELIGABLE_FOR_STAT_BOOST()
//PRINTLN("IS_GOON_ELIGABLE_FOR_STAT_BOOST FALSE = bG_SetIncreasedStats = ", bG_SetIncreasedStats)
IF NOT GB_IS_LOCAL_PLAYER_MEMBER_OF_A_GANG()
//PRINTLN("IS_GOON_ELIGABLE_FOR_STAT_BOOST FALSE = GB_IS_LOCAL_PLAYER_MEMBER_OF_A_GANG FALSE ")
RETURN FALSE
ENDIF
IF GB_IS_LOCAL_PLAYER_BOSS_OF_A_GANG()
//PRINTLN("IS_GOON_ELIGABLE_FOR_STAT_BOOST TRUE = GB_IS_LOCAL_PLAYER_BOSS_OF_A_GANG TRUE ")
RETURN FALSE
ENDIF
RETURN bG_SetIncreasedStats
ENDFUNC
FUNC FLOAT APPLY_GANG_BOSS_STAT_INCREASE_FOR_GOONS( FLOAT &fFinalStatValue)
//PRINTLN("APPLY_GANG_BOSS_STAT_INCREASE_FOR_GOONS Passed in value fFinalStatValue = ", fFinalStatValue)
IF IS_GOON_ELIGABLE_FOR_STAT_BOOST()
//PRINTLN("CALCULATE_PLAYER_STAT_VALUE IS_GOON_ELIGABLE_FOR_STAT_BOOST = TRUE: APPLY GOON BOSS BOOST")
IF GET_RANK_OF_YOUR_GANG_BOSS() < g_sMPTunables.igb_boss_stat_boost_max_rank
IF fFinalStatValue + (GET_RANK_OF_YOUR_GANG_BOSS()*g_sMPTunables.fgb_boss_stat_boost_percentage) <=g_sMPTunables.iGB_boss_boost_max_final_stat
fFinalStatValue += (GET_RANK_OF_YOUR_GANG_BOSS()*g_sMPTunables.fgb_boss_stat_boost_percentage)
//PRINTLN("APPLY_GANG_BOSS_STAT_INCREASE_FOR_GOONS fFinalStatValue = ", fFinalStatValue)
ENDIF
ENDIF
RETURN fFinalStatValue
ELSE
//PRINTLN("CALCULATE_PLAYER_STAT_VALUE IS_GOON_ELIGABLE_FOR_STAT_BOOST = FALSE: DO NOT APPLY GOON BOSS BOOST. DO NOTHING")
//PRINTLN("APPLY_GANG_BOSS_STAT_INCREASE_FOR_GOONS fFinalStatValue = ", fFinalStatValue)
RETURN fFinalStatValue
ENDIF
ENDFUNC
/// PURPOSE: Works out the players stat based on current progression.
/// NOTE: Set bApplyFeedUpdateFreqCap to true if you want to round down the value to the nearest GET_FEED_UPDATE_FREQ()
FUNC INT CALCULATE_PLAYER_STAT_VALUE(enumCharacterList ePed, PLAYER_STATS_ENUM ePlayerStat, BOOL bApplyFeedUpdateFreqCap #IF USE_TU_CHANGES , INT iSlot = -1 #ENDIF )
FLOAT fFinalStatValue, fTempStatValue
INT iFinalStatValue = 0
INT iTempStatValue
#IF FEATURE_FREEMODE_ARCADE
IF ePed = CHAR_MULTIPLAYER
AND IS_FREEMODE_ARCADE()
RETURN GET_FM_ARCADE_PLAYER_STAT_VALUE(ePlayerStat)
ENDIF
#ENDIF
SWITCH ePlayerStat
CASE PS_SPECIAL_ABILITY
// Not updated by script so return stat value
IF ePed = CHAR_MICHAEL
STAT_GET_INT(SP0_SPECIAL_ABILITY_UNLOCKED, iTempStatValue)
fFinalStatValue = TO_FLOAT(iTempStatValue)
ELIF ePed = CHAR_FRANKLIN
STAT_GET_INT(SP1_SPECIAL_ABILITY_UNLOCKED, iTempStatValue)
fFinalStatValue = TO_FLOAT(iTempStatValue)
ELIF ePed = CHAR_TREVOR
STAT_GET_INT(SP2_SPECIAL_ABILITY_UNLOCKED, iTempStatValue)
fFinalStatValue = TO_FLOAT(iTempStatValue)
ELIF ePed = CHAR_MULTIPLAYER
fFinalStatValue = TO_FLOAT(GET_MP_INT_CHARACTER_STAT(MP_STAT_SPECIAL_ABILITY #IF USE_TU_CHANGES , iSlot #ENDIF ))
ENDIF
BREAK
CASE PS_STAMINA
// 1% for every 175m ran
IF ePed = CHAR_MICHAEL
STAT_GET_FLOAT(SP0_DIST_RUNNING, fTempStatValue)
fFinalStatValue = ((fTempStatValue-g_savedGlobals.sPlayerData.sInfo.fStatOffset_DistRunning[ePed]) / 175)
ELIF ePed = CHAR_FRANKLIN
STAT_GET_FLOAT(SP1_DIST_RUNNING, fTempStatValue)
fFinalStatValue = ((fTempStatValue-g_savedGlobals.sPlayerData.sInfo.fStatOffset_DistRunning[ePed]) / 175)
ELIF ePed = CHAR_TREVOR
STAT_GET_FLOAT(SP2_DIST_RUNNING, fTempStatValue)
fFinalStatValue = ((fTempStatValue-g_savedGlobals.sPlayerData.sInfo.fStatOffset_DistRunning[ePed]) / 175)
ELIF ePed = CHAR_MULTIPLAYER
fFinalStatValue = (GET_MP_FLOAT_CHARACTER_STAT(MP_STAT_DIST_RUNNING #IF USE_TU_CHANGES , iSlot #ENDIF ) / 175)
#IF IS_DEBUG_BUILD
IF GET_COMMANDLINE_PARAM_EXISTS("sc_PrintCharSelectStats")
PRINTLN("CALCULATE_PLAYER_STAT_VALUE: DIST_RUNNING fFinalStatValue = ", fFinalStatValue, " iSlot = ", iSlot, " " )
ENDIF
#ENDIF
APPLY_GANG_BOSS_STAT_INCREASE_FOR_GOONS(fFinalStatValue)
ENDIF
// 1% for every 1 minute swimming
IF ePed = CHAR_MICHAEL
fFinalStatValue += (TO_FLOAT(GET_TOTAL_NUMBER_OF_MINUTES_FOR_UNSIGNED_INT_STAT(SP0_TIME_SWIMMING)))
ELIF ePed = CHAR_FRANKLIN
fFinalStatValue += (TO_FLOAT(GET_TOTAL_NUMBER_OF_MINUTES_FOR_UNSIGNED_INT_STAT(SP1_TIME_SWIMMING)))
ELIF ePed = CHAR_TREVOR
fFinalStatValue += (TO_FLOAT(GET_TOTAL_NUMBER_OF_MINUTES_FOR_UNSIGNED_INT_STAT(SP2_TIME_SWIMMING)))
ELIF ePed = CHAR_MULTIPLAYER
fFinalStatValue += (TO_FLOAT(GET_TOTAL_NUMBER_OF_MINUTES_FOR_UNSIGNED_INT_STAT(GET_STAT_FROM_MP_INT_CHARACTER_STAT(MP_STAT_TIME_SWIMMING #IF USE_TU_CHANGES , iSlot #ENDIF ))))
#IF IS_DEBUG_BUILD
IF GET_COMMANDLINE_PARAM_EXISTS("sc_PrintCharSelectStats")
PRINTLN("CALCULATE_PLAYER_STAT_VALUE: TIME_SWIMMING fFinalStatValue = ", fFinalStatValue, " iSlot = ", iSlot, " " )
ENDIF
#ENDIF
APPLY_GANG_BOSS_STAT_INCREASE_FOR_GOONS(fFinalStatValue)
ENDIF
// 1% for every 1 minute cycling
IF ePed = CHAR_MICHAEL
fFinalStatValue += (TO_FLOAT(GET_TOTAL_NUMBER_OF_MINUTES_FOR_UNSIGNED_INT_STAT(SP0_TIME_DRIVING_BICYCLE)))
ELIF ePed = CHAR_FRANKLIN
fFinalStatValue += (TO_FLOAT(GET_TOTAL_NUMBER_OF_MINUTES_FOR_UNSIGNED_INT_STAT(SP1_TIME_DRIVING_BICYCLE)))
ELIF ePed = CHAR_TREVOR
fFinalStatValue += (TO_FLOAT(GET_TOTAL_NUMBER_OF_MINUTES_FOR_UNSIGNED_INT_STAT(SP2_TIME_DRIVING_BICYCLE)))
ELIF ePed = CHAR_MULTIPLAYER
fFinalStatValue += (TO_FLOAT(GET_TOTAL_NUMBER_OF_MINUTES_FOR_UNSIGNED_INT_STAT(GET_STAT_FROM_MP_INT_CHARACTER_STAT(MP_STAT_TIME_DRIVING_BICYCLE #IF USE_TU_CHANGES , iSlot #ENDIF ))))
#IF IS_DEBUG_BUILD
IF GET_COMMANDLINE_PARAM_EXISTS("sc_PrintCharSelectStats")
PRINTLN("CALCULATE_PLAYER_STAT_VALUE: TIME_DRIVING_BICYCLE fFinalStatValue = ", fFinalStatValue, " iSlot = ", iSlot, " " )
ENDIF
#ENDIF
APPLY_GANG_BOSS_STAT_INCREASE_FOR_GOONS(fFinalStatValue)
ENDIF
// Nightclub dance beat matching increases stam for every full min
IF ePed = CHAR_MULTIPLAYER
// Mul 4 because fFinalStatValue/=4 for multipler
fFinalStatValue += (4 * g_sMPTunables.fBB_NIGHTCLUB_BEAT_MATCHING_STAMINA_INCREASE_PER_MINUTE) * GET_MP_INT_CHARACTER_STAT(MP_STAT_DANCE_COMBO_DURATION_MINS)
ENDIF
// 4x slower in MP
IF ePed = CHAR_MULTIPLAYER
fFinalStatValue *= 0.25
#IF IS_DEBUG_BUILD
IF GET_COMMANDLINE_PARAM_EXISTS("sc_PrintCharSelectStats")
PRINTLN("CALCULATE_PLAYER_STAT_VALUE: MULTIPLYER fFinalStatValue = ", fFinalStatValue, " iSlot = ", iSlot, " " )
ENDIF
#ENDIF
ENDIF
BREAK
CASE PS_LUNG_CAPACITY
// 1% for every 30 seconds underwater
IF ePed = CHAR_MICHAEL
fFinalStatValue = (TO_FLOAT(GET_TOTAL_NUMBER_OF_SECONDS_FOR_UNSIGNED_INT_STAT(SP0_TIME_UNDERWATER)) / 30)
ELIF ePed = CHAR_FRANKLIN
fFinalStatValue = (TO_FLOAT(GET_TOTAL_NUMBER_OF_SECONDS_FOR_UNSIGNED_INT_STAT(SP1_TIME_UNDERWATER)) / 30)
ELIF ePed = CHAR_TREVOR
fFinalStatValue = (TO_FLOAT(GET_TOTAL_NUMBER_OF_SECONDS_FOR_UNSIGNED_INT_STAT(SP2_TIME_UNDERWATER)) / 30)
ELIF ePed = CHAR_MULTIPLAYER
fFinalStatValue = (TO_FLOAT(GET_TOTAL_NUMBER_OF_SECONDS_FOR_UNSIGNED_INT_STAT(GET_STAT_FROM_MP_INT_CHARACTER_STAT(MP_STAT_TIME_UNDERWATER #IF USE_TU_CHANGES , iSlot #ENDIF ))) / 30)
APPLY_GANG_BOSS_STAT_INCREASE_FOR_GOONS(fFinalStatValue)
ENDIF
BREAK
CASE PS_STRENGTH
// 1% for every 20 punches
IF ePed = CHAR_MICHAEL
STAT_GET_INT(SP0_UNARMED_HITS, iTempStatValue)
fFinalStatValue = (TO_FLOAT(iTempStatValue-g_savedGlobals.sPlayerData.sInfo.iStatOffset_HitsUnarmed[ePed]) / 20)
ELIF ePed = CHAR_FRANKLIN
STAT_GET_INT(SP1_UNARMED_HITS, iTempStatValue)
fFinalStatValue = (TO_FLOAT(iTempStatValue-g_savedGlobals.sPlayerData.sInfo.iStatOffset_HitsUnarmed[ePed]) / 20)
ELIF ePed = CHAR_TREVOR
STAT_GET_INT(SP2_UNARMED_HITS, iTempStatValue)
fFinalStatValue = (TO_FLOAT(iTempStatValue-g_savedGlobals.sPlayerData.sInfo.iStatOffset_HitsUnarmed[ePed]) / 20)
ELIF ePed = CHAR_MULTIPLAYER
#IF USE_TU_CHANGES
fFinalStatValue = (TO_FLOAT(GET_MP_INT_CHARACTER_STAT(MP_STAT_UNARMED_PED_HITS, iSlot)) / 20)
#ENDIF
#IF NOT USE_TU_CHANGES
fFinalStatValue = (TO_FLOAT(GET_MP_INT_CHARACTER_STAT(MP_STAT_UNARMED_HITS)) / 20)
#ENDIF
APPLY_GANG_BOSS_STAT_INCREASE_FOR_GOONS(fFinalStatValue)
ENDIF
BREAK
CASE PS_DRIVING_ABILITY
// 1% for every 10 seconds of wheelie action
/*IF ePed = CHAR_MICHAEL
fFinalStatValue = (TO_FLOAT(GET_TOTAL_NUMBER_OF_SECONDS_FOR_UNSIGNED_INT_STAT(SP0_TOTAL_WHEELIE_TIME)) / 10)
ELIF ePed = CHAR_FRANKLIN
fFinalStatValue = (TO_FLOAT(GET_TOTAL_NUMBER_OF_SECONDS_FOR_UNSIGNED_INT_STAT(SP1_TOTAL_WHEELIE_TIME)) / 10)
ELIF ePed = CHAR_TREVOR
fFinalStatValue = (TO_FLOAT(GET_TOTAL_NUMBER_OF_SECONDS_FOR_UNSIGNED_INT_STAT(SP2_TOTAL_WHEELIE_TIME)) / 10)
ELIF ePed = CHAR_MULTIPLAYER
fFinalStatValue = (TO_FLOAT(GET_TOTAL_NUMBER_OF_SECONDS_FOR_UNSIGNED_INT_STAT(GET_STAT_FROM_MP_INT_CHARACTER_STAT(MP_STAT_TOTAL_WHEELIE_TIME))) / 10)
ENDIF*/
// 1% for every 50 near misses
IF ePed = CHAR_MICHAEL
STAT_GET_INT(SP0_NUMBER_NEAR_MISS, iTempStatValue)
fFinalStatValue += ((TO_FLOAT(iTempStatValue-g_savedGlobals.sPlayerData.sInfo.iStatOffset_NumberNearMisses[ePed]) / 50))
ELIF ePed = CHAR_FRANKLIN
STAT_GET_INT(SP1_NUMBER_NEAR_MISS, iTempStatValue)
fFinalStatValue += ((TO_FLOAT(iTempStatValue-g_savedGlobals.sPlayerData.sInfo.iStatOffset_NumberNearMisses[ePed]) / 50))
ELIF ePed = CHAR_TREVOR
STAT_GET_INT(SP2_NUMBER_NEAR_MISS, iTempStatValue)
fFinalStatValue += ((TO_FLOAT(iTempStatValue-g_savedGlobals.sPlayerData.sInfo.iStatOffset_NumberNearMisses[ePed]) / 50))
ELIF ePed = CHAR_MULTIPLAYER
fFinalStatValue += (GET_MP_INT_CHARACTER_STAT(MP_STAT_NUMBER_NEAR_MISS #IF USE_TU_CHANGES , iSlot #ENDIF ) / 50)
APPLY_GANG_BOSS_STAT_INCREASE_FOR_GOONS(fFinalStatValue)
ENDIF
BREAK
CASE PS_FLYING_ABILITY
// 1% for every 10 minute flying
IF ePed = CHAR_MICHAEL
fFinalStatValue = (TO_FLOAT(GET_TOTAL_NUMBER_OF_MINUTES_FOR_UNSIGNED_INT_STAT(SP0_TIME_DRIVING_PLANE)) / 10)
ELIF ePed = CHAR_FRANKLIN
fFinalStatValue = (TO_FLOAT(GET_TOTAL_NUMBER_OF_MINUTES_FOR_UNSIGNED_INT_STAT(SP1_TIME_DRIVING_PLANE)) / 10)
ELIF ePed = CHAR_TREVOR
fFinalStatValue = (TO_FLOAT(GET_TOTAL_NUMBER_OF_MINUTES_FOR_UNSIGNED_INT_STAT(SP2_TIME_DRIVING_PLANE)) / 10)
ELIF ePed = CHAR_MULTIPLAYER
fFinalStatValue = (TO_FLOAT(GET_TOTAL_NUMBER_OF_MINUTES_FOR_UNSIGNED_INT_STAT(GET_STAT_FROM_MP_INT_CHARACTER_STAT(MP_STAT_TIME_DRIVING_PLANE #IF USE_TU_CHANGES , iSlot #ENDIF ))) / 10)
ENDIF
IF ePed = CHAR_MICHAEL
fFinalStatValue += (TO_FLOAT(GET_TOTAL_NUMBER_OF_MINUTES_FOR_UNSIGNED_INT_STAT(SP0_TIME_DRIVING_HELI)) / 10)
ELIF ePed = CHAR_FRANKLIN
fFinalStatValue += (TO_FLOAT(GET_TOTAL_NUMBER_OF_MINUTES_FOR_UNSIGNED_INT_STAT(SP1_TIME_DRIVING_HELI)) / 10)
ELIF ePed = CHAR_TREVOR
fFinalStatValue += (TO_FLOAT(GET_TOTAL_NUMBER_OF_MINUTES_FOR_UNSIGNED_INT_STAT(SP2_TIME_DRIVING_HELI)) / 10)
ELIF ePed = CHAR_MULTIPLAYER
fFinalStatValue += (TO_FLOAT(GET_TOTAL_NUMBER_OF_MINUTES_FOR_UNSIGNED_INT_STAT(GET_STAT_FROM_MP_INT_CHARACTER_STAT(MP_STAT_TIME_DRIVING_HELI #IF USE_TU_CHANGES , iSlot #ENDIF ))) / 10)
ENDIF
// 1% for every plane landing
IF ePed = CHAR_MICHAEL
STAT_GET_INT(SP0_PLANE_LANDINGS, iTempStatValue)
fFinalStatValue += (TO_FLOAT(iTempStatValue))
ELIF ePed = CHAR_FRANKLIN
STAT_GET_INT(SP1_PLANE_LANDINGS, iTempStatValue)
fFinalStatValue += (TO_FLOAT(iTempStatValue))
ELIF ePed = CHAR_TREVOR
STAT_GET_INT(SP2_PLANE_LANDINGS, iTempStatValue)
fFinalStatValue += (TO_FLOAT(iTempStatValue))
ELIF ePed = CHAR_MULTIPLAYER
fFinalStatValue += (GET_MP_INT_CHARACTER_STAT(MP_STAT_PLANE_LANDINGS #IF USE_TU_CHANGES , iSlot #ENDIF ))
APPLY_GANG_BOSS_STAT_INCREASE_FOR_GOONS(fFinalStatValue)
ENDIF
IF ePed = CHAR_MICHAEL
OR ePed = CHAR_FRANKLIN
OR ePed = CHAR_TREVOR
PILOT_SCHOOL_MEDAL eMedal
//Takeoff M+F: Gold 7%, silver 5% bronze 3%
//Takeoff T: Gold 3%, silver 2% bronze 1%
eMedal = GET_MEDAL_FOR_PILOT_SCHOOL_LESSON(ePed, PSC_Takeoff)
IF ePed = CHAR_TREVOR
IF eMedal = PS_GOLD
fFinalStatValue += 10
ELIF eMedal = PS_SILVER
fFinalStatValue += 7
ELIF eMedal = PS_BRONZE
fFinalStatValue += 5
ENDIF
ELSE
IF eMedal = PS_GOLD
fFinalStatValue += 12
ELIF eMedal = PS_SILVER
fFinalStatValue += 9
ELIF eMedal = PS_BRONZE
fFinalStatValue += 7
ENDIF
ENDIF
//Landing M+F: Gold 7%, silver 5% bronze 3%
//Landing T: Gold 3%, silver 2% bronze 1%
eMedal = GET_MEDAL_FOR_PILOT_SCHOOL_LESSON(ePed, PSC_Landing)
IF ePed = CHAR_TREVOR
IF eMedal = PS_GOLD
fFinalStatValue += 10
ELIF eMedal = PS_SILVER
fFinalStatValue += 7
ELIF eMedal = PS_BRONZE
fFinalStatValue += 5
ENDIF
ELSE
IF eMedal = PS_GOLD
fFinalStatValue += 12
ELIF eMedal = PS_SILVER
fFinalStatValue += 9
ELIF eMedal = PS_BRONZE
fFinalStatValue += 7
ENDIF
ENDIF
//Upside down flight: Gold 3%, silver 2% bronze 1%
eMedal = GET_MEDAL_FOR_PILOT_SCHOOL_LESSON(ePed, PSC_Inverted)
IF eMedal = PS_GOLD
fFinalStatValue += 12
ELIF eMedal = PS_SILVER
fFinalStatValue += 9
ELIF eMedal = PS_BRONZE
fFinalStatValue += 7
ENDIF
//Knife flight: Gold 3%, silver 2% bronze 1%
eMedal = GET_MEDAL_FOR_PILOT_SCHOOL_LESSON(ePed, PSC_Knifing)
IF eMedal = PS_GOLD
fFinalStatValue += 12
ELIF eMedal = PS_SILVER
fFinalStatValue += 9
ELIF eMedal = PS_BRONZE
fFinalStatValue += 7
ENDIF
//Loop the loop: Gold 3%, silver 2% bronze 1%
eMedal = GET_MEDAL_FOR_PILOT_SCHOOL_LESSON(ePed, PSC_loopTheLoop)
IF eMedal = PS_GOLD
fFinalStatValue += 12
ELIF eMedal = PS_SILVER
fFinalStatValue += 9
ELIF eMedal = PS_BRONZE
fFinalStatValue += 7
ENDIF
//Fly low: Gold 5%, silver 3% bronze 2%
eMedal = GET_MEDAL_FOR_PILOT_SCHOOL_LESSON(ePed, PSC_FlyLow)
IF eMedal = PS_GOLD
fFinalStatValue += 5
ELIF eMedal = PS_SILVER
fFinalStatValue += 3
ELIF eMedal = PS_BRONZE
fFinalStatValue += 2
ENDIF
//Daring Landing: Gold 5%, silver 3% bronze 2%
eMedal = GET_MEDAL_FOR_PILOT_SCHOOL_LESSON(ePed, PSC_DaringLanding)
IF eMedal = PS_GOLD
fFinalStatValue += 12
ELIF eMedal = PS_SILVER
fFinalStatValue += 9
ELIF eMedal = PS_BRONZE
fFinalStatValue += 7
ENDIF
//Heli Obstacle Course: Gold 5%, silver 3% bronze 2%
eMedal = GET_MEDAL_FOR_PILOT_SCHOOL_LESSON(ePed, PSC_heliCourse)
IF eMedal = PS_GOLD
fFinalStatValue += 12
ELIF eMedal = PS_SILVER
fFinalStatValue += 9
ELIF eMedal = PS_BRONZE
fFinalStatValue += 7
ENDIF
//Heli Speed Run: Gold 6%, silver 4% bronze 3%
eMedal = GET_MEDAL_FOR_PILOT_SCHOOL_LESSON(ePed, PSC_heliSpeedRun)
IF eMedal = PS_GOLD
fFinalStatValue += 12
ELIF eMedal = PS_SILVER
fFinalStatValue += 9
ELIF eMedal = PS_BRONZE
fFinalStatValue += 7
ENDIF
//Plane Obstacle Course: Gold 8%, silver 5% Bronze 4%
eMedal = GET_MEDAL_FOR_PILOT_SCHOOL_LESSON(ePed, PSC_planeCourse)
IF eMedal = PS_GOLD
fFinalStatValue += 12
ELIF eMedal = PS_SILVER
fFinalStatValue += 9
ELIF eMedal = PS_BRONZE
fFinalStatValue += 7
ENDIF
ENDIF
BREAK
CASE PS_STEALTH_ABILITY
// 1% for every 50m walking in stealth
IF ePed = CHAR_MICHAEL
STAT_GET_FLOAT(SP0_DIST_WALK_ST, fTempStatValue)
fFinalStatValue = ((fTempStatValue-g_savedGlobals.sPlayerData.sInfo.fStatOffset_DistStealth[ePed]) / 45)
ELIF ePed = CHAR_FRANKLIN
STAT_GET_FLOAT(SP1_DIST_WALK_ST, fTempStatValue)
fFinalStatValue = ((fTempStatValue-g_savedGlobals.sPlayerData.sInfo.fStatOffset_DistStealth[ePed]) / 45)
ELIF ePed = CHAR_TREVOR
STAT_GET_FLOAT(SP2_DIST_WALK_ST, fTempStatValue)
fFinalStatValue = ((fTempStatValue-g_savedGlobals.sPlayerData.sInfo.fStatOffset_DistStealth[ePed]) / 45)
ELIF ePed = CHAR_MULTIPLAYER
fFinalStatValue = (GET_MP_FLOAT_CHARACTER_STAT(MP_STAT_DIST_WALK_ST #IF USE_TU_CHANGES , iSlot #ENDIF ) / 45)
ENDIF
// 1% for every 2 stealth kills
IF ePed = CHAR_MICHAEL
STAT_GET_INT(SP0_KILLS_STEALTH, iTempStatValue)
fFinalStatValue += ((TO_FLOAT(iTempStatValue-g_savedGlobals.sPlayerData.sInfo.iStatOffset_StealtKills[ePed]) / 2) * 1.5)
ELIF ePed = CHAR_FRANKLIN
STAT_GET_INT(SP1_KILLS_STEALTH, iTempStatValue)
fFinalStatValue += ((TO_FLOAT(iTempStatValue-g_savedGlobals.sPlayerData.sInfo.iStatOffset_StealtKills[ePed]) / 2) * 1.5)
ELIF ePed = CHAR_TREVOR
STAT_GET_INT(SP2_KILLS_STEALTH, iTempStatValue)
fFinalStatValue += ((TO_FLOAT(iTempStatValue-g_savedGlobals.sPlayerData.sInfo.iStatOffset_StealtKills[ePed]) / 2) * 1.5)
ELIF ePed = CHAR_MULTIPLAYER
iTempStatValue = GET_MP_INT_CHARACTER_STAT(MP_STAT_KILLS_STEALTH #IF USE_TU_CHANGES , iSlot #ENDIF )
fFinalStatValue += ((TO_FLOAT(iTempStatValue) / 2) * 1.5)
// Give player extra 20% of Bosses Rank
APPLY_GANG_BOSS_STAT_INCREASE_FOR_GOONS(fFinalStatValue)
ENDIF
BREAK
CASE PS_SHOOTING_ABILITY
INT iOnMissionHits
INT iOffMissionHits
// 1% for every 40 hits on mission
// 1% for every 80 hits off mission
IF ePed = CHAR_MICHAEL
STAT_GET_INT(SP0_HITS_MISSION, iOnMissionHits)
STAT_GET_INT(SP0_HITS_PEDS_VEHICLES, iOffMissionHits)
iOffMissionHits -= iOnMissionHits
fFinalStatValue = (TO_FLOAT(iOnMissionHits-g_savedGlobals.sPlayerData.sInfo.iStatOffset_HitsMission[ePed]) / 40)
fFinalStatValue += (TO_FLOAT(iOffMissionHits-g_savedGlobals.sPlayerData.sInfo.iStatOffset_HitsOffMission[ePed]) / 80)
ELIF ePed = CHAR_FRANKLIN
STAT_GET_INT(SP1_HITS_MISSION, iOnMissionHits)
STAT_GET_INT(SP1_HITS_PEDS_VEHICLES, iOffMissionHits)
iOffMissionHits -= iOnMissionHits
fFinalStatValue = (TO_FLOAT(iOnMissionHits-g_savedGlobals.sPlayerData.sInfo.iStatOffset_HitsMission[ePed]) / 40)
fFinalStatValue += (TO_FLOAT(iOffMissionHits-g_savedGlobals.sPlayerData.sInfo.iStatOffset_HitsOffMission[ePed]) / 80)
ELIF ePed = CHAR_TREVOR
STAT_GET_INT(SP2_HITS_MISSION, iOnMissionHits)
STAT_GET_INT(SP2_HITS_PEDS_VEHICLES, iOffMissionHits)
iOffMissionHits -= iOnMissionHits
fFinalStatValue = (TO_FLOAT(iOnMissionHits-g_savedGlobals.sPlayerData.sInfo.iStatOffset_HitsMission[ePed]) / 40)
fFinalStatValue += (TO_FLOAT(iOffMissionHits-g_savedGlobals.sPlayerData.sInfo.iStatOffset_HitsOffMission[ePed]) / 80)
ELIF ePed = CHAR_MULTIPLAYER
iOffMissionHits = GET_MP_INT_CHARACTER_STAT(MP_STAT_HITS_PEDS_VEHICLES #IF USE_TU_CHANGES , iSlot #ENDIF )
fFinalStatValue += (TO_FLOAT(iOffMissionHits) / 80)
ENDIF
IF ePed = CHAR_MICHAEL
OR ePed = CHAR_FRANKLIN
OR ePed = CHAR_TREVOR
// 3% for every gold challenge complete
// 2% for every silver challenge complete
// 1% for every bronze challenge complete
INT iRangeChallenge
INT iGold, iSilver, iBronze
REPEAT ENUM_TO_INT(RT_MAX_ROUND_TYPES) iRangeChallenge
SWITCH GET_RANGE_CHALLENGE_ROUND_MEDAL(INT_TO_ENUM(RANGE_ROUND_TYPE, iRangeChallenge), ePed)
CASE RRM_GOLD iGold++ BREAK
CASE RRM_SILVER iSilver++ BREAK
CASE RRM_BRONZE iBronze++ BREAK
ENDSWITCH
ENDREPEAT
fFinalStatValue += (iGold * 3)
fFinalStatValue += (iSilver * 2)
fFinalStatValue += (iBronze * 1)
ELIF ePed = CHAR_MULTIPLAYER
// 1% for every win
fFinalStatValue += (GET_MP_INT_PLAYER_STAT(MPPLY_SHOOTINGRANGE_WINS ) * 1)
// Give player extra 20% of Bosses Rank
APPLY_GANG_BOSS_STAT_INCREASE_FOR_GOONS(fFinalStatValue)
ENDIF
BREAK
ENDSWITCH
// Add up all the values and clamp
IF ePlayerStat != PS_SPECIAL_ABILITY
INT iInitialStatValue = GET_INITIAL_STAT_VALUE(ePed, ePlayerStat #IF USE_TU_CHANGES , iSlot #ENDIF )
fFinalStatValue += iInitialStatValue
#IF IS_DEBUG_BUILD
IF GET_COMMANDLINE_PARAM_EXISTS("sc_PrintCharSelectStats")
PRINTLN("CALCULATE_PLAYER_STAT_VALUE: !SPECIAL_ABILITY BEFORE fFinalStatValue = ", fFinalStatValue, " iInitialStatValue = ",iInitialStatValue, " iSlot = ", iSlot, " " )
ENDIF
#ENDIF
fFinalStatValue += GET_STAT_UPDATES_FROM_SCRIPT(ePed, ePlayerStat #IF USE_TU_CHANGES , iSlot #ENDIF )
#IF IS_DEBUG_BUILD
IF GET_COMMANDLINE_PARAM_EXISTS("sc_PrintCharSelectStats")
PRINTLN("CALCULATE_PLAYER_STAT_VALUE: !SPECIAL_ABILITY fFinalStatValue = ", fFinalStatValue, " iInitialStatValue = ",iInitialStatValue, " iSlot = ", iSlot, " " )
ENDIF
#ENDIF
#IF IS_DEBUG_BUILD
IF g_iDebugPlayerStatOffset[ePlayerStat] != -1
fFinalStatValue = TO_FLOAT(g_iDebugPlayerStatOffset[ePlayerStat])
#IF IS_DEBUG_BUILD
IF GET_COMMANDLINE_PARAM_EXISTS("sc_PrintCharSelectStats")
PRINTLN("CALCULATE_PLAYER_STAT_VALUE: DBUG_STAT_OFFSET fFinalStatValue = ", fFinalStatValue, " iSlot = ", iSlot, " " )
ENDIF
#ENDIF
ENDIF
#ENDIF
ENDIF
// Stats are displayed in steps - |20|40|60|80|100|
IF bApplyFeedUpdateFreqCap
FLOAT fNextStep = (fFinalStatValue-((fFinalStatValue%GET_FEED_UPDATE_FREQ(ePed, ePlayerStat))))
IF (fFinalStatValue%GET_FEED_UPDATE_FREQ(ePed, ePlayerStat) >= 0)
fNextStep += GET_FEED_UPDATE_FREQ(ePed, ePlayerStat)
ENDIF
IF fFinalStatValue >= fNextStep
fFinalStatValue = fNextStep
ELSE
fFinalStatValue = (fNextStep-GET_FEED_UPDATE_FREQ(ePed, ePlayerStat))
ENDIF
// // Make sure it doesnt go below the initial value
// IF fFinalStatValue < TO_FLOAT(iInitialStatValue)
// fFinalStatValue = TO_FLOAT(iInitialStatValue)
// ENDIF
ENDIF
#IF IS_DEBUG_BUILD
IF GET_COMMANDLINE_PARAM_EXISTS("sc_PrintCharSelectStats")
PRINTLN("CALCULATE_PLAYER_STAT_VALUE: BEFORE CLAMP fFinalStatValue = ", fFinalStatValue, " iSlot = ", iSlot, " " )
ENDIF
#ENDIF
iFinalStatValue = FLOOR(fFinalStatValue)
iFinalStatValue = CLAMP_INT(iFinalStatValue, 0, 100)
#IF IS_DEBUG_BUILD
IF GET_COMMANDLINE_PARAM_EXISTS("sc_PrintCharSelectStats")
PRINTLN("CALCULATE_PLAYER_STAT_VALUE: RETURN fFinalStatValue = ", fFinalStatValue, " iSlot = ", iSlot, " " )
ENDIF
#ENDIF
RETURN iFinalStatValue
ENDFUNC
/// PURPOSE: Returns TRUE if the default stat values have been set
FUNC BOOL HAVE_DEFAULT_PLAYER_STATS_BEEN_SET()
IF NETWORK_IS_GAME_IN_PROGRESS()
RETURN TRUE // TODO
ELSE
RETURN g_savedGlobals.sPlayerData.sInfo.bDefaultStatsSet
ENDIF
ENDFUNC
/// PURPOSE: Set all the default player stats to 20
/// NOTE: At some point we can set up variable stats for each
/// player character, along with upper/lower limits.
PROC SETUP_DEFAULT_PLAYER_STATS()
PRINTSTRING("\nSetting default player stats")PRINTNL()
IF NETWORK_IS_GAME_IN_PROGRESS()
INT iStat
STATSENUM eSPStat
MP_INT_STATS eMPStat
// For each RPG stat...
REPEAT NUMBER_OF_PLAYER_STATS iStat
IF INT_TO_ENUM(PLAYER_STATS_ENUM, iStat) != PS_SPECIAL_ABILITY
// Reset the stat value
GET_PLAYER_PED_STAT_ENUM(CHAR_MULTIPLAYER, INT_TO_ENUM(PLAYER_STATS_ENUM, iStat), eSPStat, eMPStat)
SET_MP_INT_CHARACTER_STAT(eMPStat, GET_INITIAL_STAT_VALUE(CHAR_MULTIPLAYER, INT_TO_ENUM(PLAYER_STATS_ENUM, iStat)))
ENDIF
ENDREPEAT
SET_MP_BOOL_CHARACTER_STAT(MP_STAT_DEFAULT_STATS_SET, TRUE)
g_bPerformCustomStatUpdate = TRUE
ELSE
INT iPed, iStat
STATSENUM eSPStat
MP_INT_STATS eMPStat
// For each ped...
REPEAT NUM_OF_PLAYABLE_PEDS iPed
// For each RPG stat...
REPEAT NUMBER_OF_PLAYER_STATS iStat
IF INT_TO_ENUM(PLAYER_STATS_ENUM, iStat) != PS_SPECIAL_ABILITY
// Reset the stat value
GET_PLAYER_PED_STAT_ENUM(INT_TO_ENUM(enumCharacterList, iPed), INT_TO_ENUM(PLAYER_STATS_ENUM, iStat), eSPStat, eMPStat)
STAT_SET_INT(eSPStat, GET_INITIAL_STAT_VALUE(INT_TO_ENUM(enumCharacterList, iPed), INT_TO_ENUM(PLAYER_STATS_ENUM, iStat)))
ENDIF
ENDREPEAT
ENDREPEAT
g_savedGlobals.sPlayerData.sInfo.iTrackedSpecialAbilityUnlock[CHAR_MICHAEL] = GET_INITIAL_STAT_VALUE(CHAR_MICHAEL, PS_SPECIAL_ABILITY)
g_savedGlobals.sPlayerData.sInfo.iTrackedSpecialAbilityUnlock[CHAR_FRANKLIN] = GET_INITIAL_STAT_VALUE(CHAR_FRANKLIN, PS_SPECIAL_ABILITY)
g_savedGlobals.sPlayerData.sInfo.iTrackedSpecialAbilityUnlock[CHAR_TREVOR] = GET_INITIAL_STAT_VALUE(CHAR_TREVOR, PS_SPECIAL_ABILITY)
g_savedGlobals.sPlayerData.sInfo.bDefaultStatsSet = TRUE
g_bPerformCustomStatUpdate = TRUE
ENDIF
ENDPROC
/// PURPOSE: Stuff we need to process on the player when we do a switch or update a stat
PROC UPDATE_PLAYER_STAT_SETTINGS(enumCharacterList ePed, PLAYER_STATS_ENUM ePlayerStat)
IF ePed != CHAR_MICHAEL
OR ePed != CHAR_FRANKLIN
OR ePed != CHAR_TREVOR
OR ePed != CHAR_MULTIPLAYER
EXIT
ENDIF
INT iStatValue
FLOAT fModifierValue
STATSENUM eSPStat
MP_INT_STATS eMPStat
// Grab the stat value
GET_PLAYER_PED_STAT_ENUM(ePed, ePlayerStat, eSPStat, eMPStat)
IF NETWORK_IS_GAME_IN_PROGRESS()
iStatValue = GET_MP_INT_CHARACTER_STAT(eMPStat)
ELSE
STAT_GET_INT(eSPStat, iStatValue)
ENDIF
SWITCH ePlayerStat
CASE PS_STRENGTH
// Melee stat is a percentage value and we want to keep the modifier value within the range of 0.8 and 1.2
fModifierValue = 0.8 + (0.4*(TO_FLOAT(iStatValue)/100))
SET_PLAYER_MELEE_WEAPON_DAMAGE_MODIFIER(PLAYER_ID(), fModifierValue)
BREAK
CASE PS_STEALTH_ABILITY
// Stealth stat is a percentage value and we want to keep the modifier value within the range of 0.0 and 1.0
// These native command are currently used on some missions so dont set when runnung
IF GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("armenian3")) != 0
OR GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("trevor3")) != 0
g_bPerformCustomStatUpdateWhenMissionEnds = TRUE
ELSE
fModifierValue = 1.0 - (TO_FLOAT(iStatValue)/100)
SET_PLAYER_NOISE_MULTIPLIER(PLAYER_ID(), fModifierValue)
SET_PLAYER_SNEAKING_NOISE_MULTIPLIER(PLAYER_ID(), fModifierValue)
SET_PLAYER_STEALTH_PERCEPTION_MODIFIER(PLAYER_ID(), fModifierValue)
ENDIF
BREAK
ENDSWITCH
ENDPROC
PROC UPDATE_ALL_PLAYER_STAT_SETTINGS(enumCharacterList ePed)
INT iStat
REPEAT NUMBER_OF_PLAYER_STATS iStat
UPDATE_PLAYER_STAT_SETTINGS(ePed, INT_TO_ENUM(PLAYER_STATS_ENUM, iStat))
ENDREPEAT
ENDPROC