RegConsoleCmd и Присвоение строчечному массиву значение аргумента

Alex's Works

Участник
Сообщения
8
Реакции
0
Доброго времени суток!
На днях столкнулся с проблемой в написании плагина. И как человек, который плохо понимает в SourcePawn, жду вашей помощи.
Проблема №1 вот в чём.
Мне нужна консольная команда, которая будет иметь 2 аргумента, а не стандартный 1 Оффтоп. Компилятор на RegConsoleCmd("switch_player", admin_switch) и public Action:admin_switch(client, args, arg2) говорит о ненахождении прототипа функции, сколько бы я не писал return Plugin_Handled и Plugin_Continue. Возможно из-за бесконечного там числа ошибок или аргумента 2. Оффтоп
Проблема №2.
Мне нужно перевести значение аргумента в строку для последующей проверки наличия "аргумента" в списке игроков на сервере. IntToString? Или просто сравнить i с args?
Проблема №3
Несовпадение тегов на GetAdminFlag(client, Admin_Root). Client из admin_swich.
Пробела №4.
Пустой оператор на args != 1 , который получает cmd_survivor от admin_switch через команду cmd_survivor(args, 1)

Нарезка кода :
C-подобный:
public OnPluginStart()
{
RegConsoleCmd("spectate", cmd_spectate);
RegConsoleCmd("switch_player", admin_switch);
RegConsoleCmd("survivor", cmd_survivor);
RegConsoleCmd("infected", cmd_infected);
afkTimer = CreateTimer(20.0, afkCheckThread, _, TIMER_REPEAT);
afkRegisterEvents();
SetConVarInt(FindConVar("vs_max_team_switches"), 9999);
if (FileExists("addons/sourcemod/gamedata/l4d_takeover.txt"))
{
    L4DTakeoverConf = LoadGameConfigFile("l4d_takeover");
    if (L4DTakeoverConf == INVALID_HANDLE)
       {
        SetFailState("Survivor Bot Takeover have errors. Could not load gamedata/l4d_takeover.txt");
        return;
        }
    else
    {
        StartPrepSDKCall(SDKCall_Player);
        PrepSDKCall_SetFromConf(L4DTakeoverConf, SDKConf_Signature, "SetHumanSpec");
        PrepSDKCall_AddParameter(SDKType_CBasePlayer, SDKPass_Pointer);
        L4DTakeoverSHS = EndPrepSDKCall();

        StartPrepSDKCall(SDKCall_Player);
        PrepSDKCall_SetFromConf(L4DTakeoverConf, SDKConf_Signature, "TakeOverBot");
        PrepSDKCall_AddParameter(SDKType_Bool, SDKPass_Plain);
        L4DTakeoverTOB = EndPrepSDKCall();
        }
    }
    else
    {
        SetFailState("Survivor Bot Takeover have errors. Could not load gamedata/l4d_takeover.txt");
        return;
    }
}
C-подобный:
public Action:admin_switch(client, args, arg2){
    if(IsClientInGame(args) && IsClientConnected(args) && !IsFakeClient(args) && ( client==0 || GetAdminFlag(client, Admin_Root, Access_Real) || GetAdminFlag(client, Admin_Kick, Access_Real)))
{
        char name[60];
        int maxplayers, target = -1;
        IntToString(args, name, 60);
        maxplayers = GetMaxClients();
        for (int i = 1; i <= maxplayers; i++)
        {
            char other[60];
            GetClientName(i, other, sizeof(other));
            if (StrEqual(name, other))
            {
                target = 1;
            }
            else {return Plugin_Handled;}
            if (target == 1)
            {
                switch(arg2)
                {
                    case 1:
                    {
                        cmd_spectate(args, 1);
                        return Plugin_Continue;
                    }
                    case 2:
                    {
                        cmd_survivor(args, 1);
                        return Plugin_Continue;
                    }
                    case 3:
                    {
                        cmd_infected(args, 1);
                        return Plugin_Continue;
                    }
                }
            }
            else {return Plugin_Handled;}
        }
    }
    else {return Plugin_Handled;}
    return Plugin_Continue;
}
C-подобный:
public Action:cmd_survivor(client, args){
    if(client==0){return Plugin_Handled;}
    if(GetClientTeam(client)==2){return Plugin_Handled;}
    for (new x =1; x<32; x++){
            if(IsClientInGame(x) && IsClientConnected(x)){
                if (GetClientTeam(x)==2 && !IsFakeClient(x)){surv++;}}}
    if (surv == 4 && args != 1){PrintToChat(client, "[Team switcher] No places"); ;}
    else{
        new bot;
        for (bot = 1; bot <= 32; bot++){
            if (!IsClientConnected(bot) || !IsFakeClient(bot) || GetClientTeam(bot) != 2 || GetClientHealth(bot) == 0){}
            else{break;}
        }
        SDKCall(L4DTakeoverSHS, bot, client);
        SDKCall(L4DTakeoverTOB, client, true);   
        surv=0;
        PrintToChatAll("\x01\x04[SM] \x03You \x01has been switched to \x03Survivors");
        return Plugin_Continue;
}}
 

