/***************************************************************************** * * Module: plugin_spawndamage * * Description: Prevents spawndamaging by detecting teamdamaging in the first * few seconds of play and punishing the perpetrator. * * Revision History: 11-01-01, initial creation by dodger * 12-11-01, revised by dodger, allows customized detection * time * 12-17-01, revised by dodger, no longer uses timers * 03-04-02, revised by dodger, special cases grenades * * DevNotes: One nice feature would be to snapshot all user origins on * Round_Start, and ignore spawn damage events if the player * has moved more than a certain distance from that point. * *****************************************************************************/ #include <core> #include <console> #include <string> #include <admin> #include <adminlib> #define ACCESS_CONSOLE 131072 #define ACCESS_RESTRICT 32 new STRING_VERSION[MAX_DATA_LENGTH] = "1.30"; new i_SDTime = 0; new epoch_SDStart = 0; /***************************************************************************** * * Function: admin_setsdtime * * Description: set spawndamage time (not including buy time) * * Revision History: 12-11-01, initial creation by dodger * *****************************************************************************/ public admin_setsdtime( HLCommand, HLData, HLUserName, UserIndex ) { new data[MAX_DATA_LENGTH]; new user[MAX_NAME_LENGTH]; new text[MAX_TEXT_LENGTH]; convert_string( HLData, data, MAX_DATA_LENGTH ); convert_string( HLUserName, user, MAX_NAME_LENGTH ); new i_time = strtonum( data ); new i_buytime = getvar( "mp_freezetime" ); if( i_time <= 0 ) { i_SDTime = 0; snprintf( text, MAX_TEXT_LENGTH, "[SPAWN] spawndamage time set to zero seconds.", i_time, i_buytime ); } else { i_SDTime = i_time + i_buytime; snprintf( text, MAX_TEXT_LENGTH, "[SPAWN] spawndamage time set to %d seconds plus %d seconds buy time.", i_time, i_buytime ); } messageex( user, text, print_console ); return PLUGIN_HANDLED; } /***************************************************************************** * * Function: td_on * * Description: Timer event function that turns spawndamage checking on. * * Revision History: 11-01-01, initial creation by dodger * 12-11-01, revised by dodger, allows customized detection * time * 12-17-01, revised by dodger, no longer uses timers * *****************************************************************************/ public td_on( HLCommand, HLData, HLUserName, s_action ) { new data[MAX_DATA_LENGTH]; convert_string( HLData, data, MAX_DATA_LENGTH ); /* if Worldspawn signals the start of a round, enable detection and set the timer to turn it back off again */ if( strcasecmp( data, "Round_Start" ) == 0 ) { epoch_SDStart = systemtime(); } return PLUGIN_CONTINUE; } /***************************************************************************** * * Function: handle_td * * Description: Take a single injure event and determine if it is a valid * spawn damage event. * * Revision History: 11-01-01, initial creation by dodger * 12-17-01, revised by dodger, no longer uses timers * 01-22-02, revised by dodger, reversed the systemtime() * call, which goes backwards for some reason. * added coverage of CT <--> VIP damage. * 01-29-02, revised by dodger, no no, systemtime() counts * properly, dodger == teh stupid * *****************************************************************************/ public handle_td( HLCommand, HLData, HLUserName, UserIndex ) { if( epoch_SDStart + i_SDTime < systemtime() ) { return PLUGIN_CONTINUE; } new data[MAX_DATA_LENGTH]; convert_string( HLData, data, MAX_DATA_LENGTH ); new attacker[MAX_DATA_LENGTH]; new victim[MAX_DATA_LENGTH]; new weapon[MAX_DATA_LENGTH]; new strhealth[MAX_DATA_LENGTH]; new strcolon[MAX_DATA_LENGTH]; new damage[MAX_DATA_LENGTH]; strsplit( data, " ", attacker, MAX_DATA_LENGTH, victim, MAX_DATA_LENGTH, weapon, MAX_DATA_LENGTH, strhealth, MAX_DATA_LENGTH, strcolon, MAX_DATA_LENGTH, damage, MAX_DATA_LENGTH ); new attacker_id = strtonum( attacker ); new attacker_userid; new attacker_teamid; new attacker_wonid; if( !playerinfo( attacker_id, attacker, MAX_NAME_LENGTH, attacker_userid, attacker_wonid, attacker_teamid ) ) { return PLUGIN_CONTINUE; } new victim_id = strtonum( victim ); new victim_userid; new victim_teamid; new victim_wonid; if( !playerinfo( victim_id, victim, MAX_NAME_LENGTH, victim_userid, victim_wonid, victim_teamid ) ) { return PLUGIN_CONTINUE; } if( attacker_userid == victim_userid ) { return PLUGIN_CONTINUE; } new response_message[MAX_TEXT_LENGTH]; /* handle standard team damaging */ if( attacker_teamid == victim_teamid ) { /* we're nice, and don't count grenades that don't do too much damage, which happens frequently */ if( strcmp( weapon, "grenade" ) == 0 ) { if( strtonum(damage) < 10 ) { snprintf( response_message, MAX_TEXT_LENGTH, "[SPAWN] %s, careful with the grenades.", attacker ); typesay( response_message, 10, 255, 255, 255 ); return PLUGIN_CONTINUE; } } snprintf( response_message, MAX_TEXT_LENGTH, "[SPAWN] %s slain for injuring a teammate.", attacker ); typesay( response_message, 10, 255, 255, 255 ); plugin_exec( "admin_slay", attacker ); return PLUGIN_CONTINUE; } /* handle the VIP shooting his teammates */ if( ( attacker_teamid >=2 ) && ( victim_teamid >= 2 ) ) { if( attacker_teamid == 3 ) { snprintf( response_message, MAX_TEXT_LENGTH, "[SPAWN] %s, the VIP, kicked for injuring a teammate.", attacker ); } else { snprintf( response_message, MAX_TEXT_LENGTH, "[SPAWN] %s kicked for injuring the VIP.", attacker ); } typesay( response_message, 10, 255, 255, 255 ); message( attacker, response_message ); plugin_exec( "admin_kick", attacker ); return PLUGIN_CONTINUE; } return PLUGIN_CONTINUE; } /***************************************************************************** * * Function: plugin_init * * Description: Register functions with halflife engine and with LogD event * handler. * * Revision History: 11-01-01, initial creation by dodger * 12-11-01, revised by dodger, allows customized detection * time * 12-13-01, revised by dodger, added default behavior * *****************************************************************************/ public plugin_init() { plugin_registerinfo( "Spawndamage prevention", "Auto detects and punishes spawn teamdamagers.", STRING_VERSION ); plugin_registercmd( "td_on", "td_on", ACCESS_CONSOLE, "" ); plugin_registercmd( "handle_td", "handle_td", ACCESS_CONSOLE, "" ); plugin_registercmd( "admin_setsdtime", "admin_setsdtime", ACCESS_RESTRICT, "admin_setsdtime <sec>: enable spawndamage detection for <sec> seconds" ); /* register td_on to receive all type 62 (World Action) messages */ exec( "logd_reg 62 admin_command td_on" ); /* register handle_td to receive all type 58 (Injure) messages */ exec( "logd_reg 58 admin_command handle_td" ); /* default spawndamage time is set to five seconds into the round */ new i_buytime = getvar( "mp_freezetime" ); if( i_buytime < 0 ) { i_buytime = 0; } i_SDTime = 5 + i_buytime; return PLUGIN_CONTINUE; }