Написание плагинов

Palonez

бб братки
Сообщения
3,035
Реакции
1,837
Видимо учусь на своих же ошибках) Без этого он выдает ошибку:
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'AUTO_INCREMENT,`auth` varchar(22) NOT NULL,`name` varchar(64) NOT NULL,`rank` in' at line 1
C-подобный:
SQL_FormatQuery(db, sQuery, sizeof(sQuery), "CREATE TABLE IF NOT EXISTS `%s` (\
  `id` PRIMARY KEY AUTO_INCREMENT,\
  `auth` varchar(22) NOT NULL,\
  `name` varchar(256) NOT NULL,\
  `rank` integer(11) unsigned NOT NULL,\
  `kills` integer(11) NOT NULL,\
  `death` integer(11) NOT NULL,\
  `hs` integer(11) NOT NULL,\
  `connect_time` timestamp) ENGINE InnoDBDEFAULT CHARSET utf8;", TABLENAME);
 

skaeN

Участник
Сообщения
204
Реакции
108
@Palonez, он категорически не хочет воспринимать это..
C#:
L 10/12/2022 - 08:00:14: [SM] Exception reported: ERROR CREATE TABLE: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'PRIMARY KEY AUTO_INCREMENT,`auth` varchar(22) NOT NULL,`name` varchar(256) NOT N' at line 1
 

Palonez

бб братки
Сообщения
3,035
Реакции
1,837
@Palonez, он категорически не хочет воспринимать это..
C#:
L 10/12/2022 - 08:00:14: [SM] Exception reported: ERROR CREATE TABLE: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'PRIMARY KEY AUTO_INCREMENT,`auth` varchar(22) NOT NULL,`name` varchar(256) NOT N' at line 1
поставь ключ на auth, а в id убери
 

Palonez

бб братки
Сообщения
3,035
Реакции
1,837
@Palonez, неа, все равно этим не решается проблема
C-подобный:
SQL_FormatQuery(db, sQuery, sizeof(sQuery), "CREATE TABLE IF NOT EXISTS `%s` (\
  `id` PRIMARY KEY AUTO_INCREMENT,\
  `auth` VARCHAR(22) NOT NULL,\
  `name` VARCHAR(256) NOT NULL,\
  `rank` INTEGER(11) NOT NULL,\
  `kills` INTEGER(11) NOT NULL,\
  `death` INTEGER(11) NOT NULL,\
  `hs` INTEGER(11) NOT NULL,\
  `connect_time` TIMESTAMP) DEFAULT CHARSET=utf8mb4;", TABLENAME);
так?
 

skaeN

Участник
Сообщения
204
Реакции
108
@Palonez, неа, все так же.
Если генерить в mysql запрос, то он автоматом выставляет тип для id INT

C-подобный:
CREATE TABLE `u27800_users`. ( 
`id` INT NOT NULL AUTO_INCREMENT ,
 `auth` VARCHAR(22) NOT NULL , 
`name` VARCHAR(256) NOT NULL , 
`rank` INT(11) NOT NULL , 
`kills` INT(11) NOT NULL ,
 `deaths` INT(11) NOT NULL ,
 `hs` INT(11) NOT NULL ,
 `team` INT(11) NOT NULL ,
 `connect_time` TIMESTAMP NOT NULL , PRIMARY KEY (`auth`), UNIQUE (`id`)) ENGINE = InnoDB;
 

Palonez

бб братки
Сообщения
3,035
Реакции
1,837
@Palonez, неа, все так же.
Если генерить в mysql запрос, то он автоматом выставляет тип для id INT

C-подобный:
CREATE TABLE `u27800_users`. (
`id` INT NOT NULL AUTO_INCREMENT ,
 `auth` VARCHAR(22) NOT NULL ,
`name` VARCHAR(256) NOT NULL ,
`rank` INT(11) NOT NULL ,
`kills` INT(11) NOT NULL ,
 `deaths` INT(11) NOT NULL ,
 `hs` INT(11) NOT NULL ,
 `team` INT(11) NOT NULL ,
 `connect_time` TIMESTAMP NOT NULL , PRIMARY KEY (`auth`), UNIQUE (`id`)) ENGINE = InnoDB;
Ну этот и сделай запрос
 

skaeN

Участник
Сообщения
204
Реакции
108
Ну этот и сделай запрос
Методом тыка, рабочий вариант вот такой:

