Выполнение команды если игрок стоит на месте.

phll

Участник
Сообщения
16
Реакции
1
Если простой способ отловить afk? csgo.

p.s. я плохо разбираюсь в этом:(.
 
Последнее редактирование:

FrozDark

Участник
Сообщения
1,769
Реакции
2,050
попробуй
 

Вложения

  • afk_manager_reinvented.smx
    11 КБ · Просмотры: 8
  • afk_manager_reinvented.txt
    3.9 КБ · Просмотры: 22

phll

Участник
Сообщения
16
Реакции
1
Спасибо за ответ:) но не мог бы ты выложить исходник?
как ты определяешь afk? и как сильно такая проверка может нагрузить серв?

грубо говоря мне нужно условия определение afk(желательно не громозкое и легкое), при нахождение чтобы выполнилось это команда, и все:) KickClient(client, "AFK");.
 

phll

Участник
Сообщения
16
Реакции
1
нашел вот это:
C-подобный:
CheckForAFK(client)
{
    new Float:f_Loc[3];
    new f_Team = GetClientTeam(client);
    new bool:f_SamePlace[3];

    if(f_Team > 1 || g_IsSynergy)
    {
        GetPlayerEye(client, f_Loc);

        for(new i = 0; i < 3; i++)
        {
            if(g_Position[client][i] == f_Loc[i])
            {
                f_SamePlace[i] = true;
            }
            else
            {
                f_SamePlace[i] = false;
            }
        }
    }

    if((f_SamePlace[0] == true
        && f_SamePlace[1] == true
        && f_SamePlace[2] == true)
        || (f_Team < 2 && g_IsSynergy == false))
    {
        g_TimeAFK[client]++;
    }
    else
    {
        g_TimeAFK[client] = 0;
    }
}

.......

bool:GetPlayerEye(client, Float:pos[3])
{
    new Float:vAngles[3], Float:vOrigin[3];
    GetClientEyePosition(client,vOrigin);
    GetClientEyeAngles(client, vAngles);
    
    new Handle:trace = TR_TraceRayFilterEx(vOrigin, vAngles, MASK_SHOT, RayType_Infinite, TraceEntityFilterPlayer);
    
    if(TR_DidHit(trace))
    {
         //This is the first function i ever saw that anything comes before the handle
        TR_GetEndPosition(pos, trace);
        CloseHandle(trace);
        return true;
    }
    CloseHandle(trace);
    return false;
}
немогу рзобраться, знаю что это то, но не могу использовать... может кто то сможет помощь? Нужная простая проверка afk, на респе в начале раунда. Если игрок не двигался 30 секунд, выполнить команду KickClient(client, "AFK")


Вот плагин:
C-подобный:
/**
 * vim: set ts=4 :
 * =============================================================================
 * AFK Manager
 * Handles AFK Players
 *
 * SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved.
 * =============================================================================
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License, version 3.0, as published by the
 * Free Software Foundation.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * As a special exception, AlliedModders LLC gives you permission to link the
 * code of this program (as well as its derivative works) to "Half-Life 2," the
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
 * by the Valve Corporation.  You must obey the GNU General Public License in
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
 * this exception to all derivative works.  AlliedModders LLC defines further
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
 * or <http://www.sourcemod.net/license.php>.
 *
 */

#pragma semicolon 1
#include <sourcemod>
#include <sdktools>

#define VERSION "2.8"

#define _DEBUG 0 // set to 1 to enable debug

// global variables
new Float:g_Position[MAXPLAYERS+1][3];
new g_TimeAFK[MAXPLAYERS+1];
new bool:g_IsSynergy = false;
new bool:g_IsTF2Arena;
new bool:g_IsLateLoad = false;
new g_MaxPlayers = 0;

// cvars
new Handle:g_Cvar_Enabled = INVALID_HANDLE;
new Handle:g_Cvar_MinPlayersMove = INVALID_HANDLE;
new Handle:g_Cvar_MinPlayersKick = INVALID_HANDLE;
new Handle:g_Cvar_AdminsImmune = INVALID_HANDLE;
new Handle:g_Cvar_MoveSpec = INVALID_HANDLE;
new Handle:g_Cvar_TimeToMove = INVALID_HANDLE;
new Handle:g_Cvar_TimeToKick = INVALID_HANDLE;

public Plugin:myinfo =
{
    name = "AFK Manager",
    author = "Liam",
    description = "Handles AFK Players",
    version = VERSION,
    url = "http://www.wcugaming.org"
};

public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max)
{
    g_IsLateLoad = late;
    return APLRes_Success;
}

