#include <amxmodx>
#include <engine>
#include <hamsandwich>
#include <fakemeta>
#include <mysqlt>
#include <prophunt>
/* =====================================================================
* [ Global stuff ]
* ===================================================================== */
#define SetPlayerBit(%1,%2) ( %1 |= ( 1 << ( %2 & 31 ) ) )
#define ClearPlayerBit(%1,%2) ( %1 &= ~( 1 << ( %2 & 31 ) ) )
#define GetPlayerBit(%1,%2) ( %1 & ( 1 << ( %2 & 31 ) ) )
#define isDigit(%0) ( 48 <= %0 <= 57 )
#define isLetter(%0) ( 65 <= %0 <= 90 || 97 <= %0 <= 122 )
#define IsPlayerValid(%0) ( 1 <= %0 <= 32 )
#define IsUserPlaying(%0) ( g_ePlayerAccount[ %0 ][ Account_Status ] == Status_Playing )
#define GetNeededExp(%0) floatround( floatpower( ( %0 * 6.0 ), 3.0 ) )
#define GetHiderExp ( ( floatround( get_gametime( ) - g_flLastStart ) / HIDER_EXPDIV ) * g_iMultiplier )
#define GetHunterExp ( ( floatround( ( g_flLastStart + g_flTimer ) - get_gametime( ) ) / HUNTER_EXPDIV ) * g_iMultiplier )
#define ShouldLevelUp(%0) ( g_ePlayerStats[ %0 ][ Player_Exp ] >= GetNeededExp( g_ePlayerStats[ %0 ][ Player_Level ] + 1 ) )
#define ShouldRankUp(%0) ( g_ePlayerStats[ %0 ][ Player_Level ] >= g_eRanks[ g_ePlayerStats[ %0 ][ Player_Rank ] + 1 ][ Rank_Level ] )
const m_iVGUI = 510;
const CODE_CHARS = 8;
const MIN_CHARS = 4;
const HIDER_EXPDIV = 4;
const HUNTER_EXPDIV = 7;
enum _:Query_Type
{
Query_Autologin,
Query_Create_User,
Query_Load_User,
Query_Create_Stats,
Query_Load_Stats,
Query_Save,
Query_Top,
Query_Names,
Query_Rank,
Query_Players
}
enum _:Player_Stats
{
Player_Exp,
Player_Rank,
Player_Level,
Player_Frags,
Player_Points,
Player_Hunter,
Player_Hider,
Player_Played
}
enum _:Account_Data
{
Account_Userid,
Account_Status,
Account_Ip[ 32 ],
Account_Name[ 32 ],
Account_Password[ 32 ],
Account_Code[ CODE_CHARS ]
}
enum _:Hud_Color
{
HC_Red,
HC_Green,
HC_Yellow
}
enum _:Rank_Data
{
Rank_Name[ 16 ],
Rank_Level
}
new const g_eRanks[ ][ Rank_Data ] =
{
{ "Nuevo", 1 },
{ "Aprendiz", 4 },
{ "Conocido", 9 },
{ "Miembro", 16 },
{ "Avanzado", 23 },
{ "Astuto", 36 },
{ "Habil", 48 },
{ "Vicio", 66 },
{ "Experto", 78 },
{ "Pro", 110 },
{ "Maestro", 154 },
{ "Inmortal", 198 },
{ "Developer", 300 }
};
new const g_szMultiplierNames[ ][ ] =
{
"cero",
"normal",
"duplicada"
};
new const g_szTeamnames[ ][ ] =
{
"Sin equipo",
"Hiders",
"Hunters",
"Espectadores"
};
new const g_szCache_Name[ ] = "name";
new const g_iHudSounds[ Hud_Color] = { 10, 3, 9 };
new const g_iHudColors[ Hud_Color ][ 3 ] =
{
{ 255, 0, 0 },
{ 0, 255, 0 },
{ 255, 255, 0 }
};
new const g_szLevelUpSound[ ] = "ph/level.wav";
new g_iAlive,
g_iSyncObj,
g_iShowMenu,
g_iVGUIMenu,
g_iConnected,
g_iLoginMenu,
g_iMultiplier,
g_iMaxPlayers,
g_iTotalPlayers,
Float:g_flTimer,
Handle:g_hSQLHost,
Float:g_flLastStart,
g_szMotdInfo[ 1400 ],
g_eTop[ 10 ][ Player_Stats ],
g_ePlayerStats[ 33 ][ Player_Stats ],
g_ePlayerAccount[ 33 ][ Account_Data ];
/* =====================================================================
* [ Plugin events ]
* ===================================================================== */
public plugin_precache( )
{
// Resource precaching
precache_sound( g_szLevelUpSound );
}
public plugin_natives( )
{
// Native registering
register_native( "ph_add_xp", "_ph_add_xp" );
register_native( "ph_get_level", "_ph_get_level" );
register_native( "ph_show_top", "_ph_show_top" );
register_native( "ph_show_rank", "_ph_show_rank" );
register_native( "ph_show_stats", "_ph_show_stats" );
}
public plugin_init( )
{
register_plugin( "[PH] Stats", VERSION, AUTHOR );
// Hook some player events
RegisterHam( Ham_Spawn, "player", "fw_PlayerSpawn_Post", true );
RegisterHam( Ham_Killed, "player", "fw_PlayerKilled_Post", true );
// Block name changing
register_forward( FM_ClientUserInfoChanged, "fw_ClientUserInfoChanged_Pre", false );
// Block team choosing
register_menucmd( register_menuid( "Team_Select", true ), (1<<0)|(1<<1)|(1<<4)|(1<<5), "HookTeamChoosing" );
register_clcmd( "jointeam", "HookTeamChoosing" );
register_clcmd( "chooseteam", "HookTeamChoosing" );
// Hook account-information input
register_clcmd( "INGRESAR_CLAVE", "CommandPassword" );
// Hook say and say_team
register_clcmd( "say", "CommandSay" );
register_clcmd( "say_team", "CommandSayTeam" );
// Default values, etc.
g_iLoginMenu = -1;
g_iMaxPlayers = get_maxplayers( );
g_iSyncObj = CreateHudSyncObj( );
g_iShowMenu = get_user_msgid( "ShowMenu" );
g_iVGUIMenu = get_user_msgid( "VGUIMenu" );
// MySQL initiation, top10 loading, etc.
MySQL_Init( );
}
/* =====================================================================
* [ Forwards & Events ]
* ===================================================================== */
public ph_gamemode( iGamemode )
{
// Game has ended
if( iGamemode & GS_Ended )
{
// Hunters win
if( iGamemode & GS_Hunters )
{
for( new iPlayer = 1; iPlayer <= g_iMaxPlayers; iPlayer++ )
{
if( !GetPlayerBit( g_iConnected, iPlayer ) || ( get_user_team( iPlayer ) != 2 ) )
continue;
g_ePlayerStats[ iPlayer ][ Player_Hunter ]++;
}
}
// Hiders win
else
{
for( new iPlayer = 1; iPlayer <= g_iMaxPlayers; iPlayer++ )
{
if( !GetPlayerBit( g_iConnected, iPlayer ) || ( get_user_team( iPlayer ) != 1 ) )
continue;
g_ePlayerStats[ iPlayer ][ Player_Hider ]++;
if( GetPlayerBit( g_iAlive, iPlayer ) )
{
g_ePlayerStats[ iPlayer ][ Player_Exp ] += GetHiderExp;
UpdateLevel( iPlayer );
}
}
}
}
// Game is preparing (countdown)
else if( iGamemode & GS_Preparing )
{
static szTime[ 16 ], szHour[ 4 ], iHour;
// Get timers
g_flLastStart = get_gametime( );
g_flTimer = get_cvar_float( "mp_roundtime" ) * 60.0;
// Get time, check happyhour and notify about happyhour status
get_time( "%H", szHour, charsmax( szHour ) );
get_time( "%H:%M:%S", szTime, charsmax( szTime ) );
iHour = str_to_num( szHour );
g_iMultiplier = ( 6 >= ( iHour ) >= 0 ) ? 2 : 1;
client_print_color( 0, print_team_default, "^x04[PropHunt]^x01 Hora:^x04 %s^x01^x03 -^x01 Ganancia:^x04 %s^x01.", szTime, g_szMultiplierNames[ g_iMultiplier ] );
}
}
public fw_ClientUserInfoChanged_Pre( iId )
{
// Player must be connected
if( GetPlayerBit( g_iConnected, iId ) )
{
static szName[ 32 ]; get_user_info( iId, g_szCache_Name, szName, charsmax( szName ) );
// If player is logged and his name did change then block the event
if( IsUserPlaying( iId ) && !equal( szName, g_ePlayerAccount[ iId ][ Account_Name ] ) )
{
client_cmd( iId, ";name ^"%s^"", g_ePlayerAccount[ iId ][ Account_Name ] );
set_user_info( iId, g_szCache_Name, g_ePlayerAccount[ iId ][ Account_Name ] );
return FMRES_SUPERCEDE;
}
}
// Nothing happened <3
return FMRES_IGNORED;
}
public fw_PlayerKilled_Post( iVictim, iKiller, iShouldGib )
{
ClearPlayerBit( g_iAlive, iVictim );
// Killer is valid, connected and he didn't kill himself
if( IsPlayerValid( iKiller ) && GetPlayerBit( g_iConnected, iKiller ) && ( iVictim != iKiller ) )
{
// Add a frag to the killer
g_ePlayerStats[ iKiller ][ Player_Frags ]++;
// Add experience to killer and victim
g_ePlayerStats[ iVictim ][ Player_Exp ] += GetHiderExp;
g_ePlayerStats[ iKiller ][ Player_Exp ] += GetHunterExp;
// Update level for both players
UpdateLevel( iKiller );
UpdateLevel( iVictim );
}
return HAM_IGNORED;
}
public fw_PlayerSpawn_Post( iId )
{
// Avoid bugs. Player should be alive by this moment
if( is_user_alive( iId ) )
SetPlayerBit( g_iAlive, iId );
return HAM_IGNORED;
}
/* =====================================================================
* [ Client-related section ]
* ===================================================================== */
public CommandSay( iId )
{
// Player must be logged
if( IsUserPlaying( iId ) )
{
static iLen, szTeam[ 12 ], szBuffer[ 192 ];
// Get say's data and lenght
read_args( szBuffer, charsmax( szBuffer ) );
remove_quotes( szBuffer );
iLen = strlen( szBuffer );
// Character replacement (exploit?)
for( new i, j; i < iLen; i++ )
{
if( szBuffer[ i ] == '#' || szBuffer[ i ] == '%' )
j++;
szBuffer[ i ] = szBuffer[ i + j ]; iLen--;
}
// String lenght is greater than 0
if( iLen > 0 )
{
// Get sender's team
get_user_team( iId, szTeam, charsmax( szTeam ) );
format( szBuffer, charsmax( szBuffer ), "^x01%s^x04[%s]^x03 %s^x01: %s", GetPlayerBit( g_iAlive, iId ) ? "" : "*Muerto* ",
g_eRanks[ g_ePlayerStats[ iId ][ Player_Rank ] ][ Rank_Name ], g_ePlayerAccount[ iId ][ Account_Name ], szBuffer );
// Loop through all players
for( new iPlayer = 1; iPlayer <= g_iMaxPlayers; iPlayer++ )
{
// Player must be connected and have same alive state than sender
if( !GetPlayerBit( g_iConnected, iPlayer ) || ( ( GetPlayerBit( g_iAlive, iId ) && !GetPlayerBit( g_iAlive, iPlayer ) ) || ( !GetPlayerBit( g_iAlive, iId ) && GetPlayerBit( g_iAlive, iPlayer ) ) ) )
continue;
// Send message
client_print_color( iPlayer, iId, szBuffer );
}
}
}
else
client_print_color( iId, print_team_default, "^x04[PropHunt]^x01 No puedes hablar por chat sin ingresar al juego." );
return PLUGIN_HANDLED_MAIN;
}
public CommandSayTeam( iId )
{
// Player must be logged
if( IsUserPlaying( iId ) )
{
static iLen, iTeam, szBuffer[ 192 ];
// Get say data and its lenght
read_args( szBuffer, charsmax( szBuffer ) );
remove_quotes( szBuffer ); iLen = strlen( szBuffer );
// Character replacement (exploit?)
for( new i, j; i < iLen; i++ )
{
if( szBuffer[ i ] == '#' || szBuffer[ i ] == '%' )
j++;
szBuffer[ i ] = szBuffer[ i + j ]; iLen--;
}
// String lenght is greater than 0
if( iLen > 0 )
{
// Get sender's team
iTeam = get_user_team( iId );
format( szBuffer, charsmax( szBuffer ), "^x01%s(%s)^x03 %s^x01: %s",
GetPlayerBit( g_iAlive, iId ) ? "" : "*Muerto* ", g_szTeamnames[ iTeam ], g_ePlayerAccount[ iId ][ Account_Name ], szBuffer );
// Loop through all playersn
for( new iPlayer = 1; iPlayer <= g_iMaxPlayers; iPlayer++ )
{
// Player must be connected and have same alive state and team than sender
if( !GetPlayerBit( g_iConnected, iPlayer ) || ( ( ( GetPlayerBit( g_iAlive, iId ) && !GetPlayerBit( g_iAlive, iPlayer ) ) || ( !GetPlayerBit( g_iAlive, iId ) && GetPlayerBit( g_iAlive, iPlayer ) ) ) || ( iTeam != get_user_team( iPlayer ) ) ) )
continue;
// Send message
client_print_color( iPlayer, iId, szBuffer );
}
}
}
else
client_print_color( iId, print_team_default, "^x04[PropHunt]^x01 No puedes hablar por chat sin ingresar al juego." );
return PLUGIN_HANDLED_MAIN;
}
public CommandPassword( iId )
{
static szBuffer[ 32 ]; read_argv( 1, szBuffer, charsmax( szBuffer ) );
// Player is registered
if( g_ePlayerAccount[ iId ][ Account_Status ] == Status_Registered )
{
// Password checking
if( equal( szBuffer, g_ePlayerAccount[ iId ][ Account_Password ] ) )
{
// Player logged in
g_ePlayerAccount[ iId ][ Account_Status ] = Status_Playing;
// Auto-join
ForceJoinTeam( iId );
SendHudmessage( iId, 3, HC_Green, "Has ingresado satisfactoriamente a tu cuenta!" );
}
else
{
// Passwords were not equal, tell the player to re-input password
client_cmd( iId, "messagemode INGRESAR_CLAVE" );
SendHudmessage( iId, 3, HC_Red, "La clave ingresada no era identica a la de la cuenta!" );
}
}
else
{
// Player is registering an account
if( g_ePlayerAccount[ iId ][ Account_Status ] == Status_Unregistered )
{
// Min four chars, max twenty, only alphanumeric
if( 4 <= strlen( szBuffer ) <= 20 && IsAlphanumeric( szBuffer ) )
{
// Save current password and ask for confirmation
copy( g_ePlayerAccount[ iId ][ Account_Password ], charsmax( g_ePlayerAccount[ ][ Account_Password ] ), szBuffer );
// Change player's status to password confirming
g_ePlayerAccount[ iId ][ Account_Status ] = Status_Confirm;
// Tell the player to re-input password
client_cmd( iId, "messagemode INGRESAR_CLAVE" );
SendHudmessage( iId, 3, HC_Yellow, "Le pedimos que vuelva a ingresar su clave por seguridad de errores." );
}
else
{
// Password is not valid
client_cmd( iId, "messagemode INGRESAR_CLAVE" );
SendHudmessage( iId, 3, HC_Red, "La clave solo puede ser alfanumerica y de al menos cuatro caracteres!" );
}
}
// Player is confirming his password
else if( g_ePlayerAccount[ iId ][ Account_Status ] == Status_Confirm )
{
// Password checking
if( !equal( szBuffer, g_ePlayerAccount[ iId ][ Account_Password ] ) )
{
// Passwords were not equal, reset password and status
g_ePlayerAccount[ iId ][ Account_Password ][ 0 ] = EOS;
g_ePlayerAccount[ iId ][ Account_Status ] = Status_Unregistered;
// Password were not equal, tell the player to re-do the process
client_cmd( iId, "messagemode INGRESAR_CLAVE" );
SendHudmessage( iId, 3, HC_Red, "La clave ingresada no coincide con la anterior, repita el procedimiento." );
}
else
{
GenerateCode( iId );
client_print_color( iId, print_team_default, "^x04[PropHunt]^x01 Se ha generado un codigo de recuperacion para tu cuenta." );
client_print_color( iId, print_team_default, "^x04[PropHunt]^x01 Codigo:^x04 %s^x01. Anotalo, no lo pierdas.", g_ePlayerAccount[ iId ][ Account_Code ] );
ExecuteQuery( iId, Query_Create_User );
}
}
}
return PLUGIN_HANDLED;
}
public HookTeamChoosing( iId )
{
// Player is logged
if( IsUserPlaying( iId ) )
ph_show_main( iId );
// Player is not logged, is not auto-login and login-menu is a valid menu
else if( g_ePlayerAccount[ iId ][ Account_Status ] != Status_Loading && g_iLoginMenu != -1 )
ShowLoginMenu( iId );
return PLUGIN_HANDLED;
}
public client_putinserver( iId )
{
SetPlayerBit( g_iConnected, iId );
g_ePlayerAccount[ iId ][ Account_Userid ] = 0;
g_ePlayerAccount[ iId ][ Account_Status ] = Status_Loading;
g_ePlayerStats[ iId ][ Player_Exp ] = 0;
g_ePlayerStats[ iId ][ Player_Level ] = 1;
g_ePlayerStats[ iId ][ Player_Frags ] = 0;
g_ePlayerStats[ iId ][ Player_Points ] = 0;
g_ePlayerStats[ iId ][ Player_Hunter ] = 0;
g_ePlayerStats[ iId ][ Player_Hider ] = 0;
g_ePlayerStats[ iId ][ Player_Played ] = 0;
get_user_name( iId, g_ePlayerAccount[ iId ][ Account_Name ], charsmax( g_ePlayerAccount[ ][ Account_Name ] ) );
get_user_ip( iId, g_ePlayerAccount[ iId ][ Account_Ip ], charsmax( g_ePlayerAccount[ ][ Account_Ip ] ), true );
ExecuteQuery( iId, Query_Load_User );
}
public client_disconnect( iId )
{
// If player was playing then save his information
if( IsUserPlaying( iId ) )
{
g_ePlayerStats[ iId ][ Player_Played ] += ( get_user_time( iId ) / 60 );
ExecuteQuery( iId, Query_Save );
}
// Clear connected flag
ClearPlayerBit( g_iConnected, iId );
}
/* =====================================================================
* [ Client menus ]
* ===================================================================== */
public ShowLoginMenu( iId )
{
menu_display( iId, g_iLoginMenu );
return PLUGIN_HANDLED;
}
public LoginHandler( iId, iMenu, iItem )
{
if( iItem != MENU_EXIT && g_ePlayerAccount[ iId ][ Account_Status ] != Status_Loading )
{
if( iItem )
{
// Account is not registered?
if( g_ePlayerAccount[ iId ][ Account_Status ] != Status_Registered )
{
// Show login menu and throw an error
ShowLoginMenu( iId );
SendHudmessage( iId, 3, HC_Red, "La cuenta a la que intentas ingresar no existe." );
}
else
{
// Tell the player to input his password
client_cmd( iId, "messagemode INGRESAR_CLAVE" );
SendHudmessage( iId, 3, HC_Yellow, "Ingresa tu clave para ingresar en la cuenta." );
}
}
else
{
// Account is registered?
if( g_ePlayerAccount[ iId ][ Account_Status ] != Status_Unregistered )
{
// Show login menu and throw an error
ShowLoginMenu( iId );
SendHudmessage( iId, 3, HC_Red, "La cuenta que intentas crear ya se encuentra registrada." );
}
else
{
// Reset password
g_ePlayerAccount[ iId ][ Account_Password ][ 0 ] = EOS;
// Tell the player to input his password
client_cmd( iId, "messagemode INGRESAR_CLAVE" );
SendHudmessage( iId, 3, HC_Yellow, "Ingresa la clave para tu nueva cuenta.^nDebe ser alfanumerica, minimo 4 y maximo 20 caracteres!" );
}
}
}
return PLUGIN_HANDLED;
}
/* =====================================================================
* [ MySQL Section ]
* ===================================================================== */
MySQL_Init( )
{
new iErrnum, szData[ 128 ], szSQLData[ 4 ][ 32 ];
// Get SQL-config file's route
get_localinfo( "amxx_configsdir", szData, charsmax( szData ) );
add( szData, charsmax( szData ), "/mysql/prophunt.cfg" );
// If file does not exists then we cant save or load any stats, plugin is useless
if( !file_exists( szData ) )
set_fail_state( "[MySQL] No se ha podido encontrar el archivo de configuraciones." );
new iFile = fopen( szData, "rt" ), iNum;
// Loop until we reach end of file
while( !feof( iFile ) )
{
fgets( iFile, szData, charsmax( szData ) );
trim( szData );
if( szData[ 0 ] == ';' || ( strlen( szData ) <= 4 ) )
continue;
// Store every found config
strtok( szData, szData, charsmax( szData ), szSQLData[ iNum++ ], charsmax( szSQLData[ ] ), '=', true );
}
// Close the file
fclose( iFile );
// Establish connection with MySQL host
g_hSQLHost = mysql_makehost( szSQLData[ 0 ], szSQLData[ 1 ], szSQLData[ 2 ], szSQLData[ 3 ] );
// Make a permanent connection with the database
mysql_connect( g_hSQLHost, iErrnum, szData, charsmax( szData ) );
if( iErrnum )
{
log_to_file( "stats.log", "[MySQL] Error: %s.", szData );
set_fail_state( "Error al conectar con la base de datos." );
}
// Load top and get player count
ExecuteQuery( 0, Query_Top );
ExecuteQuery( 0, Query_Players );
}
ExecuteQuery( const iId, const iQuery )
{
static szQuery[ 512 ], szData[ 4 ];
// Store query data ( user id and type )
szData[ 0 ] = iId;
szData[ 1 ] = iQuery;
// Messy messy messy
switch( iQuery )
{
case Query_Load_User:
formatex( szQuery, charsmax( szQuery ), "SELECT * FROM ph_users WHERE user_name=^"%s^"", g_ePlayerAccount[ iId ][ Account_Name ] );
case Query_Create_User:
formatex( szQuery, charsmax( szQuery ), "INSERT INTO ph_users ( user_name, user_password, user_code ) VALUES ( ^"%s^", ^"%s^", ^"%s^" )",
g_ePlayerAccount[ iId ][ Account_Name ],
g_ePlayerAccount[ iId ][ Account_Password ],
g_ePlayerAccount[ iId ][ Account_Code ] );
case Query_Load_Stats:
formatex( szQuery, charsmax( szQuery ), "SELECT * FROM ph_stats WHERE user_owner='%d'", g_ePlayerAccount[ iId ][ Account_Userid ] );
case Query_Create_Stats:
formatex( szQuery, charsmax( szQuery ), "INSERT INTO ph_stats ( user_owner ) VALUES ( '%d' )", g_ePlayerAccount[ iId ][ Account_Userid ] );
case Query_Top:
formatex( szQuery, charsmax( szQuery ), "SELECT * FROM ph_stats ORDER BY user_exp DESC LIMIT 10" );
case Query_Rank:
formatex( szQuery, charsmax( szQuery ), "SELECT (COUNT(*) + 1) AS pos FROM ph_stats WHERE user_exp > '%d'", g_ePlayerStats[ iId ][ Player_Exp ] );
case Query_Players:
formatex( szQuery, charsmax( szQuery ), "SELECT COUNT(*) FROM ph_stats" );
case Query_Save:
{
formatex( szQuery, charsmax( szQuery ), "UPDATE ph_stats SET user_level='%d',user_exp='%d',user_played='%d',user_frags='%d',user_points='%d',user_rank='%d',user_hunter='%d',user_hider='%d' WHERE user_owner='%d'",
g_ePlayerStats[ iId ][ Player_Level ],
g_ePlayerStats[ iId ][ Player_Exp ],
g_ePlayerStats[ iId ][ Player_Played ],
g_ePlayerStats[ iId ][ Player_Frags ],
g_ePlayerStats[ iId ][ Player_Points ],
g_ePlayerStats[ iId ][ Player_Rank ],
g_ePlayerStats[ iId ][ Player_Hunter ],
g_ePlayerStats[ iId ][ Player_Hider ],
g_ePlayerAccount[ iId ][ Account_Userid ] );
formatex( szQuery[ strlen( szQuery ) ], charsmax( szQuery ) - strlen( szQuery ), ";UPDATE ph_users SET user_ip=^"%s^" WHERE user_id='%d'",
g_ePlayerAccount[ iId ][ Account_Ip ],
g_ePlayerAccount[ iId ][ Account_Userid ] );
}
}
// Execute desired query
mysql_query( g_hSQLHost, "ExecuteQueryHandler", szQuery, szData, sizeof( szData ) - 1 );
}
public ExecuteQueryHandler( iFailState, szError[ ], iErrcode, szData[ ], iDatasize )
{
static iId, iType, szBuffer[ 32 ];
// Get stored query data
iId = szData[ 0 ];
iType = szData[ 1 ];
// Messy messy messy
if( iFailState != TQUERY_SUCCESS )
log_to_file( "mysql.log", "[MySQL] Error: %s.", szError );
else
{
switch( iType )
{
case Query_Create_User:
{
g_ePlayerAccount[ iId ][ Account_Status ] = Status_Playing;
g_ePlayerAccount[ iId ][ Account_Userid ] = mysql_get_insert_id( );
ForceJoinTeam( iId );
ExecuteQuery( iId, Query_Create_Stats );
SendHudmessage( iId, 3, HC_Green, "Tu cuenta ha sido creada satisfactoriamente, diviertete!" );
}
case Query_Load_User:
{
if( mysql_num_results( ) > 0 )
{
g_ePlayerAccount[ iId ][ Account_Userid ] = mysql_read_result( 0 );
mysql_read_result( 2, g_ePlayerAccount[ iId ][ Account_Password ], charsmax( g_ePlayerAccount[ ][ Account_Password ] ) );
mysql_read_result( 3, g_ePlayerAccount[ iId ][ Account_Code ], charsmax( g_ePlayerAccount[ ][ Account_Code ] ) );
mysql_read_result( 4, szBuffer, charsmax( szBuffer ) );
if( !CheckConnectedAccount( iId ) )
{
ExecuteQuery( iId, Query_Load_Stats );
if( equal( szBuffer, g_ePlayerAccount[ iId ][ Account_Ip ] ) )
{
g_ePlayerAccount[ iId ][ Account_Status ] = Status_Playing;
ForceJoinTeam( iId );
SendHudmessage( iId, 3, HC_Green, "Has ingresado en tu cuenta por IP, diviertete!" );
}
else
g_ePlayerAccount[ iId ][ Account_Status ] = Status_Registered;
}
else
server_cmd( "kick #%d ^"La cuenta esta siendo usada^"", get_user_userid( iId ) );
}
else
g_ePlayerAccount[ iId ][ Account_Status ] = Status_Unregistered;
}
case Query_Load_Stats:
{
if( mysql_num_results( ) != 0 )
{
g_ePlayerStats[ iId ][ Player_Exp ] = mysql_read_result( 1 );
g_ePlayerStats[ iId ][ Player_Rank ] = mysql_read_result( 2 );
g_ePlayerStats[ iId ][ Player_Level ] = mysql_read_result( 3 );
g_ePlayerStats[ iId ][ Player_Frags ] = mysql_read_result( 4 );
g_ePlayerStats[ iId ][ Player_Points ] = mysql_read_result( 5 );
g_ePlayerStats[ iId ][ Player_Hunter ] = mysql_read_result( 6 );
g_ePlayerStats[ iId ][ Player_Hider ] = mysql_read_result( 7 );
g_ePlayerStats[ iId ][ Player_Played ] = mysql_read_result( 8 );
}
}
case Query_Create_Stats:
{
g_iTotalPlayers++;
client_cmd( 0, "spk buttons/bell1" );
client_print_color( 0, print_team_default, "^x04[PropHunt]^x01 Bienvenido^x04 %s^x01 a nuestro^x04 PropHunt^x01.", g_ePlayerAccount[ iId ][ Account_Name ] );
}
case Query_Names:
{
new i, iLen;
iLen = formatex( g_szMotdInfo, charsmax( g_szMotdInfo ), "<html><head><style>table,td,th { border:1px solid black; border-collapse:collapse; }</style></head><body bgcolor='#ebf3f8'><table style='width:748px'>" );
iLen += formatex( g_szMotdInfo[ iLen ], charsmax( g_szMotdInfo ) - iLen, "<th>Nr.</th><th>Nombre</th><th>Nivel</th><th>Experiencia</th><th>Asesinatos</th><th>Tiempo jugado (m)</th>");
while( mysql_more_results( ) )
{
mysql_read_result( 0, szBuffer, charsmax( szBuffer ) );
iLen += formatex( g_szMotdInfo[ iLen ], charsmax( g_szMotdInfo ) - iLen, "<tr>");
iLen += formatex( g_szMotdInfo[ iLen ], charsmax( g_szMotdInfo ) - iLen, "<td>%d.</td>", i + 1 );
iLen += formatex( g_szMotdInfo[ iLen ], charsmax( g_szMotdInfo ) - iLen, "<td>%s</td>", szBuffer );
iLen += formatex( g_szMotdInfo[ iLen ], charsmax( g_szMotdInfo ) - iLen, "<td>%d</td>", g_eTop[ i ][ Player_Level ] );
iLen += formatex( g_szMotdInfo[ iLen ], charsmax( g_szMotdInfo ) - iLen, "<td>%d</td>", g_eTop[ i ][ Player_Exp ] );
iLen += formatex( g_szMotdInfo[ iLen ], charsmax( g_szMotdInfo ) - iLen, "<td>%d</td>", g_eTop[ i ][ Player_Frags ] );
iLen += formatex( g_szMotdInfo[ iLen ], charsmax( g_szMotdInfo ) - iLen, "<td>%d</td>", g_eTop[ i ][ Player_Played ] );
iLen += formatex( g_szMotdInfo[ iLen ], charsmax( g_szMotdInfo ) - iLen, "</tr>");
i++; mysql_next_row( );
}
iLen += formatex( g_szMotdInfo[ iLen ], charsmax( g_szMotdInfo ) - iLen, "</table></body></html>" );
}
case Query_Top:
{
new i, iLen, szQuery[ 256 ];
while( mysql_more_results( ) )
{
g_eTop[ i ][ Player_Level ] = mysql_read_result( 3 );
g_eTop[ i ][ Player_Exp ] = mysql_read_result( 1 );
g_eTop[ i ][ Player_Frags ] = mysql_read_result( 4 );
g_eTop[ i ][ Player_Played ] = mysql_read_result( 8 );
iLen += formatex( szBuffer[ iLen ], charsmax( szBuffer ) - iLen, "%s%d", ( iLen > 0 ) ? "," : "", mysql_read_result( 0 ) );
i++; mysql_next_row( );
}
formatex( szQuery, charsmax( szQuery ), "SELECT user_name FROM ph_users WHERE user_id IN (%s) ORDER BY FIELD(user_id,%s)", szBuffer, szBuffer );
szBuffer[ 0 ] = 0;
szBuffer[ 1 ] = Query_Names;
mysql_query( g_hSQLHost, "ExecuteQueryHandler", szQuery, szBuffer, sizeof( szBuffer ) - 1 );
}
case Query_Rank: client_print_color( iId, print_team_default, "^x04[PropHunt]^x01 Te encontras en el puesto^x03 %d^x01 de^x04 %d^x01 jugadores.", mysql_read_result( 0 ), g_iTotalPlayers );
case Query_Players:
{
g_iTotalPlayers = mysql_read_result( 0 );
CreateLoginMenu( );
}
}
}
}
/* =====================================================================
* [ Private functions ]
* ===================================================================== */
UpdateLevel( const iId )
{
// Player should level up?
if( ShouldLevelUp( iId ) )
{
// Loop until we add enough levels / ranks
while( ShouldLevelUp( iId ) ) g_ePlayerStats[ iId ][ Player_Level ]++;
while( ShouldRankUp( iId ) ) g_ePlayerStats[ iId ][ Player_Rank ]++;
// Send IMPLOSION effect
static iOrigin[ 3 ]; get_user_origin( iId, iOrigin );
message_begin( MSG_BROADCAST, SVC_TEMPENTITY );
write_byte( TE_IMPLOSION );
write_coord( iOrigin[ 0 ] );
write_coord( iOrigin[ 1 ] );
write_coord( iOrigin[ 2 ] );
write_byte( 250 );
write_byte( 25 );
write_byte( 10 );
message_end( );
// Emit a level up sound
emit_sound( iId, CHAN_BODY, g_szLevelUpSound, 0.3, ATTN_NORM, 0, PITCH_NORM );
}
}
ShowPlayerStats( const iId )
{
static iLen, szData[ 1040 ];
iLen = formatex( szData, charsmax( szData ), "<meta http-equiv=^"Content-Type^" content=^"text/html;charset=UTF-8^">\
<body bgcolor=black style=line-height:1;color:white><center><font color=FFFFFF size=6 face=Tahoma><p>EstadÃsticas<p>" );
iLen += formatex( szData[ iLen ], charsmax( szData ) -iLen, "<font color=FFFFFF size=4>Tu nivel es \
<font color=5F04B4>%d<font color=FFFFFF> y tu rango actual es <font color=F7FE2E> %s<font color=FFFFFF><p>",
g_ePlayerStats[ iId ][ Player_Level ],
g_eRanks[ g_ePlayerStats[ iId ][ Player_Rank ] ][ Rank_Name ] );
iLen += formatex( szData[ iLen ], charsmax( szData ) -iLen, "<font color=FFFFFF size=4>Contas con un total de <font color=2E9AFE> %d<font color=FFFFFF> puntos y <font color=FF00>%d\
<font color=FFFFFF> asesinatos<p><font color=FFFFFF size=4>Ganaste <font color=FF90>%d<font color=FFFFFF> partidas como hider y<font color=FF4C4C> %d<font color=FFFFFF> como hunter<p>",
g_ePlayerStats[ iId ][ Player_Points ],
g_ePlayerStats[ iId ][ Player_Frags ],
g_ePlayerStats[ iId ][ Player_Hider ],
g_ePlayerStats[ iId ][ Player_Hunter ] );
iLen += formatex( szData[ iLen ], charsmax( szData ) -iLen, "<font color=FFFFFF size=4>Tenes <font color=9F81F7>%d<font color=FFFFFF> de experiencia y te falta <font color=82FA58> %d<font color=FFFFFF> para subir de nivel",
g_ePlayerStats[ iId ][ Player_Exp ],
GetNeededExp( g_ePlayerStats[ iId ][ Player_Level ] + 1 ) - g_ePlayerStats[ iId ][ Player_Exp ] );
show_motd( iId, szData, "Estadisticas" );
}
CreateLoginMenu( )
{
g_iLoginMenu = menu_create( "\y==============================\w^n \wSeguridad - PropHunt^n\y==============================", "LoginHandler" );
menu_additem( g_iLoginMenu, "\yCrear \wuna nueva cuenta", "1" );
menu_additem( g_iLoginMenu, "\yEntrar \wen una cuenta existente^n", "2" );
new szData[ 64 ]; formatex( szData, charsmax( szData ), "Cuentas creadas hasta hoy: \y%d", g_iTotalPlayers );
menu_addtext( g_iLoginMenu, szData );
menu_addtext( g_iLoginMenu, "\wSi perdiste tu clave contacta un \yadministrador" );
// No option for cancel, player must login or register
menu_setprop( g_iLoginMenu, MPROP_EXIT, MEXIT_NEVER );
}
SendHudmessage( const iId, const iHoldtime, const iColor, const szMessage[ ] )
{
set_hudmessage( g_iHudColors[ iColor ][ 0 ], g_iHudColors[ iColor ][ 1 ], g_iHudColors[ iColor ][ 2 ], 0.05, 0.15, 1, 2.0, float( iHoldtime ) );
ShowSyncHudMsg( iId, g_iSyncObj, szMessage );
client_cmd( iId, "spk buttons/button%d", g_iHudSounds[ iColor ] );
}
ForceJoinTeam( const iId )
{
// We will access private data so we must make sure player is connected
if( GetPlayerBit( g_iConnected, iId ) )
{
static iRestore; iRestore = get_pdata_int( iId, m_iVGUI );
// We avoid bugs with menus
if( iRestore & (1<<0) )
set_pdata_int( iId, m_iVGUI, iRestore & ~(1<<0) );
set_msg_block( g_iShowMenu, BLOCK_SET );
set_msg_block( g_iVGUIMenu, BLOCK_SET );
engclient_cmd( iId, "jointeam", "1" );
engclient_cmd( iId, "joinclass", "5" );
set_msg_block( g_iShowMenu, BLOCK_NOT );
set_msg_block( g_iVGUIMenu, BLOCK_NOT );
if( iRestore & (1<<0) )
set_pdata_int( iId, m_iVGUI, iRestore );
// Cancel any player menu
menu_cancel( iId );
// Set his in-game name
client_cmd( iId, ";name ^"%s^"", g_ePlayerAccount[ iId ][ Account_Name ] );
set_user_info( iId, g_szCache_Name, g_ePlayerAccount[ iId ][ Account_Name ] );
}
}
CheckConnectedAccount( const iId )
{
// Loop through all players until we find an equality of userids
for( new iPlayer = 1; iPlayer <= g_iMaxPlayers; iPlayer++ )
{
if( ( iId != iPlayer ) && GetPlayerBit( g_iConnected, iPlayer ) )
{
if( g_ePlayerAccount[ iId ][ Account_Userid ] == g_ePlayerAccount[ iPlayer ][ Account_Userid ] )
return true;
}
}
// We found nothing
return false;
}
GenerateCode( const iId )
{
// Generate a code made of letters and numbers
for( new i; i < CODE_CHARS; i++ )
g_ePlayerAccount[ iId ][ Account_Code ][ i ] = ( random( 2 ) > 0 ) ? random_num( 48, 57 ) : random_num( 65, 90 );
}
IsAlphanumeric( const szData[ ] )
{
new iLen = strlen( szData );
// Loop through all string's characters until we find a non-alphanumeric character
for( new i; i < iLen; i++ )
if( !isLetter( szData[ i ] ) && !isDigit( szData[ i ] ) )
return false;
return true;
}
/* =====================================================================
* [ Natives ]
* ===================================================================== */
public _ph_get_level( iPlugin, iParams )
{
if( iParams != 1 )
return 0;
return g_ePlayerStats[ get_param( 1 ) ][ Player_Level ];
}
public _ph_show_stats( iPlugin, iParams )
{
if( iParams != 1 )
return 0;
ShowPlayerStats( get_param( 1 ) );
return 1;
}
public _ph_add_xp( iPlugin, iParams )
{
if( iParams != 2 )
return 0;
g_ePlayerStats[ get_param( 1 ) ][ Player_Exp ] += get_param( 2 );
return 1;
}
public _ph_show_rank( iPlugin, iParams )
{
if( iParams != 1 )
return 0;
ExecuteQuery( get_param( 1 ), Query_Rank );
return 1;
}
public _ph_show_top( iPlugin, iParams )
{
if( iParams != 1 )
return 0;
show_motd( get_param( 1 ), g_szMotdInfo, "Top" );
return 1;
}
/*CREATE TABLE ph_users (
user_id INT PRIMARY KEY AUTO_INCREMENT,
user_name VARCHAR( 32 ) UNIQUE NOT NULL default '',
user_password VARCHAR( 32 ) NOT NULL default '',
user_code VARCHAR( 8 ) NOT NULL default '',
user_ip VARCHAR( 32 ) NOT NULL default '',
user_date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP );
CREATE TABLE ph_stats (
user_owner INT UNIQUE NOT NULL default 0,
user_exp INT NOT NULL default 0,
user_rank INT NOT NULL default 0,
user_level INT NOT NULL default 1,
user_frags INT NOT NULL default 0,
user_points INT NOT NULL default 0,
user_hunter INT NOT NULL default 0,
user_hider INT NOT NULL default 0,
user_played INT NOT NULL default 0 )*/