C#:
    SQL_FormatQuery(db, sQuery, sizeof(sQuery), "CREATE TABLE IF NOT EXISTS `%s` (\
                                                  `id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,\
                                                  `auth` VARCHAR(22) NOT NULL,\
                                                  `name` VARCHAR(256) NOT NULL,\
                                                  `rank` INTEGER(11) NOT NULL,\
                                                  `kills` INTEGER(11) NOT NULL,\
                                                  `death` INTEGER(11) NOT NULL,\
                                                  `hs` INTEGER(11) NOT NULL,\
                                                  `team` INTEGER(11) NOT NULL,\
                                                  `connect_time` TIMESTAMP) DEFAULT CHARSET=utf8mb4;", TABLENAME);
Последний вопросик, можно как-то сократить эту запись?

C-подобный:
GetClientName(client, sName, sizeof(sName));
    int iLen = 2*strlen(sName)+1;
    char[] szEscapedName = new char[iLen ];
    db.Escape(sName, szEscapedName, iLen );
 

Palonez

бб братки
Сообщения
3,035
Реакции
1,837
Методом тыка, рабочий вариант вот такой:

C#:
    SQL_FormatQuery(db, sQuery, sizeof(sQuery), "CREATE TABLE IF NOT EXISTS `%s` (\
                                                  `id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,\
                                                  `auth` VARCHAR(22) NOT NULL,\
                                                  `name` VARCHAR(256) NOT NULL,\
                                                  `rank` INTEGER(11) NOT NULL,\
                                                  `kills` INTEGER(11) NOT NULL,\
                                                  `death` INTEGER(11) NOT NULL,\
                                                  `hs` INTEGER(11) NOT NULL,\
                                                  `team` INTEGER(11) NOT NULL,\
                                                  `connect_time` TIMESTAMP) DEFAULT CHARSET=utf8mb4;", TABLENAME);
Последний вопросик, можно как-то сократить эту запись?

C-подобный:
GetClientName(client, sName, sizeof(sName));
    int iLen = 2*strlen(sName)+1;
    char[] szEscapedName = new char[iLen ];
    db.Escape(sName, szEscapedName, iLen );
Неа, главное зачем?
 

skaeN

Участник
Сообщения
204
Реакции
108
Неа, главное зачем?
Просто как-то, не помню кто, правил плагин и сокращал запись до такой:
C-подобный:
GetClientName(iClient, szQuery, MAX_NAME_LENGTH);
g_hDatabase.Escape(szQuery, szName, sizeof(szName)); // Экранируем запрещенные символы в имени
Но в данной ситуации это вроде не работает
 

Palonez

бб братки
Сообщения
3,035
Реакции
1,837
Просто как-то, не помню кто, правил плагин и сокращал запись до такой:
C-подобный:
GetClientName(iClient, szQuery, MAX_NAME_LENGTH);
g_hDatabase.Escape(szQuery, szName, sizeof(szName)); // Экранируем запрещенные символы в имени
Но в данной ситуации это вроде не работает
В твоем случае, видимо расчет идет на кириллицу в содержании экранирования, которая хавает в 2 раза больше, но скорее всего я не прав
 
Последнее редактирование:

0-BuTaJIuK-0

Участник
Сообщения
235
Реакции
57
Для получения hammerid:
C-подобный:
int                    GetEntProp(entity, Prop_Data, "m_iHammerID");
Выполняется при спавне любой энтити на карте:
C-подобный:
public void OnEntityCreated(int iEntity, const char[] sClassname)
Благодарствую, снимаю шляпу за хук оружия Hammera.

Итого:

C++:
#include <sourcemod>
#include <sdktools>
#include <sdkhooks>
#include <cstrike>

public OnPluginStart()
{
    for(int i = 1; i <= MaxClients; i++)
    {
        if(IsClientInGame(i))
        {
            OnClientPutInServer(i); // На случай если плагин был перезагружен
        }
    }
}

public OnClientPutInServer(client)
{
    if(IsFakeClient(client)) return;
    SDKHook(client, SDKHook_WeaponEquip, OnWeaponEquip); // подбирает любое оружие
}

public Action OnWeaponEquip(int client, int weapon)
{
    PrintToChat(client, "Equip %i", GetEntProp(weapon, Prop_Data, "m_iHammerID")) // Проверочка на id хамера
    if(GetEntProp(weapon, Prop_Data, "m_iHammerID")>0)
    {
        static char cls[32];
           GetEntityClassname(weapon, cls, sizeof cls)
        AcceptEntityInput(weapon, "Kill")
        GivePlayerItem(client, cls)
    }

}

Но, плагин убивает и даёт пушку настолько быстро, что выдает и после этого, пушка которая выдаётся, выпадает, словно в инвентаре что-то есть)
C++:
AcceptEntityInput(weapon, "Kill")
//Между ними пауза нужна
GivePlayerItem(client, cls)

