Пользователь Lisoh разместил новый ресурс: AntiAfk - Кикает или переводит в наблюдатели афк игроков Узнать больше об этом ресурсе... Lite version(легкая версия): AntiAfk
Спойлер Разрешите до**аться. Всюду Код: GetConVarInt(cvTime) (Это медленно) Лучше создать в глобале переменные содержащие информацию из кваров, сделать хук изменения кваров и там уже изменять переменные. Код: hTimer[iClient] = CreateTimer(1.0, CheckAfk, GetClientUserId(iClient), TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE); А проверять раз в секунду - не часто ли? Код: FormatEx(tBuffer, sizeof(tBuffer), "%t", "Kick message"); Тут либо добавить перед этим Код: SetGlobalTransTarget(iClient); , либо использовать %T вместо %t
Спойлер Никогда так не делал. Если бы это как то повлияло на оптимизацию, я может быть еще подумал об этом заранее. Ради двух проверок? Код внимательно прочитайте. Хм... Специально для вас: PHP: #include <sdkhooks>#include <sdktools_functions>#pragma semicolon 1#pragma newdecls requiredpublic Plugin myinfo = {name = "AntiAfk", author = "Drumanid", version = "1.0", url = "http://vk.com/drumanid"}Handle hTimer[MAXPLAYERS +1];bool bAfk[MAXPLAYERS +1];int iTime[MAXPLAYERS +1], iLimit[MAXPLAYERS +1];int ciTime, ciLimit, ciSpecKick;char tBuffer[192];public void OnPluginStart(){ ConVar CV; (CV = CreateConVar("cvTime", "30", "RU: Время перед наказанием | EN: Time of punishment", _, true, 5.0, true, 60.0)).AddChangeHook(Cvar_ciTime); ciTime = CV.IntValue; (CV = CreateConVar("cvLimit", "3", "RU: Предупреждения | EN: Warning", _, true, 2.0, true, 6.0)).AddChangeHook(Cvar_ciLimit); ciLimit = CV.IntValue; (CV = CreateConVar("cvSpecKick", "0", "RU: 0 - Кикать / 1 - Перевести в наблюдатели | EN: 0 - Kicked | 1 - Change team 1(spec)", _, true, 0.0, true, 1.0)).AddChangeHook(Cvar_ciSpecKick); ciSpecKick = CV.IntValue; LoadTranslations("AntiAfk.phrases"); AutoExecConfig(true, "AntiAfk");}public void Cvar_ciTime(ConVar convar, const char[] oldValue, const char[] newValue) {ciTime = convar.IntValue;}public void Cvar_ciLimit(ConVar convar, const char[] oldValue, const char[] newValue) {ciLimit = convar.IntValue;}public void Cvar_ciSpecKick(ConVar convar, const char[] oldValue, const char[] newValue) {ciSpecKick = convar.IntValue;}public void OnClientPostAdminCheck(int iClient){ if(!IsFakeClient(iClient)) SDKHook(iClient, SDKHook_SpawnPost, SpawnPost);}public Action SpawnPost(int iClient){ if(iClient) { bAfk[iClient] = true; if(hTimer[iClient] && iTime[iClient] > 0) iTime[iClient] = ciTime; else { iTime[iClient] = ciTime; hTimer[iClient] = CreateTimer(1.0, CheckAfk, GetClientUserId(iClient), TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE); } }}public Action CheckAfk(Handle timer, any UserId){ int iClient = GetClientOfUserId(UserId); if(iClient && IsPlayerAlive(iClient) && !IsFakeClient(iClient) && bAfk[iClient]) { if(--iTime[iClient] > 0) { if(iTime[iClient] > (ciTime - 5)) return Plugin_Handled; else { FormatEx(tBuffer, sizeof(tBuffer), "%t", "Warning motion hud", iTime[iClient]); SetHudTextParams(0.005, 0.5, 1.0, 255, 68, 68, 255, 0, 1.0, 0.1, 0.1); ShowHudText(iClient, -1, tBuffer); } return Plugin_Continue; } ++iLimit[iClient]; FormatEx(tBuffer, sizeof(tBuffer), "%t", "Warning motion chat", iLimit[iClient], ciLimit); PrintToChat(iClient, tBuffer); if(iLimit[iClient] == ciLimit) { switch(ciSpecKick) { case 0: { FormatEx(tBuffer, sizeof(tBuffer), "%T", "Kick message"); KickClient(iClient, tBuffer); } case 1: { ChangeClientTeam(iClient, 1); FormatEx(tBuffer, sizeof(tBuffer), "%t", "Change team"); PrintToChat(iClient, tBuffer); } } } else { ForcePlayerSuicide(iClient); FormatEx(tBuffer, sizeof(tBuffer), "%t", "Kill player", iClient); PrintToChatAll(tBuffer); } } hTimer[iClient] = null; return Plugin_Stop;}public Action OnPlayerRunCmd(int iClient, int &iButtons, int &iImpulse, float fVel[3], float fAngles[3], int &iWeapon){ if(bAfk[iClient] && IsPlayerAlive(iClient) && !IsFakeClient(iClient)) { if(iButtons) // if(iButtons & IN_RUN || iButtons & IN_RIGHT || iButtons & IN_LEFT || iButtons & IN_BACK || iButtons & IN_DUCK || iButtons & IN_JUMP) { bAfk[iClient] = false; iLimit[iClient] = 0; } }}public void OnClientDisconnect(int iClient){ if(hTimer[iClient] != null) { KillTimer(hTimer[iClient]); hTimer[iClient] = null; } iLimit[iClient] = 0;}
гоу сразу и вторую версию, перевод в чате) чтобы писало через сколько кикнит/переместит в спектора, и к ксгоколорс прикрутить
Мой AntiAfkLite (легкая версия). ПРЕДУПРЕЖДЕНИЕ: Не ставьте на сервера с модом Deathmatch, толку не будет, конкретно эту версию. PHP: #include <sdktools_functions>float fCP[MAXPLAYERS +1][3], fCI[MAXPLAYERS +1][3];public Plugin myinfo = {name = "AntiAfkLite", author = "Drumanid", version = "1.0", url = "http://vk.com/drumanid"}public void OnPluginStart() {HookEvent("round_freeze_end", RoundFreezeEnd);}public Action RoundFreezeEnd(Event event, const char[] name, bool dbc){ for (int i = 1; i <= MaxClients; i++) { if(IsClientInGame(i) && IsPlayerAlive(i) && !IsFakeClient(i)) { GetClientAbsOrigin(i, fCP[i]); } } CreateTimer(15.0, CheckPlayers, _, TIMER_FLAG_NO_MAPCHANGE); // меняйте под себя}public Action CheckPlayers(Handle timer){ for (int i = 1; i <= MaxClients; i++) { if(IsClientInGame(i) && IsPlayerAlive(i) && !IsFakeClient(i)) { GetClientAbsOrigin(i, fCI[i]); if(fCP[i][0] == fCI[i][0] && fCP[i][1] == fCI[i][1]) { ForcePlayerSuicide(i); PrintToChat(i, " \x02Не стойте в афк и вы не будете убиты!"); //LogToFile("addons/sourcemod/logs/afklog.txt", "%N - был убит, т.к долго находился в афк", i); } } }}
вот это зря. таймер не умирает в конце раунда и на следующий раунд их становится. С каждым раундом кол-во таймеров увеличивается на 1. Лучше запиши таймер в глобальный Handle и в конце раунда убивай его А еще лучше просто создать таймер в OnMapStart()
PHP: #include <sdktools_functions>float fCP[MAXPLAYERS +1][3], fCI[MAXPLAYERS +1][3];bool bStop; // Надо, иначе игроков может в один момент убить. Поэтому - запрещаем, а потом разрешаем и уже только потом снова проверяем.public Plugin myinfo = {name = "AntiAfkLite", author = "Drumanid", version = "1.0", url = "http://vk.com/drumanid"}public void OnPluginStart(){ HookEvent("round_freeze_end", RoundFreezeEnd);}public void OnMapStart(){ CreateTimer(15.0, CheckPlayers, _, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE); // меняйте под себя(время)}public Action RoundFreezeEnd(Event event, const char[] name, bool dbc){ bStop = false; for (int i = 1; i <= MaxClients; i++) { if(IsClientInGame(i) && IsPlayerAlive(i) && !IsFakeClient(i)) { GetClientAbsOrigin(i, fCP[i]); } }}public Action CheckPlayers(Handle timer){ if(bStop) { for (int i = 1; i <= MaxClients; i++) { if(IsClientInGame(i) && IsPlayerAlive(i) && !IsFakeClient(i)) { GetClientAbsOrigin(i, fCI[i]); if(fCP[i][0] == fCI[i][0] && fCP[i][1] == fCI[i][1]) { ForcePlayerSuicide(i); PrintToChat(i, " \x02Не стойте в афк и вы не будете убиты!"); //LogToFile("addons/sourcemod/logs/afklog.txt", "%N - был убит, т.к долго находился в афк", i); } } } } bStop = true;} P.S в таком случае везде нужно создавать 'handle' для таймеров
под новый синтаксис бы эту версию ) [CS: Source] - [KDLP] Облегченный AFK Manager [CSS] [TF2 в разработке] второй чет не встречал
@R1KO, а в чьём нибудь плагине есть какое нибудь решение с переводом в спектаторы последнего игрока, чтобы раунд заканчивался?)
@R1KO, у меня drapi_afk_manager, а эти не проверял, просто не хочется уже ставить не зная точно что там такого бага нет. Не понял на счёт мин. игроков, я на счёт того что когда остаётся 1 игрок в команде и его переводит в спектаторы за афк, то сервер не в курсе что нет игроков больше и пока не кикнешь например того который афк или живой не напишет kill то раунд не заканчивается.