public OnPluginStart( )
{
    decl String:f_ModName[64];

    LoadTranslations("common.phrases");
    RegisterHooks( );
    RegisterCvars( );
    AutoExecConfig(true, "afk_manager");
    g_MaxPlayers = GetMaxClients();

    GetGameDescription(f_ModName, sizeof(f_ModName), true);

    if(!strcmp(f_ModName, "Synergy"))
    {
        g_IsSynergy = true;
    }
    
    if (g_IsLateLoad == true)
    {
        if (FindEntityByClassname(GetMaxClients() + 1, "tf_arena_logic") == INVALID_ENT_REFERENCE)
        {
            g_IsTF2Arena = false;
        }
        else
        {
            g_IsTF2Arena = true;
        }
    }
}

RegisterCvars( )
{
    CreateConVar("sm_afk_version", VERSION, "Current version of the AFK Manager", FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD);
    g_Cvar_Enabled = CreateConVar("sm_afkenable", "1", "Is the AFK manager enabled or disabled? [0 = FALSE, 1 = TRUE]");
    g_Cvar_MinPlayersMove = CreateConVar("sm_minplayersmove", "4", "Minimum amount of connected clients needed to move AFK clients to spec.");
    g_Cvar_MinPlayersKick = CreateConVar("sm_minplayerskick", "6", "Minimum amount of connected clients needed to kick AFK clients.");
    g_Cvar_AdminsImmune = CreateConVar("sm_adminsimmune", "1", "Admins immune to being kicked? [0 = FALSE, 1 = TRUE]");
    g_Cvar_MoveSpec = CreateConVar("sm_movespec", "1", "Move AFK clients to spec before kicking them? [0 = FALSE, 1 = TRUE]");
    g_Cvar_TimeToMove = CreateConVar("sm_timetomove", "60.0", "Time in seconds before moving an AFK player.");
    g_Cvar_TimeToKick = CreateConVar("sm_timetokick", "120.0", "Time in seconds before kicking an AFK player.");
}

public OnMapStart( )
{
    for(new i = 1; i <= g_MaxPlayers; i++)
    {
        g_TimeAFK[i] = 0;
    }
    CreateTimer(60.0, Timer_StartTimers, _, TIMER_FLAG_NO_MAPCHANGE);
}