Не хотел на таймер садить, но видимо придётся на 0.1сек, что-то в духе этого.
Но будет другой баг, когда ты стоишь на другом weapon, то он будет его подбирать.
 

Grey83

не пишу плагины с весны 2022
Сообщения
8,520
Реакции
4,979
словно в инвентаре что-то есть
просто сначала нуно делать RemovePlayerItem(client, weapon); и только потом AcceptEntityInput(weapon, "Kill");
Сообщения автоматически склеены:

Ну или возвращать Plugin_Handled, раз уж ты хукаешь SDKHook_WeaponEquip. Ну а для прочего оружия возвращать Plugin_Continue.
Вот как-то так:
C-подобный:
#include <sdkhooks>
#include <sdktools_entinput>
#include <sdktools_functions>

public OnPluginStart()
{
    for(int i = 1; i <= MaxClients; i++) if(IsClientInGame(i)) OnClientPutInServer(i);
}

public OnClientPutInServer(client)
{
    if(!IsFakeClient(client)) SDKHook(client, SDKHook_WeaponEquip, OnWeaponEquip);
}

public Action OnWeaponEquip(int client, int weapon)
{
    static int id;
    id = GetEntProp(weapon, Prop_Data, "m_iHammerID");
    PrintToChat(client, "Equip %i", id) // Проверочка на id хамера
    if(id > 0)
    {
        static char cls[32];
        GetEntityClassname(weapon, cls, sizeof cls);
        AcceptEntityInput(weapon, "Kill");
        GivePlayerItem(client, cls);
        return Plugin_Handled;
    }

    return Plugin_Continue;
}
 
Последнее редактирование:

0-BuTaJIuK-0

Участник
Сообщения
235
Реакции
57
Ну или возвращать Plugin_Handled, раз уж ты хукаешь SDKHook_WeaponEquip. Ну а для прочего оружия возвращать Plugin_Continue.
Благодарю. Всё отлично работает, НО...
Добавил:
C++:
static char cls[32];
GetEntityClassname(weapon, cls, sizeof cls)
PrintToChat(client, "Equip %s", cls)

Таким образом: хукаем подбор оружия, проверяем из хаммера ли, а дальше выгружаем имя оружия.
Так вот, выгрузка имени не учитывает оружие с глушителем, например: берём M4A1-S, а в плагине воспринимается как M4A1 и выдаёт M4A1. Точно так-же с USP и MP7

Нашел какой-то параметр, GetEntProp(iWeapon, Prop_Send, "m_iItemDefinitionIndex"))
 

Вложения

  • изображение_2022-10-13_135021028.png
    изображение_2022-10-13_135021028.png
    916.9 КБ · Просмотры: 52
Последнее редактирование:

0-BuTaJIuK-0

Участник
Сообщения
235
Реакции
57
Давненько уже не писал код, подскажите, как лучше оптимизировать включение и отключение по квару?
Посадить на старт раунда?

C++:
#include <sourcemod>
#include <sdktools>
#include <sdkhooks>
#include <cstrike>
#include <sdktools_entinput>
#include <sdktools_functions>

new Handle:Enabled

public void OnPluginStart()
{
    Enabled = CreateConVar("fix_arena", "0", "Enbale/Disable fix on arena maps", 0, true, 0.0, true, 1.0);

    HookEvent("player_spawn", OnPlayerSpawn);
    for(int i = 1; i <= MaxClients; i++)
    {
        if(IsClientInGame(i))
        {
            OnClientPutInServer(i); // На случай если плагин был перезагружен
        }
    }
}

public OnClientPutInServer(client)
{
    if(IsFakeClient(client)) return;
    SDKHook(client, SDKHook_WeaponEquip, OnWeaponEquip); // подбирает любое оружие
}

public Action OnWeaponEquip(int client, int weapon)
{
    if(GetConVarInt(Enabled))
    {
        //code
        return Plugin_Handled;
    }
    return Plugin_Continue;
}

public Action:OnPlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast)
{
    if(GetConVarInt(Enabled))
    {
        //code
    }
}
 

Nekro

Терра инкогнита
Сообщения
4,025
Реакции
2,260
Давненько уже не писал код, подскажите, как лучше оптимизировать включение и отключение по квару?
Посадить на старт раунда?

C++:
#include <sourcemod>
#include <sdktools>
#include <sdkhooks>
#include <cstrike>
#include <sdktools_entinput>
#include <sdktools_functions>

new Handle:Enabled

