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

alexfyodrv

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

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

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

yand3xmail

Участник
Сообщения
16
Реакции
1
C-подобный:
#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;
}
Оффтоп
 

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #3
  • switch (g_db) { case null: {
    чем if не угодил?
  • в Database.Connect 1 не нужно передавать
  • при создании таблицы нужно делать LockDatabase, а после UnlockDatabase
  • У тебя в таблице есть `id` int(5) NOT NULL AUTO_INCREMENT, а ты все ровно работаешь со стимом. Он нужен только 1 раз чтобы получить id
  • ну и еще много лишнего
 

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); На этом я думаю всё для начала нужна основа плагина, далее уже можно доделать по необходимости.
 

yand3xmail

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

alexfyodrv

Участник
Сообщения
24
Реакции
0
Оффтоп
LockDatabase не обязательно юзать, я не видел чтобы на новом синтаксисе кто то его использовал. Это осталось на старом.

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

yand3xmail

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

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #11
@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 db, char[] sError, any 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 hDatabase, DBResultSet results, const char[] sError, any 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(iClient, AuthId_Engine, sAuth, sizeof(sAuth), true);
        FormatEx(sQuery, sizeof(sQuery), "SELECT `id`, `points`, `deaths`, `kills` FROM `players` WHERE `steamid` = '%s' LIMIT 1;", sAuth);
        g_hDatabase.Query(SQL_Callback_SearchClient, sQuery, GetClientUserId(iClient));
    }
}

public void SQL_Callback_SearchClient(Database hDatabase, DBResultSet results, const char[] sError, any 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(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));
        }
    }
}

public void SQL_Callback_CreateClient(Database hDatabase, DBResultSet results, const char[] sError, any 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[] sEventName, bool bDontBroadcast)
{
    int iClient = GetClientOfUserId(hEvent.GetInt("userid"));

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

    int iAttacker = GetClientOfUserId(hEvent.GetInt("attacker"));
    if(iAttacker)
    {
        FormatEx(sQuery, sizeof(sQuery), "UPDATE `players` SET `kills` = %i WHERE `id` = '%i';", ++g_iKills[iAttacker], g_iClientID[iAttacker]);
        g_hDatabase.Query(SQL_Callback_CheckError, sQuery);
    }
}
Но оптимальнее сделать сохранение при выходе.
 
Последнее редактирование:

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));
 
Последнее редактирование:

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #13
@alexfyodrv, почему через int ? FetchString
--- Добавлено позже ---
@alexfyodrv, ну если у тебя статистика то лучше храни всё в плагине, а из базой работай только при входе/выходе. Так запросов в базу будет меньше и не надо будет в неё лезть каждый раз чтобы что-то получить.
 
Последнее редактирование:

alexfyodrv

Участник
Сообщения
24
Реакции
0
@alexfyodrv, почему через int ? FetchString
--- Добавлено позже ---
@alexfyodrv, ну если у тебя статистика то лучше храни всё в плагине, а из базой работай только при входе/выходе. Так запросов в базу будет меньше и не надо будет в неё лезть каждый раз чтобы что-то получить.

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

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

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #15
На сервере 64 игрока к примеру я же не буду хранить все их данные сразу, тем более если они изменяются и при следующем получении поинтов они будут отличаться и аттакер может быть кто угодно заранее неизвестно. Мне нужно при убийстве игрока показать вас убил %N у него %d поинтов, а вот убийца может быть кто угодно поэтому нужно получить steamid убийцы и сделать выборку по нему из базы. Возможно я не правильно понимаю как это лучше реализовать. Посоветуйте как бы вы сделали.
Почему не будешь хранить? В этом нет ничего страшного, тем более информации не так много.
Следуй такому алгоритму (на примере убийств:
  1. Игрок вошел - получил данные о нем и хранишь их в плагине (например в переменную g_iKills)
  2. Все изменения производишь с переменными плагина (с переменной g_iKills)
  3. Игрок вышел - сохраняешь новую информацию о нем в базу.

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

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

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

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 db, char[] sError, any 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 hDatabase, DBResultSet results, const char[] sError, any 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(iClient, AuthId_Engine, sAuth, sizeof(sAuth), true);
        FormatEx(sQuery, sizeof(sQuery), "SELECT `id`, `points`, `deaths`, `kills` FROM `players` WHERE `steamid` = '%s' LIMIT 1;", sAuth);
        g_hDatabase.Query(SQL_Callback_SearchClient, sQuery, GetClientUserId(iClient));
    }
}

public void SQL_Callback_SearchClient(Database hDatabase, DBResultSet results, const char[] sError, any 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(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));
        }
    }
}

public void SQL_Callback_CreateClient(Database hDatabase, DBResultSet results, const char[] sError, any 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(sQuery, sizeof(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_CheckError, sQuery);
}

public void Event_PlayerDeath(Event hEvent, const char[] sEventName, bool 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 убийств.", additional, kills);
            g_iPoints[iClient] + additional;
        }
    
        ++g_iDeaths[iClient];
        g_iPoints[iClient] - death_pn;
        g_iManyKills[iClient] = 0;
        PrintToChat(iClient, "Вас убил %N у него %d поинтов", iAttacker, aPoints);
    }

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

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

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

2. Как посчитать количество строк в базе чтобы показать позицию игрока в списке ну и получить его позицию в ранге.
PHP:
public Action ShowRank(int client, int args) {
    if (client && IsClientInGame(client)) {
     
        PrintToChatAll("%s %N позиция %d из %d игроков с %d поинтами, убийств %d, смертей %d.", PREFIX, client, 1, 1, g_iPoints[client], g_iKills[client], g_iDeaths[client]);
    }
    return Plugin_Handled;
}

3. Какой командой можно реализовать следующее, чтобы при написании rank выдавало ранг игрока в чате без ! перед ним. Сейчас так RegConsoleCmd("sm_rank", ShowRank);
 
Последнее редактирование:

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #17
Как лучше сделать дополнительное сохранение статистики так как карта может сменится и данные игрока не сохраняться так как он не выходил с сервера.
При смене карты вызывается OnClientDisconnect
Как посчитать количество строк в базе чтобы показать позицию игрока в списке ну и получить его позицию в ранге.
Количество строк:
PHP:
SELECT COUNT(*) FROM players;
Какой командой можно реализовать следующее, чтобы при написании rank выдавало ранг игрока в чате без ! перед ним. Сейчас так RegConsoleCmd("sm_rank", ShowRank);

Чтобы без ! ловило надо ловить не команду, а сообщение в чате.

А по твоему коду:
  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(0, szBuffer, sizeof(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 то игрока убил мир.
 

alexfyodrv

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