SHAREN

Servers-Info.Ru
Сообщения
232
Реакции
32
args это количество аргументов после команды, пример "sm_ban @me" args == 1, sm_ban @me 1440 args == 2,

Пример с аргументами
sourcemod/kick.sp at 237db0504c7a59e394828446af3e8ca3d53ef647 · alliedmodders/sourcemod · GitHub
RegAdminCmd("sm_kick", Command_Kick, ADMFLAG_KICK, "sm_kick <#userid|name> [reason]");

Чтобы получить что написано после sm_ban, т.е. аргументы используй
char Arguments[256];
GetCmdArgString(Arguments, sizeof(Arguments)); // там будет типа "@me 1440"
потом разделяешь все по пробелам через BreakString, в int len записываешь позицию второго аргумента

132 строка

Просто изучи готовые исходники и сделай по аналогии
 

Alex's Works

Участник
Сообщения
8
Реакции
0
Долго ковырялся со строчками и последующем переводом в int Оффтоп, но вроде скомпилировал без ошибок. Буду проверять
 

Alex's Works

Участник
Сообщения
8
Реакции
0
PHP:
public Action:admin_switch(client, args)
{
    if (!args || !client) return Plugin_Handled;
    AdminId admin = GetUserAdmin(client);
    if (GetAdminFlag(admin, Admin_Root, Access_Real) || GetAdminFlag(admin, Admin_Kick, Access_Real))
    {
        char name[MAX_NAME_LENGTH], other[MAX_NAME_LENGTH];
        int target;
        GetCmdArg(1, name, sizeof(name));
        for (int i = 1; i <= MaxClients; i++)
        {
            if (IsClientInGame(i))
            {
                GetClientName(i, other, sizeof(other));
                if (StrEqual(name, other))
                {
                    target = i;
                    break;
                }
            }
        }
        if (target)
        {
            switch(GetClientTeam(target))
            {
                case 1:
                {
                    cmd_spectate(target, args);
                }
                case 2:
                {
                    cmd_survivor(target, args);
                }
                case 3:
                {
                    cmd_infected(target, args);
                }
            }
        }
    }
    return Plugin_Handled;
}

Вот что примерно будет
C-подобный:
public Action:admin_switch(client, args){
    if (!args || !client) return Plugin_Handled;
    AdminId admin = GetUserAdmin(client);
    if (GetAdminFlag(admin, Admin_Root) || GetAdminFlag(admin, Admin_Kick)){
        char name[MAX_NAME_LENGTH], other[MAX_NAME_LENGTH], arg2[2];
        int target, arg2int = 0;
        GetCmdArg(1, name, sizeof(name));
        GetCmdArg(2, arg2, sizeof(arg2));
        if (StrEqual(arg2, "1")) arg2int = 1;
        if (StrEqual(arg2, "2")) arg2int = 2;
        if (StrEqual(arg2, "3")) arg2int = 3;
        if (arg2int == 0) return Plugin_Handled;
        for (int i = 1; i <= MaxClients; i++){
            if (IsClientInGame(i))
            {
                GetClientName(i, other, sizeof(other));
                if (StrEqual(name, other))
                {
                    target = i;
                    break;
                }
            }
        }
        if (target){
            switch(arg2int)
            {
                case 1:
                {
                    cmd_spectate(target, 1);
                }
                case 2:
                {
                    cmd_survivor(target, 1);
                }
                case 3:
                {
                    cmd_infected(target, 1);
                }
            }
        }
    }
    return Plugin_Handled;
}
И где там Оффтоп потеря отступа на GetCmdArg(2, arg2, sizeof(arg2)); и for (int i = 1; i <= MaxClients; i++)?
--- Добавлено позже ---
ChangeClientTeam(target, StringToInt(other));
В Left 4 Dead 2 некорректно работает такое изменение команды
 
Последнее редактирование:

Grey83

не пишу плагины с весны 2022
Сообщения
8,521
Реакции
4,981
@Alex'sWorks, если писать на новом синтаксисе то лучше будет сделать как-то вроде этого:
PHP:
#pragma semicolon 1
#pragma newdecls required

#include <sdktools>

int iTeamSize[4];

Handle L4DTakeoverConf,
    L4DTakeoverSHS,
    L4DTakeoverTOB,
    afkTimer;