public Action:Timer_StartTimers(Handle:Timer)
{
    CreateTimer(7.0, Timer_UpdateView, _, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
    CreateTimer(10.0, Timer_CheckPlayers, _, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
}

RegisterHooks( )
{
    HookEvent("player_spawn", Event_PlayerSpawn);
    HookEvent("player_team", Event_PlayerTeam);
    HookEventEx("arena_round_start", Event_ArenaRoundStart);
    HookEventEx("teamplay_round_start", Event_RoundStart);
    HookEventEx("round_start", Event_RoundStart);
}

public Action:Event_PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast)
{
    new client = GetClientOfUserId(GetEventInt(event, "userid"));
    g_TimeAFK[client] = 0;
}

public Action:Event_RoundStart(Handle:event, const String:name[], bool:dontBroadcast)
{
    g_IsTF2Arena = false;
}

public Action:Event_ArenaRoundStart(Handle:event, const String:name[], bool:dontBroadcast)
{
    g_IsTF2Arena = true;
}

public Action:Event_PlayerTeam(Handle:event, const String:name[], bool:dontBroadcast)
{
    new client = GetClientOfUserId(GetEventInt(event, "userid"));
    
    if(!g_IsSynergy)
    {        
        if(GetEventInt(event, "team") > 1)
        {
            g_TimeAFK[client] = 0;
        }
    }
    else
    {
        g_TimeAFK[client] = 0;
    }
}

public Action:Timer_UpdateView(Handle:Timer)
{
    for(new i = 1; i <= g_MaxPlayers; i++)
    {
        if(IsRealPlayer(i) == false
            || IsPlayerAlive(i) == false)
        {
            continue;
        }
        GetPlayerEye(i, g_Position[i]);
    }
}

public Action:Timer_CheckPlayers(Handle:Timer)
{
    if(GetConVarInt(g_Cvar_Enabled) == 0)
        return Plugin_Stop;

    if(GetConVarInt(g_Cvar_MinPlayersMove) >= GetClientCount( ))
    {
        return Plugin_Continue;
    }

    for(new i = 1; i < g_MaxPlayers; i++)
    {
        if(IsRealPlayer(i) == false)
        {
            continue;
        }
        CheckForAFK(i);
        HandleAFKClient(i);
    }
    return Plugin_Continue;
}

CheckForAFK(client)
{
    new Float:f_Loc[3];
    new f_Team = GetClientTeam(client);
    new bool:f_SamePlace[3];

    if(f_Team > 1 || g_IsSynergy)
    {
        GetPlayerEye(client, f_Loc);

        for(new i = 0; i < 3; i++)
        {
            if(g_Position[client][i] == f_Loc[i])
            {
                f_SamePlace[i] = true;
            }
            else
            {
                f_SamePlace[i] = false;
            }
        }
    }

    if((f_SamePlace[0] == true
        && f_SamePlace[1] == true
        && f_SamePlace[2] == true)
        || (f_Team < 2 && g_IsSynergy == false))
    {
        g_TimeAFK[client]++;
    }
    else
    {
        g_TimeAFK[client] = 0;
    }
}

HandleAFKClient(client)
{
    new f_SpecTime = RoundToZero(GetConVarFloat(g_Cvar_TimeToMove)) / 10;
    new f_KickTime = RoundToZero(GetConVarFloat(g_Cvar_TimeToKick)) / 10;
    new f_MoveSpec = GetConVarInt(g_Cvar_MoveSpec);
    new f_MinKick = GetConVarInt(g_Cvar_MinPlayersKick);
    decl String:f_Name[MAX_NAME_LENGTH];
    new f_Team = GetClientTeam(client);

    GetClientName(client, f_Name, sizeof(f_Name));

    if (g_IsSynergy == false
        && f_MoveSpec == 1
        && g_TimeAFK[client] < f_KickTime 
        && g_TimeAFK[client] >= f_SpecTime)
    {
        if(f_Team == 2 || f_Team == 3)
        {
            PrintToChatAll("%s was moved to spectate for being AFK.", f_Name);
            LogAction(0, -1, "\"%L\" was moved to spectate for being AFK too long.", client);
            ChangeClientTeam(client, 1);
            
            if (g_IsTF2Arena == true)
            {
                SetEntProp(client, Prop_Send, "m_bArenaSpectator", true);
            }
        }
        return;
    }
    
    // added to do a last final check. Maybe they moved during the timer update and max count?
    CheckForAFK(client);

    if(g_TimeAFK[client] >= f_KickTime
        && !IsAdmin(client))
    {
#if _DEBUG
        LogAction(0, -1, "Kicking Client: %d, Team: %d - CVar_MinKick: %d - ClientCount: %d", client, f_Team, f_MinKick, GetClientCount(false));
#endif
        if(GetClientCount(false) >= f_MinKick) // this shouldn't matter but wtf ever
        {
            PrintToChatAll("%s was kicked for being AFK.", f_Name);
            LogAction(0, -1, "\"%L\" was kicked for being AFK too long.", client);
            KickClient(client, "You were AFK for too long.");
        }
    }
}

// This code was borrowed from Nican's spraytracer
bool:GetPlayerEye(client, Float:pos[3])
{
    new Float:vAngles[3], Float:vOrigin[3];
    GetClientEyePosition(client,vOrigin);
    GetClientEyeAngles(client, vAngles);
    
    new Handle:trace = TR_TraceRayFilterEx(vOrigin, vAngles, MASK_SHOT, RayType_Infinite, TraceEntityFilterPlayer);
    
    if(TR_DidHit(trace))
    {
         //This is the first function i ever saw that anything comes before the handle
        TR_GetEndPosition(pos, trace);
        CloseHandle(trace);
        return true;
    }
    CloseHandle(trace);
    return false;
}

public bool:TraceEntityFilterPlayer(entity, contentsMask)
{
    return entity > GetMaxClients( );
}

bool:IsAdmin(client)
{
#if _DEBUG
    LogAction(0, -1, "Checking for admins.");
#endif

    if(GetConVarInt(g_Cvar_AdminsImmune) == 0)
    {
#if _DEBUG
        LogAction(0, -1, "Admins are not immune to being kicked.");
#endif
        return false;
    }

    new AdminId:admin = GetUserAdmin(client);

#if _DEBUG
    decl String:name[MAX_NAME_LENGTH];

    GetClientName(client, name, sizeof(name));
    LogAction(0, -1, "Checking for valid AdminID: Found: %d for client %s", _:admin, name);
#endif

    if(admin == INVALID_ADMIN_ID)
    {
#if _DEBUG
        LogAction(0, -1, "Client %s has an invalid Admin ID.", name);
#endif
        return false;
    }
#if _DEBUG
    LogAction(0, -1, "Client %s has a valid Admin ID and is immune.", name);
#endif
    return true;
}

bool:IsRealPlayer(client)
{
    if(!IsClientConnected(client)
        || !IsClientInGame(client)
        || IsFakeClient(client))
    {
        return false;
    }
    return true;
}
 

FrozDark

Участник
Сообщения
1,769
Реакции
2,050
только он проверяет не только игрока стоящего на респе
 

Вложения

  • afk_manager_reinvented.sp
    6.5 КБ · Просмотры: 10

hostvd

Участник
Сообщения
21
Реакции
2
Вот обрезанная версия плагина от wS (AFK Ping Control v1.3)
PHP:
#pragma semicolon 1
#include <sourcemod>
#include <sdktools_functions>

new Handle:g_hTimer;
new Float:g_MyAngles[MAXPLAYERS + 1][3];

public OnPluginStart()
{
    wS_StartTimer();
}

wS_StartTimer(){g_hTimer = CreateTimer(7.0, g_AfkTimer_CallBack, _, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE);} \\ если игрок бездействует 7 секунд, то кикает.

public OnMapStart()
{
    g_hTimer = INVALID_HANDLE;
}

public Action:g_AfkTimer_CallBack(Handle:timer)
{
    decl Float:angles[3];
    for (new i = 1; i <= MaxClients; i++)
    {
        if (IsClientInGame(i) && !IsFakeClient(i))
        {
            if (GetClientEyeAngles(i, angles))
            {
                if (angles[0] == g_MyAngles[i][0] && angles[1] == g_MyAngles[i][1] && angles[2] == g_MyAngles[i][2])
                {
                    KickClient(i, "AFK");
                }
                else
                    g_MyAngles[i] = angles;
            }
        }
    }
    return Plugin_Continue;
}

public OnClientPutInServer(client)
{
    if (g_hTimer == INVALID_HANDLE && !IsFakeClient(client))
        wS_StartTimer();
}
вроде работает...
Но было бы хорошо, если бы взглянул знающий человек и оптимизировал:).
 

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #7
HOSTVD,
PHP:
#pragma semicolon 1
#include <sourcemod>
#include <sdktools_functions>

