Mysql Нужен пример подключения

Тема в разделе "Программирование / Скриптинг", создана пользователем alexfyodrv, 23 сен 2016.

  1. alexfyodrv

    alexfyodrv

    Сообщения:
    24
    Симпатии:
    0
    Здравствуйте. Обращаюсь к более опытным скриптерам, пожалуйста, напишите пример подключения к базе данных. Есть желание написать простую статистику и личный кабинет (PHP хорошо понимаю и смогу сделать вполне нормальный аккаунт и админку), плагин очень простой и в двух словах, что мне нужно для начала

    stats.sp
    1. Подключение к бд
    2. Добавление игрока через INSERT INTO при подключении
    3. Пример одного события (например игрок кого-то убил) сделать UPDATE и добавить ему 1 килл.
    4. При отключении игрока сохранить его статистику.

    Далее я буду дорабатывать плагин и сделаю к нему аккаунт игрока с возможностью добавления поинтов, киллов через админку. Ну и выложу его в этой теме, буду рад если кто то установит к себе на сервер и будет пользоваться.
     
  2. yand3xmail

    yand3xmail Read Only

    Сообщения:
    16
    Симпатии:
    1
    Код:
    #pragma semicolon 1
    #pragma newdecls required
    Database g_db; bool started;
    
    int gPlayerCoin[MAXPLAYERS + 1];
    
    #define PREFIX "[Тест]"
    
    public void OnPluginStart() {
        ConnectDatabase();
     
        RegConsoleCmd("sm_coin", sm_coin);
    }
    
    public Action sm_coin(int client, int args) {
        if (client && IsClientInGame(client)) {
         
            if (g_db == null || !DB_IsStarted()) {
                ReplyToCommand(client, "\x04%s \x01Нет соединения с базой данных, сообщите на форум", PREFIX);
                return Plugin_Handled;
            }
    
            gPlayerCoin[client]++;    // +1 монетка
            DB_SaveClientStats(client);    // сохраняем данные игрока
            ReplyToCommand(client, "Монеток: %i", gPlayerCoin[client]);
        }
        return Plugin_Handled;
    }
    
    void ConnectDatabase() {
        if (g_db != null) return;
        if (SQL_CheckConfig("test_db")) Database.Connect(DB_Connect, "test_db", 1);        // подключение к базе данных mysql
    }
    
    public void DB_Connect(Database db, const char[] error, any data) {
        g_db = db;
    
        switch (g_db) {
            case null: {
                LogError("[ERROR] DB_Connect: %s", error);
                CreateTimer(10.0, DB_ReconnectTimer);
                return;
            }
        }
    
        if (error[0]) LogError("[ERROR] DB_Connect %d: %s", data, error);
    
        g_db.SetCharset("utf8");
    
        DB_CreateTables(g_db);
    }
    
    public Action DB_ReconnectTimer(Handle timer) {
        switch (g_db) {
            case null: ConnectDatabase();
        }
    }
    
    void DB_CreateTables(Database db) {
        char query[512];
        FormatEx(query, sizeof(query), "CREATE TABLE IF NOT EXISTS `test_players` (\
                              `id` int(5) NOT NULL AUTO_INCREMENT,\
                              `auth` varchar(22) NOT NULL,\
                              `coin` int(12) NOT NULL,\
                              PRIMARY KEY (`id`), \
                                UNIQUE KEY `auth` (`auth`) \
                            ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;");
    
        db.Query(DB_PlayersTable, query, 1, DBPrio_High);
    }
    
    public void DB_PlayersTable(Database db, DBResultSet results, const char[] error, any data) {
        if (error[0]) {
            LogError("[ERROR] DB_PlayersTable %d: %s", data, error);
            delete g_db;
            g_db = null;
            CreateTimer(10.0, DB_ReconnectTimer);
            return;
        }
    
        switch (data) {
            case 1: DB_Start();
        }
    }
    
    void DB_Start() {
        if (!DB_IsStarted()) {
            started = true;
    
            for (int i = 1; i <= MaxClients; i++) {
                if (IsClientInGame(i)) OnClientPutInServer(i);
            }
        }
    }
    
    stock bool DB_IsStarted() {
        return started;
    }
    
    public void OnClientPutInServer(int client) {
        if (!DB_IsStarted()) return;
     
        DB_CheckPlayer(client);    // загружаю информацию об игроке
    }
    
    void DB_CheckPlayer(int client, DBPriority prio = DBPrio_Normal) {
        if (g_db == null || !DB_IsStarted()) {
            LogError("[IPB - Warnings] DB_CheckPlayer: g_db = (%d) or bonus %s", g_db, DB_IsStarted() ? "started" : "not started");
            return;
        }
         
        char query[512], auth[32];
        Client_SteamID(client, auth, sizeof(auth));
        FormatEx(query, sizeof(query), "SELECT `coin` FROM `test_players` WHERE auth = '%s';", auth);     // извлекаем coin из test_players где auth
        g_db.Query(DB_CheckPlayer_Select, query, client, prio);
    }
    
    public void DB_CheckPlayer_Select(Database db, DBResultSet results, const char[] error, any data) {
        if (!IsClientInGame(data)) return;
     
        if (results.HasResults && results.FetchRow()) {
            gPlayerCoin[data] = results.FetchInt(0);
        } else {
            char auth[32], query[512];
            Client_SteamID(data, auth, sizeof(auth));
            FormatEx(query, sizeof(query), "INSERT INTO `test_players` (`auth`, `coin`) VALUES ('%s', '%d');", auth, gPlayerCoin[data] = 0);
         
            DB_TQueryEx(query, _, 1);
            DB_CheckPlayer(data);
        }
    }
    
    stock void DB_TQueryEx(const char[] query, DBPriority prio = DBPrio_Normal, any data = 0) {
        if (g_db == null || !DB_IsStarted()) {
            LogError("[IPB - Warnings] (data %d) DB_TQueryEx: g_db = (%d) or bonus %s", data, g_db, DB_IsStarted() ? "started" : "not started");
            return;
        }
        g_db.Query(DB_ErrorCheck, query, data, prio);
    }
    
    public void DB_ErrorCheck(Database db, DBResultSet results, const char[] error, any data) {
        if (error[0]) LogError("DB_ErrorCheck (data %d): %s", data, error);
    }
    
    void DB_SaveClientStats(int client, DBPriority prio = DBPrio_Normal) {
        if (!IsValidPlayer(client)) return;
     
        char query[512], auth[32];
        Client_SteamID(client, auth, sizeof(auth));
        FormatEx(query, sizeof(query), "UPDATE `test_players` SET `coin` = %d WHERE `auth` = '%s';", gPlayerCoin[client], auth);    // обновляем данные игрока
    
        DB_TQueryEx(query, prio, 1);
    }
    
    public bool Client_SteamID(int client, char[] steam, int maxlen) {
        if (IsClientInGame(client)) {
            return view_as<bool>(GetClientAuthId(client, AuthId_Steam2, steam, maxlen));
        }
        return false;
    }
    
    stock bool IsValidPlayer(int client){
        if (0 < client <= MaxClients && IsClientInGame(client)) return true;
        else return false;
    }
    Оффтоп
     
    alexfyodrv нравится это.
  3. R1KO

    R1KO Супер-модератор

    Сообщения:
    5.972
    Симпатии:
    2.977
    • чем if не угодил?
    • в Database.Connect 1 не нужно передавать
    • при создании таблицы нужно делать LockDatabase, а после UnlockDatabase
    • У тебя в таблице есть `id` int(5) NOT NULL AUTO_INCREMENT, а ты все ровно работаешь со стимом. Он нужен только 1 раз чтобы получить id
    • ну и еще много лишнего
     
  4. yand3xmail

    yand3xmail Read Only

    Сообщения:
    16
    Симпатии:
    1
    @R1KO, и что? я не слушаю недокодеров.
     
  5. R1KO

    R1KO Супер-модератор

    Сообщения:
    5.972
    Симпатии:
    2.977
    skolobes, teran, AlmazON и ещё 1-му нравится это.
  6. alexfyodrv

    alexfyodrv

    Сообщения:
    24
    Симпатии:
    0
    Спасибо, это отличный пример. RIKO если сможете добавьте блокировку и разблокировку таблиц я так думаю это критически важно и могут возникать ошибки. yand3xmail буду благодарен за помощь с вашим кодом. Для начала мне нужно удалить всё лишнее из вашего кода и создать таблицу, обязательно mysql с полями user, steamid points, kills, deaths при подключении игрока добавлять его в эту таблицу строкой INSERT INTO players (user, steamid, points, kills, deaths) VALUES ('user','steamid','0','0','0'); Если игрок уже есть в таблице то ничего делать не нужно. Далее нужно создать хотя бы 1 event (чтобы я понял как доставать данные игрока из базы). Для примера игрок убит, нужно достать строку в виде массива и вывести в чат PrintToChat("%N (%d поинтов) убил игрока %N (%d поинтов)", attacker, attacker_points, victim, victim_points); На этом я думаю всё для начала нужна основа плагина, далее уже можно доделать по необходимости.
     
  7. yand3xmail

    yand3xmail Read Only

    Сообщения:
    16
    Симпатии:
    1
    Оффтоп
    LockDatabase не обязательно юзать, я не видел чтобы на новом синтаксисе кто то его использовал. Это осталось на старом.
     
  8. R1KO

    R1KO Супер-модератор

    Сообщения:
    5.972
    Симпатии:
    2.977
    а какое отношение имеет синтаксис см к работе СУБД ?
     
  9. alexfyodrv

    alexfyodrv

    Сообщения:
    24
    Симпатии:
    0
    Steam id игрока - client id по которому будет идентифицироваться игрок, по нему и будет происходить выборка из базы. У вас в примере он называется auth предполагаю что хранить его нужно в типе varchar только вот длину его точную не знаю.
     
  10. yand3xmail

    yand3xmail Read Only

    Сообщения:
    16
    Симпатии:
    1
    @alexfyodrv, я не про это. я о том что кинь свой стим айди(профиль там и обсудим(стим)), там быстрее получиться склепать тебе статистику, с SQL_LockDatabase если боишься что могут быть ошибки. Всегда использовал без lockdatabase пока еще ни кто не жаловался..
     
  11. R1KO

    R1KO Супер-модератор

    Сообщения:
    5.972
    Симпатии:
    2.977
    @alexfyodrv,
    PHP:
    #pragma semicolon 1

    #include <sourcemod>

    #pragma newdecls required

    Database        g_hDatabase;
    int                g_iClientID[MAXPLAYERS+1];
    int                g_iKills[MAXPLAYERS+1];
    int                g_iDeaths[MAXPLAYERS+1];
    int                g_iPoints[MAXPLAYERS+1];

    public 
    void OnPluginStart()
    {
       if(
    SQL_CheckConfig("players"))
        {
            
    Database.Connect(GotDatabase"players");
        }
        else
        {
            
    SetFailState("Не удалось найти секцию \"players\" в databases.cfg");
        }

        
    HookEvent("player_death"Event_PlayerDeath);
    }


    public 
    void GotDatabase(Database dbchar[] sErrorany data)
    {
        if (
    db == null)
        {
            
    SetFailState("Не удалось подключиться к базе: %s"sError);
        }
        else
        {
            
    g_hDatabase db;
            
    CreateTables();
        }
    }

    void CreateTables()
    {
        
    SQL_LockDatabase(g_hDatabase);
        
    g_hDatabase.Query(SQL_Callback_CheckError,    "CREATE TABLE IF NOT EXISTS `players` (\
                                                                    `id` INT NOT NULL AUTO_INCREMENT,\
                                                                    `steamid` VARCHAR(32) NOT NULL,\
                                                                    `user` VARCHAR(32) NOT NULL,\
                                                                    `points` INT UNSIGNED NOT NULL default 0,\
                                                                    `deaths` INT UNSIGNED NOT NULL default 0,\
                                                                    `kills` INT UNSIGNED NOT NULL default 0,\
                                                                    PRIMARY KEY (`id`)\
                                                                    ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci AUTO_INCREMENT=1;"
    );
        
    SQL_UnlockDatabase(g_hDatabase);

        
    g_hDatabase.SetCharset("utf8");
    }

    public 
    void SQL_Callback_CheckError(Database hDatabaseDBResultSet results, const char[] sErrorany data)
    {
        if(
    sError[0])
        {
            
    LogError("SQL_Callback_CheckError: %s"sError);
        }
    }

    public 
    void OnClientPostAdminCheck(int iClient)
    {
        if(
    IsFakeClient(iClient) == false)
        {
            
    char sQuery[256], sAuth[32];
            
    GetClientAuthId(iClientAuthId_EnginesAuthsizeof(sAuth), true);
            
    FormatEx(sQuerysizeof(sQuery), "SELECT `id`, `points`, `deaths`, `kills` FROM `players` WHERE `steamid` = '%s' LIMIT 1;"sAuth);
            
    g_hDatabase.Query(SQL_Callback_SearchClientsQueryGetClientUserId(iClient));
        }
    }

    public 
    void SQL_Callback_SearchClient(Database hDatabaseDBResultSet results, const char[] sErrorany UserID)
    {
        if(
    sError[0])
        {
            
    LogError("SQL_Callback_SearchClient: %s"sError);
            return;
        }

        
    int iClient GetClientOfUserId(UserID);
        if(
    iClient)
        {
            if(
    results.FetchRow())    // Игрок есть в базе
            
    {
                
    g_iClientID[iClient] = results.FetchInt(0);
                
    g_iPoints[iClient] = results.FetchInt(1);
                
    g_iDeaths[iClient] = results.FetchInt(2);
                
    g_iKills[iClient] = results.FetchInt(3);
            }
            else    
    // Игрока нет в базе
            
    {
                
    char sQuery[256], sAuth[32], sName[MAX_NAME_LENGTH*2+1];
                
    GetClientAuthId(iClientAuthId_EnginesAuthsizeof(sAuth), true);
                
    GetClientName(iClientsQueryMAX_NAME_LENGTH);
                
    g_hDatabase.Escape(sQuerysNamesizeof(sName));
                
    FormatEx(sQuerysizeof(sQuery), "INSERT INTO `players` (`steamid`, `user`) VALUES ('%s', '%s');"sAuthsName);
                
    g_hDatabase.Query(SQL_Callback_CreateClientsQueryGetClientUserId(iClient));
            }
        }
    }

    public 
    void SQL_Callback_CreateClient(Database hDatabaseDBResultSet results, const char[] sErrorany UserID)
    {
        if(
    sError[0])
        {
            
    LogError("SQL_Callback_CreateClient: %s"sError);
            return;
        }

        
    int iClient GetClientOfUserId(UserID);
        if(
    iClient)
        {
            
    g_iClientID[iClient] = results.InsertId;
        }
    }

    public 
    void OnClientDisconnect(int iClient)
    {
        
    g_iClientID[iClient] = 0;
        
    g_iPoints[iClient] = 0;
        
    g_iDeaths[iClient] = 0;
        
    g_iKills[iClient] = 0;
    }

    public 
    void Event_PlayerDeath(Event hEvent, const char[] sEventNamebool bDontBroadcast)
    {
        
    int iClient GetClientOfUserId(hEvent.GetInt("userid"));

        
    char sQuery[256];
        
    FormatEx(sQuerysizeof(sQuery), "UPDATE `players` SET `deaths` = %i WHERE `id` = '%i';", ++g_iDeaths[iClient], g_iClientID[iClient]);
        
    g_hDatabase.Query(SQL_Callback_CheckErrorsQuery);

        
    int iAttacker GetClientOfUserId(hEvent.GetInt("attacker"));
        if(
    iAttacker)
        {
            
    FormatEx(sQuerysizeof(sQuery), "UPDATE `players` SET `kills` = %i WHERE `id` = '%i';", ++g_iKills[iAttacker], g_iClientID[iAttacker]);
            
    g_hDatabase.Query(SQL_Callback_CheckErrorsQuery);
        }
    }

    Но оптимальнее сделать сохранение при выходе.
     
    Последнее редактирование: 23 сен 2016
    alexfyodrv нравится это.
  12. alexfyodrv

    alexfyodrv

    Сообщения:
    24
    Симпатии:
    0
    RIKO мне тип varchar (steamid) тоже через Int вытягивать?
    g_iClientID[iClient] = results.FetchInt(0);

    И ещё такой вопрос мне нужно получить данные убийцы в Player_death как это сделать? Мне заново обращаться к базе вот так же (ну только ид аттакера) или это можно как то зациклить и передавать параметром ид кого нужно?
    char sQuery[256], sAuth[32], sName[MAX_NAME_LENGTH*2+1];
    GetClientAuthId(iClient, AuthId_Engine, sAuth, sizeof(sAuth), true);
    GetClientName(iClient, sQuery, MAX_NAME_LENGTH);
    g_hDatabase.Escape(sQuery, sName, sizeof(sName));
    FormatEx(sQuery, sizeof(sQuery), "INSERT INTO `players` (`steamid`, `user`) VALUES ('%s', '%s');", sAuth, sName);
    g_hDatabase.Query(SQL_Callback_CreateClient, sQuery, GetClientUserId(iClient));
     
    Последнее редактирование: 23 сен 2016
  13. R1KO

    R1KO Супер-модератор

    Сообщения:
    5.972
    Симпатии:
    2.977
    @alexfyodrv, почему через int ? FetchString
    --- Добавлено позже ---
    @alexfyodrv, ну если у тебя статистика то лучше храни всё в плагине, а из базой работай только при входе/выходе. Так запросов в базу будет меньше и не надо будет в неё лезть каждый раз чтобы что-то получить.
     
    Последнее редактирование: 23 сен 2016
    alexfyodrv нравится это.
  14. alexfyodrv

    alexfyodrv

    Сообщения:
    24
    Симпатии:
    0
    На сервере 64 игрока к примеру я же не буду хранить все их данные сразу, тем более если они изменяются и при следующем получении поинтов они будут отличаться и attacker может быть кто угодно заранее неизвестно. Мне нужно при убийстве игрока показать вас убил %N у него %d поинтов, поэтому нужно получить steamid убийцы и сделать выборку по нему из базы. Возможно я не правильно понимаю как это лучше реализовать. Посоветуйте как бы вы сделали.

    Как получить steamid игрока если у меня есть только его userid? Это данная строка?
    GetClientAuthId(iClient, AuthId_Engine, sAuth, sizeof(sAuth), true);
     
  15. R1KO

    R1KO Супер-модератор

    Сообщения:
    5.972
    Симпатии:
    2.977
    Почему не будешь хранить? В этом нет ничего страшного, тем более информации не так много.
    Следуй такому алгоритму (на примере убийств:
    1. Игрок вошел - получил данные о нем и хранишь их в плагине (например в переменную g_iKills)
    2. Все изменения производишь с переменными плагина (с переменной g_iKills)
    3. Игрок вышел - сохраняешь новую информацию о нем в базу.

    PHP:
    public void Event_PlayerDeath(Event hEvent, const char[] sEventNamebool bDontBroadcast)
    {
        
    int iClient GetClientOfUserId(hEvent.GetInt("userid"));

        
    char sQuery[256];
        
    FormatEx(sQuerysizeof(sQuery), "UPDATE `players` SET `deaths` = %i WHERE `id` = '%i';", ++g_iDeaths[iClient], g_iClientID[iClient]);
        
    g_hDatabase.Query(SQL_Callback_CheckErrorsQuery);

        
    int iAttacker GetClientOfUserId(hEvent.GetInt("attacker"));
        if(
    iAttacker)
        {
            
    FormatEx(sQuerysizeof(sQuery), "UPDATE `players` SET `kills` = %i WHERE `id` = '%i';", ++g_iKills[iAttacker], g_iClientID[iAttacker]);
            
    g_hDatabase.Query(SQL_Callback_CheckErrorsQuery);
           
            
    PrintToChat(iClient"Вас убил %N у него %d поинтов"iAttackerg_iPoints[iAttacker]);
        }
    }
    В событие же передает индекс убийцы и жертвы
     
  16. alexfyodrv

    alexfyodrv

    Сообщения:
    24
    Симпатии:
    0
    Я сделал так как вы говорили, посмотрите все ли правильно? Компилятор находит одну ошибку на строке где я изменил FetchInt на FetchString

    PHP:
    #pragma semicolon 1

    #include <sourcemod>

    #pragma newdecls required

    Database        g_hDatabase;
    int             g_iClientID[MAXPLAYERS+1], g_iKills[MAXPLAYERS+1], g_iDeaths[MAXPLAYERS+1], g_iPoints[MAXPLAYERS+1], g_iManyKills[MAXPLAYERS+1];

    public 
    void OnPluginStart()
    {
        if(
    SQL_CheckConfig("players")) Database.Connect(GotDatabase"players");
        else 
    SetFailState("Не удалось найти секцию \"players\" в databases.cfg");

        
    HookEvent("player_death"Event_PlayerDeath);
    }


    public 
    void GotDatabase(Database dbchar[] sErrorany data)
    {
        if (
    db == null)
        {
            
    SetFailState("Не удалось подключиться к базе: %s"sError);
        }
        else
        {
            
    g_hDatabase db;
            
    CreateTables();
        }
    }

    void CreateTables()
    {
        
    SQL_LockDatabase(g_hDatabase);
        
    g_hDatabase.Query(SQL_Callback_CheckError,    "CREATE TABLE IF NOT EXISTS `players` (\
                                                                    `id` INT NOT NULL AUTO_INCREMENT,\
                                                                    `steamid` VARCHAR(32) NOT NULL,\
                                                                    `user` VARCHAR(32) NOT NULL,\
                                                                    `points` INT UNSIGNED NOT NULL default 0,\
                                                                    `deaths` INT UNSIGNED NOT NULL default 0,\
                                                                    `kills` INT UNSIGNED NOT NULL default 0,\
                                                                    PRIMARY KEY (`id`)\
                                                                    ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci AUTO_INCREMENT=1;"
    );
        
    SQL_UnlockDatabase(g_hDatabase);

        
    g_hDatabase.SetCharset("utf8");
    }

    public 
    void SQL_Callback_CheckError(Database hDatabaseDBResultSet results, const char[] sErrorany data)
    {
        if(
    sError[0])
        {
            
    LogError("SQL_Callback_CheckError: %s"sError);
        }
    }

    public 
    void OnClientPostAdminCheck(int iClient)
    {
        if(
    IsFakeClient(iClient) == false)
        {
            
    char sQuery[256], sAuth[32];
            
    GetClientAuthId(iClientAuthId_EnginesAuthsizeof(sAuth), true);
            
    FormatEx(sQuerysizeof(sQuery), "SELECT `id`, `points`, `deaths`, `kills` FROM `players` WHERE `steamid` = '%s' LIMIT 1;"sAuth);
            
    g_hDatabase.Query(SQL_Callback_SearchClientsQueryGetClientUserId(iClient));
        }
    }

    public 
    void SQL_Callback_SearchClient(Database hDatabaseDBResultSet results, const char[] sErrorany UserID)
    {
        if(
    sError[0])
        {
            
    LogError("SQL_Callback_SearchClient: %s"sError);
            return;
        }

        
    int iClient GetClientOfUserId(UserID);
        if(
    iClient)
        {
            if(
    results.FetchRow())    // Игрок есть в базе
            
    {
                
    g_iClientID[iClient] = results.FetchString();
                
    g_iPoints[iClient] = results.FetchInt(0);
                
    g_iDeaths[iClient] = results.FetchInt(1);
                
    g_iKills[iClient] = results.FetchInt(2);
            }
            else    
    // Игрока нет в базе
            
    {
                
    char sQuery[256], sAuth[32], sName[MAX_NAME_LENGTH*2+1];
                
    GetClientAuthId(iClientAuthId_EnginesAuthsizeof(sAuth), true);
                
    GetClientName(iClientsQueryMAX_NAME_LENGTH);
                
    g_hDatabase.Escape(sQuerysNamesizeof(sName));
                
    FormatEx(sQuerysizeof(sQuery), "INSERT INTO `players` (`steamid`, `user`) VALUES ('%s', '%s');"sAuthsName);
                
    g_hDatabase.Query(SQL_Callback_CreateClientsQueryGetClientUserId(iClient));
            }
        }
    }

    public 
    void SQL_Callback_CreateClient(Database hDatabaseDBResultSet results, const char[] sErrorany UserID)
    {
        if(
    sError[0])
        {
            
    LogError("SQL_Callback_CreateClient: %s"sError);
            return;
        }

        
    int iClient GetClientOfUserId(UserID);
        if(
    iClient)
        {
            
    g_iClientID[iClient] = results.InsertId;
        }
    }

    public 
    void OnClientDisconnect(int iClient)
    {
        
    g_iClientID[iClient],
        
    g_iPoints[iClient],
        
    g_iDeaths[iClient],
        
    g_iKills[iClient],
        
    g_iManyKills[iClient] = 0;

        
    char sQuery[256];
        
    FormatEx(sQuerysizeof(sQuery), "UPDATE `players` SET `points` = %i, `kills` = %i, `deaths` = %i WHERE `id` = '%i';"g_iPoints[iClient], g_iKills[iClient], g_iDeaths[iClient], g_iClientID[iClient]);
        
    g_hDatabase.Query(SQL_Callback_CheckErrorsQuery);
    }

    public 
    void Event_PlayerDeath(Event hEvent, const char[] sEventNamebool bDontBroadcast)
    {
        
    int iClient GetClientOfUserId(hEvent.GetInt("userid"));
        
    int iAttacker GetClientOfUserId(hEvent.GetInt("attacker"));
        
    int aPoints g_iPoints[iClient];
        
    int cPoints g_iPoints[iAttacker];

        
    int kill_pn 2;
        
    int death_pn 2;

        if(
    iClient && aPoints){
        
            
    int additional 0;
            
    int kills g_iManyKills[iClient];
        
            if(
    kills 1){
                
    additional kills 1;
                
    PrintToChat(iClient"Вы получили %d поинтов за %d убийств."additionalkills);
                
    g_iPoints[iClient] + additional;
            }
        
            ++
    g_iDeaths[iClient];
            
    g_iPoints[iClient] - death_pn;
            
    g_iManyKills[iClient] = 0;
            
    PrintToChat(iClient"Вас убил %N у него %d поинтов"iAttackeraPoints);
        }

        if(
    iAttacker && cPoints){
        
            
    /*
            addpoints - поинты за разницу в уровне (максимум 25)
            */
        
            
    int addpoints cPoints 100;
            if(
    addpoints 25addpoints 25;
        
            
    g_iPoints[iAttacker] + kill_pn addpoints;
            ++
    g_iKills[iAttacker];
            ++
    g_iManyKills[iClient];
            
    PrintToChat(iClient"Вы убили %N у него %d поинтов"iClientcPoints);
        }
    }


    У несколько вопросов:

    1. Как лучше сделать дополнительное сохранение статистики так как карта может сменится и данные игрока не сохраняться так как он не выходил с сервера.

    2. Как посчитать количество строк в базе чтобы показать позицию игрока в списке ну и получить его позицию в ранге.
    PHP:
    public Action ShowRank(int clientint args) {
        if (
    client && IsClientInGame(client)) {
         
            
    PrintToChatAll("%s %N позиция %d из %d игроков с %d поинтами, убийств %d, смертей %d."PREFIXclient11g_iPoints[client], g_iKills[client], g_iDeaths[client]);
        }
        return 
    Plugin_Handled;
    }
    3. Какой командой можно реализовать следующее, чтобы при написании rank выдавало ранг игрока в чате без ! перед ним. Сейчас так RegConsoleCmd("sm_rank", ShowRank);
     
    Последнее редактирование: 23 сен 2016
  17. R1KO

    R1KO Супер-модератор

    Сообщения:
    5.972
    Симпатии:
    2.977
    При смене карты вызывается OnClientDisconnect
    Количество строк:
    PHP:
    SELECT COUNT(*) FROM players;
    Чтобы без ! ловило надо ловить не команду, а сообщение в чате.

    А по твоему коду:
    1. PHP:
      g_iClientID[iClient] = results.FetchInt(0);
                  
      g_iPoints[iClient] = results.FetchInt(1);
                  
      g_iDeaths[iClient] = results.FetchInt(2);
                  
      g_iKills[iClient] = results.FetchInt(3);
      Смотри синтаксис FetchString.

      Нужно так:
      PHP:
      results.FetchString(0szBuffersizeof(szBuffer));
      И зачем id ты получаешь как строку если он int ?
      и номера не верные стоят. Верно так будет:
      PHP:
      g_iClientID[iClient] = results.FetchInt(0);
                  
      g_iPoints[iClient] = results.FetchInt(1);
                  
      g_iDeaths[iClient] = results.FetchInt(2);
                  
      g_iKills[iClient] = results.FetchInt(3);
    2. PHP:
      int aPoints g_iPoints[iClient];
          
      int cPoints g_iPoints[iAttacker];
      Зачем делать это если нужно работать сразу с g_iPoints[iAttacker] и g_iPoints[iClient]
    3. PHP:
      if(iClient && aPoints){
      Зачем 2 раза с разным кодом?
      и нужно проверять iAttacker != 0 ибо если он == 0 то игрока убил мир.
     
    666FoX666 нравится это.
  18. Primo

    Primo Где мои манеры

    Сообщения:
    1.190
    Симпатии:
    306
  19. alexfyodrv

    alexfyodrv

    Сообщения:
    24
    Симпатии:
    0
    RIKO у меня ошибка при подключении уже и локальную базу на openserver пробовал и базу с сервера не хочет подгружать плагин.
    PHP:
    L 09/24/2016 12:27:23SourceMod error session started
    L 09
    /24/2016 12:27:23Info (map "de_dust2") (file "errors_20160924.log")
    L 09/24/2016 12:27:23: [SMUnable to load plugin "stats.smx"Native "Database.Connect" was not found
     
    Последнее редактирование: 24 сен 2016
  20. R1KO

    R1KO Супер-модератор

    Сообщения:
    5.972
    Симпатии:
    2.977
    @alexfyodrv, см должен быть 1.7 или выше
     
    alexfyodrv нравится это.