public void OnPluginStart()
{
    Enabled = CreateConVar("fix_arena", "0", "Enbale/Disable fix on arena maps", 0, true, 0.0, true, 1.0);

    HookEvent("player_spawn", OnPlayerSpawn);
    for(int i = 1; i <= MaxClients; i++)
    {
        if(IsClientInGame(i))
        {
            OnClientPutInServer(i); // На случай если плагин был перезагружен
        }
    }
}

public OnClientPutInServer(client)
{
    if(IsFakeClient(client)) return;
    SDKHook(client, SDKHook_WeaponEquip, OnWeaponEquip); // подбирает любое оружие
}

public Action OnWeaponEquip(int client, int weapon)
{
    if(GetConVarInt(Enabled))
    {
        //code
        return Plugin_Handled;
    }
    return Plugin_Continue;
}

public Action:OnPlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast)
{
    if(GetConVarInt(Enabled))
    {
        //code
    }
}
м?
C#:
#include <sdkhooks>

ConVar
    cvEnable;

public void OnPluginStart()
{
    cvEnable = CreateConVar("fix_arena", "0", "Enbale/Disable fix on arena maps", 0, true, 0.0, true, 1.0);

    HookEvent("player_spawn", OnPlayerSpawn);
    
    for(int i = 1; i <= MaxClients; i++) if(IsClientInGame(i)) OnClientPutInServer(i);
}

public void OnClientPutInServer(int client)
{
    if(!IsFakeClient(client))
        SDKHook(client, SDKHook_WeaponEquip, OnWeaponEquip);        // подбирает любое оружие
}

public Action OnWeaponEquip(int client, int weapon)
{
    if(cvEnable.BoolValue)
    {
        //code
        return Plugin_Handled;
    }
    return Plugin_Continue;
}

public Action OnPlayerSpawn(Handle hEvent, const char[] sName, bool dontBroadcast)
{
    if(cvEnable.BoolValue)
    {
        //code
    }
}

К стати говоря не очень понял вопроса, что там оптимизировать та? Код пустой
 

Nekro

Терра инкогнита
Сообщения
4,025
Реакции
2,260
Я имел ввиду, что бы циклы не выполнялись, когда cvar = 0. Просто в пустоту нагрузка, или и так норм
Чуть поправил выше для нового синтаксиса.
А какие циклы та? Там только SDKHook_WeaponEquip идёт, да и пусть
 

Grey83

не пишу плагины с весны 2022
Сообщения
8,520
Реакции
4,979
как лучше оптимизировать включение и отключение по квару?
как-то так:
#include <sdkhooks>
#include <sdktools_entinput>
#include <sdktools_functions>

bool bEnable;

public OnPluginStart()
{
    ConVar cvar = CreateConVar("sm_wpnfix_enable", "1", _, _, true, _, true, 1.0);
    cvar.AddChangeHook(CVarChange);
    CVarChange(cvar, NULL_STRING, NULL_STRING);
}

public void CVarChange(ConVar cvar, const char[] oldValue, const char[] newValue)
{
    static bool hooked;
    if(hooked == (bEnable = cvar.BoolValue)) return;

    if((hooked = !hooked))
    {
        for(int i = 1; i <= MaxClients; i++) if(IsValidPlayer(i)) SDKHook(i, SDKHook_WeaponEquip, OnWeaponEquip);
        HookEvent("player_spawn", Event_Spawn);
    }
    else
    {
        for(int i = 1; i <= MaxClients; i++) if(IsValidPlayer(i)) SDKUnhook(i, SDKHook_WeaponEquip, OnWeaponEquip);
        UnhookEvent("player_spawn", Event_Spawn);
    }
}

public void OnClientPutInServer(int client)
{
    if(bEnable && !IsFakeClient(client)) SDKHook(client, SDKHook_WeaponEquip, OnWeaponEquip);
}

public Action OnWeaponEquip(int client, int weapon)
{
    static int id;
    id = GetEntProp(weapon, Prop_Data, "m_iHammerID");
    PrintToChat(client, "Equip %i", id) // Проверочка на id хамера
    if(id > 0)
    {
        static char cls[32];
        GetEntityClassname(weapon, cls, sizeof cls);
        AcceptEntityInput(weapon, "Kill");
        GivePlayerItem(client, cls);
        return Plugin_Handled;
    }

    return Plugin_Continue;
}

public void Event_Spawn(Event event, const char[] name, bool dontBroadcast)
{
    int client = GetClientOfUserId(event.GetInt("userid"));
    //code
}

stock bool IsValidPlayer(int client)
{
    return IsClientInGame(client) && !IsFakeClient(client);
}
 
Последнее редактирование:
Сверху Снизу