public void OnPluginStart()
{
    if (!FileExists("addons/sourcemod/gamedata/l4d_takeover.txt")) SetFailState("Survivor Bot Takeover have errors. Could not load gamedata/l4d_takeover.txt");
    else
    {
        L4DTakeoverConf = LoadGameConfigFile("l4d_takeover");
        if (L4DTakeoverConf == INVALID_HANDLE) SetFailState("Survivor Bot Takeover have errors. Could not load gamedata/l4d_takeover.txt");
        else
        {
            StartPrepSDKCall(SDKCall_Player);
            PrepSDKCall_SetFromConf(L4DTakeoverConf, SDKConf_Signature, "SetHumanSpec");
            PrepSDKCall_AddParameter(SDKType_CBasePlayer, SDKPass_Pointer);
            L4DTakeoverSHS = EndPrepSDKCall();

            StartPrepSDKCall(SDKCall_Player);
            PrepSDKCall_SetFromConf(L4DTakeoverConf, SDKConf_Signature, "TakeOverBot");
            PrepSDKCall_AddParameter(SDKType_Bool, SDKPass_Plain);
            L4DTakeoverTOB = EndPrepSDKCall();
        }
    }

    RegConsoleCmd("spectate", cmd_spectate);
    RegConsoleCmd("switch_player", admin_switch);
    RegConsoleCmd("survivor", cmd_survivor);
    RegConsoleCmd("infected", cmd_infected);

    afkTimer = CreateTimer(20.0, afkCheckThread, _, TIMER_REPEAT);
    afkRegisterEvents();
    SetConVarInt(FindConVar("vs_max_team_switches"), 9999);
}

public Action afkCheckThread(Handle afk_Timer){}

void afkRegisterEvents(){}

public Action cmd_spectate(int client, int args)
{
    if (client && args > 1) TeamSwitch(client, client, 1);

    return Plugin_Handled;
}

public Action cmd_survivor(int client, int args)
{
    if (client && args > 1) TeamSwitch(client, client, 2);

    return Plugin_Handled;
}

public Action cmd_infected(int client, int args)
{
    if (client && args > 1) TeamSwitch(client, client, 3);

    return Plugin_Handled;
}

int GetTarget(char[] target_name)
{
    char client_name[MAX_NAME_LENGTH];

    for (int i = 1; i <= MaxClients; i++)
    {
        if (IsClientInGame(i))
        {
            GetClientName(i, client_name, sizeof(client_name));
            if (StrEqual(target_name, client_name)) return i;
        }
    }

    return 0;
}

public Action admin_switch(int client, int args)
{
    if (!client || args < 2) return Plugin_Handled;

    AdminId admin = GetUserAdmin(client);
    if(admin == INVALID_ADMIN_ID) return Plugin_Handled;

    if (GetAdminFlag(admin, Admin_Root) || GetAdminFlag(admin, Admin_Kick))
    {
        char name[MAX_NAME_LENGTH], arg2[2];

        GetCmdArg(1, name, sizeof(name));
        int target = GetTarget(name);
        if (!target) return Plugin_Handled;

        GetCmdArg(2, arg2, sizeof(arg2));
        int arg2int = StringToInt(arg2);
        if (!arg2int) return Plugin_Handled;

        TeamSwitch(client, target, arg2int);
    }
    return Plugin_Handled;
}

void TeamSwitch(int client, int target, int team)
{
    if(!target || GetClientTeam(target) == team) return;

    for (int i =1; i <= MaxClients; i++)
    {
        if(IsClientInGame(i) && IsClientConnected(i) && GetClientTeam(i) == team && !IsFakeClient(i)) iTeamSize[team]++;
    }

    if (iTeamSize[team] == 4) PrintToChat(client, "[Team switcher] No places");
    else
    {
        int bot;
        for (bot = 1; bot <= MaxClients; bot++)
        {
            if (!IsClientConnected(bot) || !IsFakeClient(bot) || GetClientTeam(bot) != team || GetClientHealth(bot) == 0){}
            else break;
        }

        SDKCall(L4DTakeoverSHS, bot, target);
        SDKCall(L4DTakeoverTOB, target, true);
        iTeamSize[team] = 0;

        PrintToChat(target, "\x01\x04[SM] \x03You \x01has been switched to \x03Survivors");
    }
}
 

Alex's Works

Участник
Сообщения
8
Реакции
0
TeamSwitch(int client, int target, int team)
Проблема Left 4 Dead 2 в том, что для перемещения в каждую команду есть свои особенности. И L4D2 не поймёт тебя, если ты попытаешься отдать в управление игроку бота-наблюдателя
 

Grey83

не пишу плагины с весны 2022
Сообщения
8,521
Реакции
4,981
@Alex'sWorks, а подкорректировать работу функции в зависимости от выбранной команды уже нельзя, что ли?
 
Сверху Снизу