/* Plugin by Melbs, of eatingshoes.com */
#include <amxmodx>
#include <amxmisc>
#include <cstrike>
#include <fun> // for setting HP on "hurt" punishment... rather not use...hmm
#pragma semicolon 1
// ***************************************************
// ******************** DEFINES **********************
#define PLUGIN "AFManager"
#define VERSION "1.0"
#define AUTHOR "melbs"
#define MAX_LENGTH 32
#define CHECK_TASK 31337
// ****** types of punishment ******
#define POKE 1
#define PROD 2
#define HURT 3
#define SLAY 4
#define MOVE 5
#define KICK 6
// ****** cvar defines ******
#define AFKCMD "afm_afkcmd", "1" // allow "say /afk" command
#define AFKTIME "afm_afktime", "25.0" // amount of time to be marked as afk
#define ANNOUNCE "afm_announce", "1" // announce punishments to server
#define CHECKTIME "afm_checktime", "7.0" // time between checks
#define DROPBOMB "afm_dropbomb", "1"
#define ENABLE "afm_enable", "1"
#define HPTICKAMOUNT "afm_hptickamount", "5" // health subtracted when punishment is hp drop
#define HPTICKTIME "afm_hpticktime", "5" // time between health being taken
#define LOG "afm_log", "0" // log actions
#define MINPLAYERS "afm_minplayers", "2" // min player # for checking afks
#define PREFIX "afm_prefix", "[afk]" // the name of afks. If useprefix == 1
#define PUNISHMENT "afm_punishment", "2" // type of punishment
#define USEPREFIX "afm_useprefix", "0" // add prefix to afkers?
// ***************************************************
// ******************** GLOBALS **********************
new const AMX_SAYLANG[]="[AFM] %L";
new g_playersnum;
new g_players[MAX_LENGTH];
new Float:g_times[MAX_LENGTH+1] = { 0.0, ... }; // sum time players are afk
new g_origins[MAX_LENGTH+1][3]; // NOTE: initializes to garbage; this is not a problem
// g_origins[0] used as a tmp for comparison in main loop
// ****** variable pointers ******
new g_pcv_afkcmd;
new g_pcv_afktime;
new g_pcv_announce;
new g_pcv_checktime;
new g_pcv_dropbomb;
new g_pcv_enable;
new g_pcv_hptickamount;
new g_pcv_hpticktime;
new g_pcv_log;
new g_pcv_minplayers;
new g_pcv_prefix;
new g_pcv_punishment;
new g_pcv_useprefix;
new g_pcv_freezetime;
// ***************************************************
// ******************* FUNCTIONS *********************
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR);
register_cvar("afm_version",VERSION, FCVAR_SERVER|FCVAR_SPONLY);
// register variables
g_pcv_afkcmd = register_cvar(AFKCMD);
g_pcv_afktime = register_cvar(AFKTIME);
g_pcv_announce = register_cvar(ANNOUNCE);
g_pcv_checktime = register_cvar(CHECKTIME);
g_pcv_dropbomb = register_cvar(DROPBOMB);
g_pcv_enable = register_cvar(ENABLE);
g_pcv_hptickamount = register_cvar(HPTICKAMOUNT);
g_pcv_hpticktime = register_cvar(HPTICKTIME);
g_pcv_log = register_cvar(LOG);
g_pcv_minplayers = register_cvar(MINPLAYERS);
g_pcv_prefix = register_cvar(PREFIX);
g_pcv_punishment = register_cvar(PUNISHMENT);
g_pcv_useprefix = register_cvar(USEPREFIX);
register_dictionary("afm_lang.txt");
// register for new round event, so we know when freezetime is happening
register_event("HLTV", "event_new_round", "a", "1=0", "2=0");
register_clcmd("say /afk", "move_afk_cmd",-1, "- Move to spectate to afk for a bit");
g_pcv_freezetime = get_cvar_pointer("mp_freezetime");
}
public event_new_round()
{
remove_task(CHECK_TASK);
// if the plugin is enabled and has minimum required players
if( is_enabled() && get_playersnum() >= get_minplayers() ) {
new Float:freezetime = get_freezetime();
if ( freezetime == 0.0 )
start_check_afk_think(0);
else
set_task(freezetime, "start_check_afk_think", CHECK_TASK);
}
return PLUGIN_CONTINUE;
}
public move_afk_cmd(p_player)
{
if( afkcmd_enabled() )
move_to_spec(p_player);
else
client_print(p_player, print_console, AMX_SAYLANG, p_player, "NOACCESS");
}
public move_to_spec(p_player)
{
if( is_user_alive(p_player) )
{
// must kill to actually switch team
user_kill(p_player, 1); // slay but dont change k/d
cs_set_user_deaths(p_player, cs_get_user_deaths(p_player) - 1);
}
cs_set_user_team(p_player, CS_TEAM_SPECTATOR);
}
public start_check_afk_think(p_id)
set_task(get_checkinterval(), "check_afk_think", CHECK_TASK,_,0,"b");
public check_afk_think(p_ent)
{
get_players(g_players, g_playersnum);
for(new i=0; i < g_playersnum; i++)
{
new player = g_players;
// make sure the player is still alive to check origin
if( is_user_alive(player) )
{
// get current position of player
get_user_origin(player, g_origins[0]);
// if origins are the same, assume the player has not moved. ignore gaps in interval
if( equal(g_origins[player], g_origins[0], 3) ) {
g_times[player] += get_checkinterval();
} else {
g_times[player] = 0.0;
copy(g_origins[player], 3, g_origins[0]); // copy the new origin to the old
}
new Float:afktime = get_afktime();
if(g_times[player] >= afktime ) {
handle_afk(player, afktime); // the player is now considered AFK
}
}
}
return PLUGIN_CONTINUE;
}
handle_afk(p_player, Float:p_afktime)
{
new afktime = floatround(p_afktime);
new playername[MAX_LENGTH];
get_user_name(p_player, playername, MAX_LENGTH - 1);
switch ( get_punishment() )
{
case POKE:
{
client_print(0, print_chat, AMX_SAYLANG, LANG_PLAYER, "MSG_POKE", playername, afktime);
do_log(p_player, playername, afktime, "LOG_POKE");
}
case PROD:
{
if(announcing_enabled())
client_print(0, print_chat, AMX_SAYLANG, LANG_PLAYER, "MSG_PROD", playername, afktime);
user_slap(p_player, 5);
do_log(p_player, playername, afktime, "LOG_PROD");
}
case HURT:
{
// if already hurting player, do not handle
if(!task_exists(p_player))
{
if(announcing_enabled())
client_print(0, print_chat, AMX_SAYLANG, LANG_PLAYER, "MSG_HURT", playername, afktime);
set_task( get_hpticktime(), "hurt_player", p_player, g_origins[p_player], 3, "b");
do_log(p_player, playername, afktime, "LOG_HURT");
}
}
case SLAY:
{
if(announcing_enabled())
client_print(0, print_chat, AMX_SAYLANG, LANG_PLAYER, "MSG_SLAY", playername, afktime);
user_kill(p_player, 1); // slay but dont change k/d
cs_set_user_deaths(p_player, cs_get_user_deaths(p_player) - 1);
do_log(p_player, playername, afktime, "LOG_SLAY");
}
case MOVE:
{
if(announcing_enabled())
client_print(0, print_chat, AMX_SAYLANG, LANG_PLAYER, "MSG_SPEC", playername, afktime);
move_to_spec(p_player);
do_log(p_player, playername, afktime, AMX_SAYLANG);
}
case KICK:
{
if(announcing_enabled())
client_print(0, print_chat, AMX_SAYLANG, LANG_PLAYER, "MSG_KICK", playername, afktime);
server_cmd("kick #%d ^"%L^"", get_user_userid(p_player), LANG_PLAYER, "DAS_BOOT", afktime);
do_log(p_player, playername, afktime, "LOG_KICK");
}
}
if( is_user_alive(p_player))
{
if(dropbomb_enabled() && user_has_weapon(p_player, CSW_C4)) // cs_get_user_team(pPlayer) == CS_TEAM_T &&
{
client_cmd(p_player,"drop weapon_c4 ");
if(announcing_enabled())
client_print(0, print_chat, AMX_SAYLANG, LANG_PLAYER, "MSG_BOMB", playername, afktime);
do_log(p_player, playername, afktime, "LOG_BOMB");
}
if( prefix_enabled() )
{
new prefix[MAX_LENGTH];
get_pcvar_string(g_pcv_prefix, prefix, MAX_LENGTH - 1);
// if the name is not already prefixed
if( !equal(playername, prefix, strlen(prefix)) ) {
client_cmd(p_player, "name ^"%s%s^"", prefix, playername);
if( logging_enabled() ) {
log_amx(AMX_SAYLANG, LANG_SERVER, "LOG_NAME");
}
}
}
}
g_times[p_player] = 0.0; // reset time to save a few cycles next time
}
public hurt_player(const p_origin[], p_player)
{
new tmporigins[3];
get_user_origin(p_player, tmporigins); // do this instead of checking g_origins because we
// dont know how long the interval is set to.
if(!equal(p_origin, tmporigins, 3))
remove_task(p_player);
else
set_user_health(p_player, get_user_health(p_player) - get_hptickamount());
}
// all logs have the same information displayed, so it's easier to do it like this :)
do_log(p_player, const p_playername[], p_afktime, const p_langkey[])
{
if( logging_enabled() )
{
new ip[MAX_LENGTH];
new authid[MAX_LENGTH];
get_user_ip(p_player, ip, MAX_LENGTH - 1);
get_user_authid(p_player, authid, MAX_LENGTH - 1);
log_amx(AMX_SAYLANG, LANG_SERVER, p_langkey, p_playername, authid, ip, p_afktime);
}
}
stock prefix_enabled()
return get_pcvar_num(g_pcv_useprefix);
stock dropbomb_enabled()
return get_pcvar_num(g_pcv_dropbomb);
stock afkcmd_enabled()
return get_pcvar_num(g_pcv_afkcmd);
stock Float:get_freezetime()
return get_pcvar_float(g_pcv_freezetime);
stock is_enabled()
return get_pcvar_num(g_pcv_enable);
stock Float:get_checkinterval()
return get_pcvar_float(g_pcv_checktime);
stock Float:get_afktime()
return get_pcvar_float(g_pcv_afktime);
stock get_minplayers()
return get_pcvar_num(g_pcv_minplayers);
stock get_punishment()
return get_pcvar_num(g_pcv_punishment);
public get_hptickamount()
return get_pcvar_num(g_pcv_hptickamount);
stock Float:get_hpticktime()
return get_pcvar_float(g_pcv_hpticktime);
stock announcing_enabled()
return get_pcvar_num(g_pcv_announce);
stock logging_enabled()
return get_pcvar_num(g_pcv_log);
/* AMXX-Studio Notes - DO NOT MODIFY BELOW HERE
*{\\ rtf1\\ ansi\\ ansicpg1252\\ deff0\\ deflang1033{\\ fonttbl{\\ f0\\ fnil Tahoma;}}\n\\ viewkind4\\ uc1\\ pard\\ f0\\ fs16 \n\\ par }
*/