2022-05-21 23:10:17 +02:00
# pragma semicolon 1
# define PLUGIN_AUTHOR "jenz"
2023-04-09 13:57:39 +02:00
# define PLUGIN_VERSION "1.1"
2022-05-21 23:10:17 +02:00
# include <sourcemod>
2023-04-09 13:57:39 +02:00
# include <PlayerManager>
# include <AFKManager>
2022-05-21 23:10:17 +02:00
Database g_hDatabase ;
2023-04-09 13:57:39 +02:00
//check if autismbot
bool is_bot_player [ MAXPLAYERS + 1 ] ;
2022-06-15 21:56:44 +02:00
Handle g_h_time_activity = null ;
2023-03-19 16:12:37 +01:00
char g_cTimeRecords [ 100 ] [ 128 ] ;
2023-04-09 13:57:39 +02:00
int g_iPlayerTimeServer [ MAXPLAYERS + 1 ] ;
int g_iPlayerAFKTime ;
2022-05-21 23:10:17 +02:00
public Plugin myinfo =
{
name = " UNLOZE_player_time " ,
author = PLUGIN_AUTHOR ,
description = " checks playtime on servers " ,
version = PLUGIN_VERSION ,
url = " www.unloze.com "
} ;
2023-04-23 20:21:28 +02:00
//timer
Handle g_hTimer_avg_hour_count = null ;
2022-05-21 23:10:17 +02:00
public Action time_query_activity ( Handle timer , any data )
{
2022-06-15 21:56:44 +02:00
if ( ! g_hDatabase )
{
Database . Connect ( SQL_OnDatabaseConnect , " unloze_playtimestats " ) ;
return Plugin_Continue ;
}
2022-05-21 23:10:17 +02:00
for ( int client = 1 ; client < = MaxClients ; client + + )
if ( IsValidClient ( client ) & & ! IsFakeClient ( client ) & & IsPlayerAlive ( client ) )
{
char sAuthID [ 32 ] ;
GetClientAuthId ( client , AuthId_Steam2 , sAuthID , sizeof ( sAuthID ) , false ) ;
char sIP [ 32 ] ;
GetClientIP ( client , sIP , sizeof ( sIP ) ) ;
char sQuery [ 512 ] ;
char sServer [ 64 ] ;
int i_port = GetConVarInt ( FindConVar ( " hostport " ) ) ;
if ( i_port = = 27015 )
{
Format ( sServer , sizeof ( sServer ) , " ze_time " ) ;
}
else if ( i_port = = 27016 )
{
Format ( sServer , sizeof ( sServer ) , " zr_time " ) ;
}
else if ( i_port = = 27017 )
{
Format ( sServer , sizeof ( sServer ) , " mg_time " ) ;
}
else if ( i_port = = 27023 )
{
Format ( sServer , sizeof ( sServer ) , " jb_time " ) ;
}
else
{
continue ;
}
char sName [ MAX_NAME_LENGTH ] ;
GetClientName ( client , sName , sizeof ( sName ) ) ;
int size2 = 2 * strlen ( sName ) + 1 ;
char [ ] sEscapedName = new char [ size2 + 1 ] ;
g_hDatabase . Escape ( sName , sEscapedName , size2 + 1 ) ;
2023-04-16 19:45:10 +02:00
Format ( sQuery , sizeof ( sQuery ) , " update unloze_playtimestats.player_time set `%s` = `%s` + 10 where steam_id = '%s' and ipv4 = '%s' " , sServer , sServer , sAuthID , sIP ) ;
g_hDatabase . Query ( SQL_FinishedQuery , sQuery , _ , DBPrio_Low ) ;
Format ( sQuery , sizeof ( sQuery ) , " update unloze_playtimestats.player_time set player_name = '%s' where steam_id = '%s' " , sEscapedName , sAuthID ) ;
2023-02-19 15:41:54 +01:00
g_hDatabase . Query ( SQL_FinishedQuery , sQuery , _ , DBPrio_Low ) ;
2022-05-21 23:10:17 +02:00
}
return Plugin_Continue ;
}
public void OnPluginStart ( )
{
Database . Connect ( SQL_OnDatabaseConnect , " unloze_playtimestats " ) ;
2022-06-15 21:56:44 +02:00
RegConsoleCmd ( " sm_playtime " , Command_Time , " retreives total connection time on all connected servers " ) ;
RegConsoleCmd ( " sm_topplaytime " , Command_TopTime , " retreives top 12 playtime highscores on all connected servers " ) ;
g_h_time_activity = CreateTimer ( 10.0 , time_query_activity , INVALID_HANDLE , TIMER_REPEAT ) ;
2023-04-09 13:57:39 +02:00
ConVar cvar ;
HookConVarChange ( ( cvar = CreateConVar ( " sm_mapchooser_afk_detect_time " , " 120 " , " Time in seconds until a player is considered as AFK and therefore excluded from player average time. " ) ) , Cvar_playerAFKTime ) ;
g_iPlayerAFKTime = cvar . IntValue ;
delete cvar ;
2023-04-23 20:21:28 +02:00
g_hTimer_avg_hour_count = CreateTimer ( 1800.0 , log_average_hour_count , _ , TIMER_REPEAT ) ;
}
public Action log_average_hour_count ( Handle timer , any data )
{
int i_port = GetConVarInt ( FindConVar ( " hostport " ) ) ;
int avg_hour = GetAveragePlayerActiveTimeServer ( ) ;
if ( ! g_hDatabase )
{
Database . Connect ( SQL_OnDatabaseConnect , " unloze_playtimestats " ) ;
return Plugin_Handled ;
}
char sQuery [ 512 ] ;
Format ( sQuery , sizeof ( sQuery ) , " INSERT INTO `average_hours` (`avg_hour`, `server_port`) VALUES ('%i', '%i') " , avg_hour , i_port ) ;
g_hDatabase . Query ( SQL_FinishedQuery , sQuery , _ , DBPrio_Low ) ;
return Plugin_Continue ;
2023-04-09 13:57:39 +02:00
}
public void Cvar_playerAFKTime ( ConVar convar , const char [ ] oldValue , const char [ ] newValue )
{
g_iPlayerAFKTime = convar . IntValue ;
}
public APLRes AskPluginLoad2 ( Handle myself , bool late , char [ ] error , int err_max )
{
CreateNative ( " GetAveragePlayerTimeOnServer " , Native_GetAveragePlayerActiveTimeServer ) ;
return APLRes_Success ;
2022-06-15 21:56:44 +02:00
}
2023-04-23 20:21:28 +02:00
public int GetAveragePlayerActiveTimeServer ( )
2023-04-09 13:57:39 +02:00
{
int total_hours = 0 ;
int total_players = 0 ;
for ( int i = 0 ; i < MaxClients ; i + + )
{
if ( IsValidClient ( i ) & & ! IsFakeClient ( i ) & & ! IsClientSourceTV ( i ) & & ! is_bot_player [ i ] & & PM_IsPlayerSteam ( i ) & & GetClientIdleTime ( i ) < g_iPlayerAFKTime )
{
total_hours + = g_iPlayerTimeServer [ i ] ;
total_players + + ;
}
}
if ( total_hours = = 0 )
{
return 0 ;
}
return total_hours / total_players ;
}
2023-04-23 20:21:28 +02:00
public int Native_GetAveragePlayerActiveTimeServer ( Handle plugin , int numParams )
{
return GetAveragePlayerActiveTimeServer ( ) ;
}
2022-06-15 21:56:44 +02:00
public void OnPluginEnd ( )
{
if ( g_h_time_activity ! = null )
delete g_h_time_activity ;
2023-04-23 20:21:28 +02:00
if ( g_hTimer_avg_hour_count ! = null )
{
delete g_hTimer_avg_hour_count ;
}
2022-05-21 23:10:17 +02:00
}
public void SQL_OnDatabaseConnect ( Database db , const char [ ] error , any data )
{
if ( ! db | | strlen ( error ) )
{
2023-04-09 13:57:39 +02:00
LogError ( " Database error: %s " , error ) ;
return ;
2022-05-21 23:10:17 +02:00
}
g_hDatabase = db ;
for ( int i = 1 ; i < = MaxClients ; i + + )
OnClientPostAdminCheck ( i ) ;
2023-03-19 16:12:37 +01:00
OnMapStart ( ) ;
2022-05-21 23:10:17 +02:00
}
public void OnClientPostAdminCheck ( int client )
{
2023-04-09 13:57:39 +02:00
is_bot_player [ client ] = false ;
g_iPlayerTimeServer [ client ] = 0 ;
2022-05-21 23:10:17 +02:00
if ( ! IsValidClient ( client ) | | IsFakeClient ( client ) )
return ;
if ( ! g_hDatabase )
{
Database . Connect ( SQL_OnDatabaseConnect , " unloze_playtimestats " ) ;
return ;
}
insert_client ( client ) ;
2023-04-09 13:57:39 +02:00
select_client_time_server ( client ) ;
char auth [ 50 ] ;
GetClientAuthId ( client , AuthId_Engine , auth , sizeof ( auth ) ) ;
if ( StrEqual ( " [U:1:1221121532] " , auth , false ) | | StrEqual ( " STEAM_0:0:610560766 " , auth , false ) )
{
is_bot_player [ client ] = true ;
}
if ( StrEqual ( " [U:1:408797742] " , auth , false ) | | StrEqual ( " STEAM_0:0:204398871 " , auth , false ) )
{
is_bot_player [ client ] = true ;
}
if ( StrEqual ( " [U:1:1036189204] " , auth , false ) | | StrEqual ( " STEAM_0:0:518094602 " , auth , false ) )
{
is_bot_player [ client ] = true ;
}
if ( StrEqual ( " [U:1:120378081] " , auth , false ) | | StrEqual ( " STEAM_0:1:60189040 " , auth , false ) )
{
is_bot_player [ client ] = true ;
}
}
public void select_client_time_server ( int client )
{
char sServer [ 32 ] ;
int i_port = GetConVarInt ( FindConVar ( " hostport " ) ) ;
if ( i_port = = 27015 | | i_port = = 27019 )
{
Format ( sServer , sizeof ( sServer ) , " ze_time " ) ;
}
else if ( i_port = = 27016 )
{
Format ( sServer , sizeof ( sServer ) , " zr_time " ) ;
}
else if ( i_port = = 27017 )
{
Format ( sServer , sizeof ( sServer ) , " mg_time " ) ;
}
else if ( i_port = = 27023 )
{
Format ( sServer , sizeof ( sServer ) , " jb_time " ) ;
}
else
{
return ;
}
char sQuery [ 512 ] ;
char sAuthID [ 32 ] ;
GetClientAuthId ( client , AuthId_Steam2 , sAuthID , sizeof ( sAuthID ) , false ) ;
Format ( sQuery , sizeof ( sQuery ) , " select sum(%s) as %s_total from unloze_playtimestats.player_time pt where pt.steam_id = '%s' GROUP BY steam_id order by %s_total desc " , sServer , sServer , sAuthID , sServer ) ;
g_hDatabase . Query ( SQL_OnQueryCompletedTimeServer , sQuery , GetClientSerial ( client ) ) ;
}
public void SQL_OnQueryCompletedTimeServer ( Database db , DBResultSet results , const char [ ] error , int iSerial )
{
if ( ! db | | strlen ( error ) )
{
LogError ( " Query error 3: %s " , error ) ;
}
int client ;
if ( ( client = GetClientFromSerial ( iSerial ) ) = = 0 )
return ;
int iTime_Server ;
while ( results . RowCount & & results . FetchRow ( ) )
{
iTime_Server + = results . FetchInt ( 0 ) ;
}
delete results ;
int iHours_Server = ( iTime_Server / 60 ) / 60 ;
g_iPlayerTimeServer [ client ] = iHours_Server ;
}
public void OnClientDisconnect ( int client )
{
is_bot_player [ client ] = false ;
g_iPlayerTimeServer [ client ] = 0 ;
2022-05-21 23:10:17 +02:00
}
public void insert_client ( int client )
{
char sAuthID [ 32 ] ;
GetClientAuthId ( client , AuthId_Steam2 , sAuthID , sizeof ( sAuthID ) , false ) ;
char sName [ MAX_NAME_LENGTH ] ;
GetClientName ( client , sName , sizeof ( sName ) ) ;
int size2 = 2 * strlen ( sName ) + 1 ;
char [ ] sEscapedName = new char [ size2 + 1 ] ;
g_hDatabase . Escape ( sName , sEscapedName , size2 + 1 ) ;
char sIP [ 32 ] ;
GetClientIP ( client , sIP , sizeof ( sIP ) ) ;
char sQuery [ 512 ] ;
Format ( sQuery , sizeof ( sQuery ) , " INSERT INTO `player_time` (`steam_id`, `ipv4`, `player_name`, `ze_time`, `mg_time`, `zr_time`, `jb_time`) VALUES ('%s', '%s', '%s', 0, 0, 0, 0) ON DUPLICATE KEY UPDATE `player_name` = '%s' " , sAuthID , sIP , sEscapedName , sEscapedName ) ;
2023-02-19 15:41:54 +01:00
g_hDatabase . Query ( SQL_FinishedQuery , sQuery , _ , DBPrio_Low ) ;
2022-05-21 23:10:17 +02:00
}
2022-06-15 21:56:44 +02:00
public void SQL_FinishedQuery ( Database db , DBResultSet results , const char [ ] error , any data )
2022-05-21 23:10:17 +02:00
{
2023-04-23 20:21:28 +02:00
if ( ! db | | strlen ( error ) )
{
LogError ( " Query error 3: %s " , error ) ;
}
delete results ;
2022-05-21 23:10:17 +02:00
}
stock bool IsValidClient ( int client )
{
2023-04-16 19:45:10 +02:00
if ( client > 0 & & client < = MaxClients & & IsClientConnected ( client ) & & IsClientInGame ( client ) )
return true ;
return false ;
2022-05-21 23:10:17 +02:00
}
2022-06-15 21:56:44 +02:00
2023-03-19 16:12:37 +01:00
public void OnMapStart ( )
2022-06-15 21:56:44 +02:00
{
2023-04-23 20:21:28 +02:00
if ( ! g_hDatabase )
{
Database . Connect ( SQL_OnDatabaseConnect , " unloze_playtimestats " ) ;
return ;
}
char sQuery [ 512 ] ;
char sServer [ 32 ] ;
2022-06-15 21:56:44 +02:00
2023-04-23 20:21:28 +02:00
int i_port = GetConVarInt ( FindConVar ( " hostport " ) ) ;
if ( i_port = = 27015 | | i_port = = 27019 )
{
Format ( sServer , sizeof ( sServer ) , " ze_time " ) ;
}
else if ( i_port = = 27016 )
{
Format ( sServer , sizeof ( sServer ) , " zr_time " ) ;
}
else if ( i_port = = 27017 )
{
Format ( sServer , sizeof ( sServer ) , " mg_time " ) ;
}
else if ( i_port = = 27023 )
{
Format ( sServer , sizeof ( sServer ) , " jb_time " ) ;
}
else
{
return ;
}
Format ( sQuery , sizeof ( sQuery ) , " select player_name, sum(%s) as %s_total from unloze_playtimestats.player_time GROUP BY steam_id order by %s_total desc limit 100 " , sServer , sServer , sServer ) ;
g_hDatabase . Query ( SQL_OnQueryCompletedTopTime , sQuery ) ;
2023-03-19 16:12:37 +01:00
}
public Action Command_TopTime ( int client , int args )
{
char sTitle [ 64 ] ;
char sServer [ 32 ] ;
int i_port = GetConVarInt ( FindConVar ( " hostport " ) ) ;
if ( i_port = = 27015 | | i_port = = 27019 )
{
Format ( sServer , sizeof ( sServer ) , " ZE " ) ;
}
else if ( i_port = = 27016 )
{
Format ( sServer , sizeof ( sServer ) , " ZR " ) ;
}
else if ( i_port = = 27017 )
{
Format ( sServer , sizeof ( sServer ) , " MG " ) ;
}
else if ( i_port = = 27023 )
{
Format ( sServer , sizeof ( sServer ) , " JB " ) ;
}
Format ( sTitle , sizeof ( sTitle ) , " [UNLOZE Playtime] Top 100 Record Holders for %s: " , sServer ) ;
Menu menu = new Menu ( MenuHandler1 ) ;
menu . SetTitle ( sTitle ) ;
for ( int i = 0 ; i < sizeof ( g_cTimeRecords ) ; i + + )
{
menu . AddItem ( " -1 " , g_cTimeRecords [ i ] , ITEMDRAW_DISABLED ) ;
}
menu . ExitButton = true ;
menu . Display ( client , 0 ) ;
2022-06-15 21:56:44 +02:00
}
public Action Command_Time ( int client , int args )
{
if ( ! g_hDatabase )
{
Database . Connect ( SQL_OnDatabaseConnect , " unloze_playtimestats " ) ;
return Plugin_Handled ;
}
char sQuery [ 512 ] ;
char sAuthID [ 32 ] ;
GetClientAuthId ( client , AuthId_Steam2 , sAuthID , sizeof ( sAuthID ) , false ) ;
Format ( sQuery , sizeof ( sQuery ) , " select ze_time, mg_time, zr_time, jb_time from unloze_playtimestats.player_time pt where pt.steam_id = '%s' " , sAuthID ) ;
g_hDatabase . Query ( SQL_OnQueryCompletedTime , sQuery , GetClientSerial ( client ) ) ;
return Plugin_Handled ;
}
public void SQL_OnQueryCompletedTopTime ( Database db , DBResultSet results , const char [ ] error , int iSerial )
{
if ( ! db | | strlen ( error ) )
{
LogError ( " Query error 3: %s " , error ) ;
}
int iTime ;
char sName [ MAX_NAME_LENGTH ] ;
2023-03-19 16:12:37 +01:00
int counter = 0 ;
2022-06-15 21:56:44 +02:00
while ( results . RowCount & & results . FetchRow ( ) )
{
char sBuffer [ 256 ] ;
2023-03-19 16:12:37 +01:00
results . FetchString ( 0 , sName , sizeof ( sName ) ) ;
iTime = results . FetchInt ( 1 ) ;
2022-06-15 21:56:44 +02:00
int iHours = ( iTime / 60 ) / 60 ;
2023-03-19 16:12:37 +01:00
Format ( sBuffer , sizeof ( sBuffer ) , " %i %s %d Hours " , counter + 1 , sName , iHours ) ;
Format ( g_cTimeRecords [ counter ] , sizeof ( g_cTimeRecords [ ] ) , sBuffer ) ;
2022-06-15 21:56:44 +02:00
counter + + ;
}
delete results ;
}
2023-03-19 16:12:37 +01:00
public int MenuHandler1 ( Menu menu , MenuAction action , int param1 , int param2 )
{
switch ( action )
{
case MenuAction_End :
{
delete menu ;
}
}
return 0 ;
}
2022-06-15 21:56:44 +02:00
public void SQL_OnQueryCompletedTime ( Database db , DBResultSet results , const char [ ] error , int iSerial )
{
if ( ! db | | strlen ( error ) )
{
LogError ( " Query error 3: %s " , error ) ;
}
int client ;
if ( ( client = GetClientFromSerial ( iSerial ) ) = = 0 )
return ;
int iTime_ze ;
int iTime_mg ;
int iTime_zr ;
int iTime_jb ;
while ( results . RowCount & & results . FetchRow ( ) )
{
iTime_ze + = results . FetchInt ( 0 ) ;
iTime_mg + = results . FetchInt ( 1 ) ;
iTime_zr + = results . FetchInt ( 2 ) ;
iTime_jb + = results . FetchInt ( 3 ) ;
}
delete results ;
int iHours_ze = ( iTime_ze / 60 ) / 60 ;
int iMinutes_ze = ( iTime_ze / 60 ) % 60 ;
int iSeconds_ze = ( iTime_ze % 60 ) ;
int iHours_mg = ( iTime_mg / 60 ) / 60 ;
int iMinutes_mg = ( iTime_mg / 60 ) % 60 ;
int iSeconds_mg = ( iTime_mg % 60 ) ;
int iHours_zr = ( iTime_zr / 60 ) / 60 ;
int iMinutes_zr = ( iTime_zr / 60 ) % 60 ;
int iSeconds_zr = ( iTime_zr % 60 ) ;
int iHours_jb = ( iTime_jb / 60 ) / 60 ;
int iMinutes_jb = ( iTime_jb / 60 ) % 60 ;
int iSeconds_jb = ( iTime_jb % 60 ) ;
char sTime_ze [ 64 ] ;
char sTime_mg [ 64 ] ;
char sTime_zr [ 64 ] ;
char sTime_jb [ 64 ] ;
char sTitle [ 64 ] ;
Format ( sTitle , sizeof ( sTitle ) , " [UNLOZE Playtime] Player %N: " , client ) ;
Format ( sTime_ze , sizeof ( sTime_ze ) , " Zombie Escape: %d Hours %d Minutes %d Seconds " , iHours_ze , iMinutes_ze , iSeconds_ze ) ;
Format ( sTime_mg , sizeof ( sTime_mg ) , " MiniGame: %d Hours %d Minutes %d Seconds " , iHours_mg , iMinutes_mg , iSeconds_mg ) ;
Format ( sTime_zr , sizeof ( sTime_zr ) , " Zombie Riot: %d Hours %d Minutes %d Seconds " , iHours_zr , iMinutes_zr , iSeconds_zr ) ;
Format ( sTime_jb , sizeof ( sTime_jb ) , " Jail Break: %d Hours %d Minutes %d Seconds " , iHours_jb , iMinutes_jb , iSeconds_jb ) ;
Panel mSayPanel = new Panel ( GetMenuStyleHandle ( MenuStyle_Radio ) ) ;
mSayPanel . SetTitle ( sTitle ) ;
mSayPanel . DrawItem ( " " , ITEMDRAW_SPACER ) ;
mSayPanel . DrawText ( sTime_ze ) ;
mSayPanel . DrawItem ( " " , ITEMDRAW_SPACER ) ;
mSayPanel . DrawText ( sTime_mg ) ;
mSayPanel . DrawItem ( " " , ITEMDRAW_SPACER ) ;
mSayPanel . DrawText ( sTime_zr ) ;
mSayPanel . DrawItem ( " " , ITEMDRAW_SPACER ) ;
mSayPanel . DrawText ( sTime_jb ) ;
mSayPanel . DrawItem ( " " , ITEMDRAW_SPACER ) ;
mSayPanel . DrawItem ( " 1. Got it! " , ITEMDRAW_RAWLINE ) ;
mSayPanel . SetKeys ( 1023 ) ;
mSayPanel . Send ( client , Handler_Menu , 0 ) ;
delete mSayPanel ;
}
public int Handler_Menu ( Menu menu , MenuAction action , int param1 , int param2 )
{
switch ( action )
{
case MenuAction_Select , MenuAction_Cancel :
delete menu ;
}
}