new Handle:g_hTimer;
new Float:g_MyAngles[MAXPLAYERS + 1][3];

public OnMapStart()
{
	if(g_hTimer != INVALID_HANDLE)
	{
		KillTimer(g_hTimer);
		g_hTimer = INVALID_HANDLE;
	}
	g_hTimer = CreateTimer(7.0, g_AfkTimer_CallBack, _, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE);
}

public Action:g_AfkTimer_CallBack(Handle:timer)
{
	decl Float:angles[3];
	for (new i = 1; i <= MaxClients; i++)
	{
		if (IsClientInGame(i) && !IsFakeClient(i))
		{
			if (GetClientEyeAngles(i, angles))
			{
				if (angles[0] == g_MyAngles[i][0] && angles[1] == g_MyAngles[i][1] && angles[2] == g_MyAngles[i][2]) KickClient(i, "AFK");
				else g_MyAngles[i] = angles;
			}
		}
	}
	return Plugin_Continue;
}

Но еще не плохо было бы проверять наблюдатель ли он.
 

hostvd

Участник
Сообщения
21
Реакции
2
Баг: если не двигать мышку а просто ходить туда сюда клавой, тебя всеравно кикнет. Из-за того что используется только GetClientEyeAngles.

Добавлено через 2 минуты
Но еще не плохо было бы проверять наблюдатель ли он.

я в этом плох.... сможешь допилить на досуге?:)
 
Последнее редактирование:

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #9
Баг: если не двигать мышку а просто ходить туда сюда клавой, тебя всеравно кикнет. Из-за того что используется только GetClientEyeAngles.
Проверяй GetClientEyeAngles и GetClientAbsOrigin.

Еще учитывай IsClientObserver, GetEntProp(client, Prop_Send, "m_iObserverMode") и GetEntPropEnt(client, Prop_Send, "m_hObserverTarget");

я в этом плох.... сможешь допилить на досуге?:)
У меня не бывает досуга..

Чем это не устраивает?
http://hlmod.ru/forum/plaginy-dlya-...chennyi-afk-manager-css-tf2-v-razrabotke.html
 

KorDen

Atra esterní ono thelduin!
Сообщения
2,142
Реакции
1,424
R1KO, там нет проверки на AFK со спауна, я же как раз ее вырезал там
 
  • Мне нравится
Реакции: R1KO

The End Is Near...

Russian Roulette
Сообщения
874
Реакции
691
R1KO
Не нужно выделять переменную для таймера в данном случае
 
  • Мне нравится
Реакции: R1KO
Сверху Снизу