PDA

Просмотр полной версии : [CMD] /setskin [DC_CMD | (i)ZCMD | Pawn.CMD] [Поддержка MySQL R40+]



Kovshevoy
16.12.2019, 03:46
/setskin
Устанавливает скин игроку с возможностью выбора, постоянный или временный скин с поддержкой MySQL.

Зависимости:

Любой командный процессор имеющий синтаксис ZCMD [DC_CMD | iZCMD, Pawn.CMD (если будете использовать флаги)]
sscanf 2.8.2 и выше
MySQL R40+


Параметры:

targetid, modelid, is_tmp

targetid - ID игрока, которому будет изменятся скин
modelid - ID скина, который заменит нынешний скин (От 1 до 311, кроме 74. Если используется 0.3DL то еще и от 20000 до 30000)
is_tmp - необязательный параметр (по стандарту - 1), который обозначает постоянный скин (0) (с записью в бд) или временный (1) (без записи)



Код:

flags:setskin(/* Ваш флаг уровня администратора */);
/* Если не используете флаги - удалите строчку выше */
CMD:setskin(playerid, params[])
{
if(!/* переменная отвечающая за админку */)
return SendClientMessage(playerid, 0xFF0000FF, "Ошибка: {F6F6F6}Команда доступна только администратору.");

if(/* переменная отвечающая за админку */ < /* требуемый уровень админки для выполнения команды */)
return SendClientMessage(playerid, 0xFF0000FF, "Ошибка: {F6F6F6}Недостаточный уровень администратора, для использования команды.");

/* Если используете флаги - уберите выше обе проверки на админку и уровень администратора */
extract params -> new player:targetid, modelid, is_tmp = 1; else
return SendClientMessage(playerid, 0xFF9900FF, "Используйте: {F6F6F6}/setskin [playerid] [modelid] {временный (1)/постоянный (0)}");

if(targetid == INVALID_PLAYER_ID)
return SendClientMessage(playerid, 0xFF0000FF, "Ошибка: {F6F6F6}Неверный ID игрока.");

#if defined GetPlayerCustomSkin
if(!(1 <= modelid <= 311) || modelid == 74 || !(20_000 <= modelid <= 30_000))
return SendClientMessage(playerid, 0xFF0000FF, "Ошибка: {F6F6F6}Неверный ID скина. Диапазон: 1 - 311 или 20000 - 30000, кроме 74.");
#else
if(!(1 <= modelid <= 311) || modelid == 74)
return SendClientMessage(playerid, 0xFF0000FF, "Ошибка: {F6F6F6}Неверный ID скина. Диапазон: 1 - 311, кроме 74.");
#endif

new skin_modelid = /* измените на вашу переменную скина */;
skin_modelid = modelid;

if(!is_tmp)
{
#if !defined TABLE_ACCOUNTS
#define TABLE_ACCOUNTS "accounts" /* таблица с аккаунтами */
#endif

#if !defined COLUMN_SKIN
#define COLUMN_SKIN "skin" /* столбец отвечающий за скин */
#endif

#if !defined COLUMN_ID
#define COLUMN_ID "id" /* столбец отвечающий за ID игрока в базе */
#endif

static const save_skin_query[] = "UPDATE "TABLE_ACCOUNTS" SET "COLUMN_SKIN" = %d WHERE "COLUMN_ID" = %d";
new save_skin_str[sizeof(save_skin_query) + ((-2 * 2) + 3 + MAX_PLAYER_NAME) +1];

format
(
save_skin_str, sizeof(save_skin_str),
save_skin_query,
skin_modelid,
/* замените на свою переменную ID игрока, пример *PlayerInfo[playerid][pID]* */
);
mysql_query(/* переменная подключения MySQL */, save_skin_str, false);
}
SetPlayerSkin(playerid, skin_modelid);

new player_name[MAX_PLAYER_NAME +1];
GetPlayerName(targetid, player_name, sizeof(player_name));

static const set_skin[] = "Выполнено: {F6F6F6}Вы установили игроку {FF9900}%s[%d] {FFFF00}%s {F6F6F6}скин под номером {FF9900}%d{F6F6F6}.";
new str[sizeof(set_skin) + ((-2 * 4) + sizeof(player_name) + 4 + 10 + 3) +1];

format(str, sizeof(str), set_skin, player_name, targetid, is_tmp ? ("временный") : ("постоянный"), modelid);
SendClientMessage(playerid, 0x87CEEBFF, str);
return 1;
}


На случай, если скриншот не появился - ссылка (https://imgur.com/a/tn7ZApV)

https://i.imgur.com/vYk4cLG.png

20th century
16.12.2019, 17:42
offtop

Desulaid
16.12.2019, 21:48
От вызова IsPlayerConnected можно избавиться, так как у тебя есть sscanf.
За место format можно использоваться strcat, к тому же на форуме используют такую идею, что имя может быть иногда и все 24 символа, так как SetPlayerName позволит это сделать.
Лучше использовать для локальных переменных краткие названия.
На этапе препроцессинга как я помню, sizeof итак возвращает +1, так что в конце это делать не нужно (для ясности можно при использовании sizeof убрать минус, а в конце всей операции добавить плюс +1).
Семантика save_skin_str не очень ясна, я бы просто дал имя save_req(uest).
Твой способ форматирования кода выглядит глупо в момент автоподсчета строки и ее форматирования. Угадай почему (:

Kovshevoy
16.12.2019, 22:40
Твой способ форматирования кода выглядит глупо в момент автоподсчета строки и ее форматирования. Угадай почему (:


Подсказку в студию.

- - - Добавлено - - -



За место format можно использоваться strcat, к тому же на форуме используют такую идею, что имя может быть иногда и все 24 символа, так как SetPlayerName позволит это сделать.


У меня это учитывается и так)

- - - Добавлено - - -



От вызова IsPlayerConnected можно избавиться, так как у тебя есть sscanf.


Не знал, что sscanf чекает, исправил.

Desulaid
16.12.2019, 22:45
Подсказку в студию.

Хотя этот пункт слишком претенциозен, забудем)

Kovshevoy
16.12.2019, 22:47
Хотя этот пункт слишком претенциозен, забудем)

Все-равно интересно, выкладывай.

Desulaid
16.12.2019, 22:53
Все-равно интересно, выкладывай.

static const save_skin_query[] = "UPDATE "TABLE_ACCOUNTS" SET "COLUMN_SKIN" = %d WHERE "COLUMN_ID" = '%d' LIMIT 1";
static save_skin_str[sizeof(save_skin_query) + ((-2 * 2) + 3 + MAX_PLAYER_NAME) +1];

format
(
save_skin_str, sizeof(save_skin_str),
save_skin_query,
/* измените на вашу переменную скина */,
/* замените на свою переменную ID игрока, пример *PlayerInfo[playerid][pID]* */
);


Типа смотри как вылезла строка save_skin_query, format на ее фоне теряет свою компактность)

Kovshevoy
16.12.2019, 22:56
Типа смотри как вылезла строка save_skin_query, format на ее фоне теряет свою компактность)

Я тут с челиком одним, по фану РЛС для паблика оптимизируем и до ума доводим, так что у меня тут и пострашней вещи есть.
http://prntscr.com/qboqgd

execution
16.12.2019, 23:15
Вообще можно избавиться от создания локального массива player_name и использовать уже имеющийся:

static const set_skin[] = "{87CEEB}Выполнено: {F6F6F6}Вы установили игроку {FF9900}%s[%d] {FFFF00}%s {F6F6F6}скин под номером {FF9900}%d{F6F6F6}.";
static str[sizeof(set_skin) + ((-2 * 4) + MAX_PLAYER_NAME + 4 + 10 + 3) +1];

str = "";
GetPlayerName(player_id, str, sizeof(str));
format(str, sizeof(str), set_skin, str, player_id, parameter ? "временный" : "постоянный", modelid);

Немного не читабельно, но всё же

Kovshevoy
16.12.2019, 23:16
Вообще можно избавиться от создания локального массива player_name и использовать уже имеющийся:

static const set_skin[] = "{87CEEB}Выполнено: {F6F6F6}Вы установили игроку {FF9900}%s[%d] {FFFF00}%s {F6F6F6}скин под номером {FF9900}%d{F6F6F6}.";
static str[sizeof(set_skin) + ((-2 * 4) + MAX_PLAYER_NAME + 4 + 10 + 3) +1];

str = "";
GetPlayerName(player_id, str, sizeof(str));
format(str, sizeof(str), set_skin, str, player_id, parameter ? "временный" : "постоянный", modelid);

Немного не читабельно, но всё же

В своем моде я вообще не использую GetPlayerName, ибо у меня при входе берется ник игрока и хранится в переменной на протяжении всей игровой сессии.

DeimoS
17.12.2019, 12:50
Если уж решил такую вермишель ради одной строки делать (хотя, имхо, от такой реализации, в данном случае, больше вреда, чем пользы):
static const set_skin[] = "{87CEEB}Выполнено: {F6F6F6}Вы установили игроку {FF9900}%s[%d] {FFFF00}%s {F6F6F6}скин под номером {FF9900}%d{F6F6F6}.";
static str[sizeof(set_skin) + ((-2 * 4) + sizeof(player_name) + 4 + 10 + 3) +1];

format(str, sizeof(str), set_skin, player_name, player_id, parameter ? "временный" : "постоянный", modelid);
То и строки "временный"/"постоянный" вынес бы в static-массивы, чтоб сразу учитывать размер наибольшей строки в формуле для "str". Да и формула сейчас неправильная, ибо в 0.3DL ID добавленных скинов может быть длиной в 5 символов, а не 3.

Так же непонятно зачем тут функция SetPlayerSkinEx (у которой довольно сомнительные наименования параметров). Выносить код в отдельную функцию и потом использовать эту функцию всего один раз - сомнительная идея.

Ну и в запросе есть лишние кавычки + "LIMIT 1" там совершенно ни к чему, если условие запроса проходит по AI-полю.

Kovshevoy
17.12.2019, 18:29
Да и формула сейчас неправильная, ибо в 0.3DL ID добавленных скинов может быть длиной в 5 символов, а не 3.

0.3DL ветка недоступна для скачивания, соответственно, кому нужно - пусть сам добавляет проверку.

if(!(1 <= modelid <= 311) || modelid == 74 || !(20_000 <= modelid <= 30_000))
return SendClientMessage(playerid, -1, "{FF0000}Ошибка: {F6F6F6}Неверный ID скина. От 1 до 311, или от 20000 до 30000.");

А так оно по сути "вне закона".
Про использовании функции один раз. Я вот у себя в моде её использую не 1 раз, а гораздо больше, поэтому и вырезал от туда. Если кто-то желает отставить стандартную функу, то пусть использует:


/* переменная хранящая скин игрока */ = modelid;

if(!is_tmp)
SetPlayerSkin(playerid, /* переменная хранящая скин игрока */);
else
SetPlayerSkin(playerid, modelid);


- - - Добавлено - - -


Если уж решил такую вермишель ради одной строки делать (хотя, имхо, от такой реализации, в данном случае, больше вреда, чем пользы)

Как говорят мудрейшие - не нравится, сделай сам.
Меня всё полностью устраивает, я не гонюсь за идеалом. Меня устраивает такой стиль кода и устраивает подобная реализация.
Да только как я заметил практически большую часть юзеров которые кодят нестандартными (не п-ишными) методами, зачастую при виде схожего кода как предоставил я, начинает метать из стороны в сторону и все пытаются надоумить сделать лучше. Я нигде вроде не говорил, что это САМАЯ МЕНЕЕ ЗАТРАТНАЯ ПО ПАМЯТИ И МАКСИМАЛЬНО ОПТИМИЗИРОВАННАЯ КОМАНДА КОТОРУЮ ОБЯЗАН ИСПОЛЬЗОВАТЬ КАЖДЫЙ. Тем более, мы кодим на каком-то там павне и даже та реализация, которую предоставил я - уже более менее хороший вариант, нежели как все делают по стандарту.




То и строки "временный"/"постоянный" вынес бы в static-массивы, чтоб сразу учитывать размер наибольшей строки в формуле для "str".


Чуть позже изменю, окей.



Ну и в запросе есть лишние кавычки + "LIMIT 1" там совершенно ни к чему, если условие запроса проходит по AI-полю.


Тут соглашусь, тоже чуть позже подправлю, спасибо за замечания.

Daniel_Cortez
17.12.2019, 19:55
static const set_skin[] = "{87CEEB}Выполнено: {F6F6F6}Вы установили игроку {FF9900}%s[%d] {FFFF00}%s {F6F6F6}скин под номером {FF9900}%d{F6F6F6}.";
static str[sizeof(set_skin) + ((-2 * 4) + sizeof(player_name) + 4 + 10 + 3) +1];

1. В чём профит от объявления массива "str" с помощью static? (Нет, не "set_skin", а именно "str".)

2. Переменные с одинаковым названием ("playerid" и "player_id") - просто замечательная идея! На всякий случай я проверил код из 1-го поста, и вроде бы нигде эти переменные не перепутаны (акцент на "вроде бы"), но я всё же советовал бы задать переменной для целевого игрока более отличимое название (например, я для таких целей называю переменную "targetid").

3. Название переменной "parameter" совершенно не отражает сути. Я бы назвал такую переменную "is_temporary", "is_temp" или "istemp" (если назвать просто "temporary" или "temp"/"tmp", то читающий может подумать, что это переменная для хранения какого-то временного значения).

Kovshevoy
17.12.2019, 20:12
1. В чём профит от объявления массива "str" с помощью static? (Нет, не "set_skin", а именно "str".)

Мастурбирование на экономию памяти (или как говорят на п-и стэкодрочеры)


2. Переменные с одинаковым названием ("playerid" и "player_id") - просто замечательная идея! На всякий случай я проверил код из 1-го поста, и вроде бы нигде эти переменные не перепутаны (акцент на "вроде бы"), но я всё же советовал бы задать переменной для целевого игрока более отличимое название (например, я для таких целей называю переменную "targetid").

Да, тут согласен, изменю. И да, переменные нигде не перепутаны. Сменил на targetid, спасибо за замечание.


3. Название переменной "parameter" совершенно не отражает сути. Я бы назвал такую переменную "is_temporary", "is_temp" или "istemp" (если назвать просто "temporary" или "temp"/"tmp", то читающий может подумать, что это переменная для хранения какого-то временного значения).

Принято, комрад, так же соглашусь. Изменил.

DeimoS
17.12.2019, 21:22
0.3DL ветка недоступна для скачивания, соответственно, кому нужно - пусть сам добавляет проверку.

if(!(1 <= modelid <= 311) || modelid == 74 || !(20_000 <= modelid <= 30_000))
return SendClientMessage(playerid, -1, "{FF0000}Ошибка: {F6F6F6}Неверный ID скина. От 1 до 311, или от 20000 до 30000.");

А так оно по сути "вне закона".

Только, во-первых, её и так было довольно проблематично скачать, ибо Куй не писал о ней на сайте особо. Так что для 0.3DL ситуация с этим "запретом" не особо изменилась (разве что отключение мастер-листа чуть сильнее повлияло, но и то это не смертельно, ибо сервера, в любом случае, до этого жили только за счёт самораскрутки, в основном. Новых случайных игроков было минимум).
Во-вторых, на неё всё равно продолжают сидеть люди и продолжают появляться желающие открыть на ней сервер.


Про использовании функции один раз. Я вот у себя в моде её использую не 1 раз, а гораздо больше, поэтому и вырезал от туда. Если кто-то желает отставить стандартную функу, то пусть использует:

Я прекрасно понимаю, что это функция из твоего мода и ты её используешь часто. Но, повторюсь: зачем она тут? Уж мог бы приложить чуть больше усилий и скопировать код из функции прямо в команду перед публикацией. Тебе не сложно, а новичок, который наткнётся на твою тему, не создаст у себя дополнительную бесполезную для него функцию, которая ещё и может быть с уже занятым названием.

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



Как говорят мудрейшие - не нравится, сделай сам.
Меня всё полностью устраивает, я не гонюсь за идеалом. Меня устраивает такой стиль кода и устраивает подобная реализация.

Я-то сделаю, но зачем тогда твой код нужен на этом форуме? Если тебя всё устраивает в своём коде, то и оставь его при себе. Зачем публиковать?
А уж если решил опубликовать, то будь открытым к советам и критике, которые делаются не чтоб тебя обидеть, а чтоб тебе помочь (а заодно и тем, что решит твоим кодом воспользоваться).



Да только как я заметил практически большую часть юзеров которые кодят нестандартными (не п-ишными) методами, зачастую при виде схожего кода как предоставил я, начинает метать из стороны в сторону и все пытаются надоумить сделать лучше. Я нигде вроде не говорил, что это САМАЯ МЕНЕЕ ЗАТРАТНАЯ ПО ПАМЯТИ И МАКСИМАЛЬНО ОПТИМИЗИРОВАННАЯ КОМАНДА КОТОРУЮ ОБЯЗАН ИСПОЛЬЗОВАТЬ КАЖДЫЙ. Тем более, мы кодим на каком-то там павне и даже та реализация, которую предоставил я - уже более менее хороший вариант, нежели как все делают по стандарту.

Во-первых, странно свои косяки оправдывать другими людьми.
Во-вторых, речь не о том, что твой код какой-то там не такой в плане оптимизации (точнее, это менее приоритетный вопрос в данном случае). Речь о банальной логике, которая, в данном случае, напрочь отсутствует. Метод подсчёта, который ты используешь, хорош своей частичной автоматизацией. Но ты эту самую автоматизацию убиваешь, заставляя вручную подсчитывать размер двух строк, при том, что можно и подсчёт их размера автоматизировать.



Мастурбирование на экономию памяти (или как говорят на п-и стэкодрочеры)

Только этим ты никак память не экономишь. Скорее, ты её расходуешь ещё больше. Вот, почитай - http://pro-pawn.ru/showthread.php?16533-%D0%92%D0%BE%D0%BF%D1%80%D0%BE%D1%81-%D0%BF%D0%BE-Stack-heap-size&p=92930&viewfull=1#post92930

Kovshevoy
17.12.2019, 22:11
Только этим ты никак память не экономишь. Скорее, ты её расходуешь ещё больше памяти. Вот, почитай - http://pro-pawn.ru/showthread.php?16533-%D0%92%D0%BE%D0%BF%D1%80%D0%BE%D1%81-%D0%BF%D0%BE-Stack-heap-size&p=92930&viewfull=1#post92930

Я изучал большую часть твоим тем, где ты отвечаешь и подробно описываешь то или инное действие юзеров, ибо уважаю тебя как кодера и более чем уверен в твоем скилле, так что с данным топиком я знаком. И раз уж на то дело пошло, может ты тогда создашь топик с подробным описанием про стэк с приведением примеров и тестов? Просто переправлять на тему, где ты отвечаешь юзеру конкретно за глобальные массивы подсчета строк, хотя это косвенно относится к тебе - такой себе вариант.
А касаемо глобальных массивов я их не использую, ибо это ни что инное как ПСЕВДОоптимизация (учитывая даже то, что вроде на Стейдже, Гамбите и еще парочке довольно таки популярити проектов используют глобальный массив, опираясь на слитые оригинальные моды, я все равно не использую и ни в коем случае не рекомендую использовать глобальный массив таким образом, которым его используют юзеры).



Я-то сделаю, но зачем тогда твой код нужен на этом форуме? Если тебя всё устраивает в своём коде, то и оставь его при себе. Зачем публиковать?
А уж если решил опубликовать, то будь открытым к советам и критике, которые делаются не чтоб тебя обидеть, а чтоб тебе помочь (а заодно и тем, что решит твоим кодом воспользоваться).


По твоей логике на форумах можно лишь оставить тогда мануалы по созданию команд/систем/функций, но никак не выкладывать готовое, что могут использовать юзеры. Я вот не нашел ни на одном из форумов команду с требуемыми параметрами, которые нужны мне и поэтому написал её сам, и выложил, чтобы если какому-либо юзеру понадобилась данная команда - она уже тут есть, он может её спокойно взять и вставить в мод, причем из дополнительных костылей я только привел свою функцию SetPlayerPosEx, но да ладно, я её уже убрал из темы просто вставив код из неё непосредственно в команде.



Только, во-первых, её и так было довольно проблематично скачать, ибо Куй не писал о ней на сайте особо. Так что для 0.3DL ситуация с этим "запретом" не особо изменилась (разве что отключение мастер-листа чуть сильнее повлияло, но и то это не смертельно, ибо сервера, в любом случае, до этого жили только за счёт самораскрутки, в основном. Новых случайных игроков было минимум).
Во-вторых, на неё всё равно продолжают сидеть люди и продолжают появляться желающие открыть на ней сервер.

На официальном форуме удалены всевозможные топики и её не скачать с официального сайта. Сам клиент и сервер валяется на просторах интернета, но я не могу ручаться на то, что в этих версиях что-то не изменено. Можно скачать конечно с официального сайта Абсолюта, которые дорабатывают эту версию, но я тоже не могу ручаться, что в их файла нет вредоносного кода.
Если какому-либо из юзеров потребовалось бы использовать и скины для 0.3DL ветки, и он бы попросил сбросить код - я бы предоставил, это не столь трудно.

- - - Добавлено - - -

Обновлена команда - убрана костыль функция SetPlayerPosEx (теперь все действия происходят внутри команды), подправлены #define к данным передающимся запросом, добавлена поддержка 0.3DL скинов, создан массив со значением is_tmp, для автоматического подсчета.

DeimoS
17.12.2019, 22:36
Просто переправлять на тему, где ты отвечаешь юзеру конкретно за глобальные массивы подсчета строк, хотя это косвенно относится к тебе - такой себе вариант.

Эмм...
1) Когда ты используешь оператор "static", ты и так создаёшь глобальный массив...
2) В теме я описывал принцип работы стека, а не "принцип работы стека относительно глобальных массивов".



По твоей логике на форумах можно лишь оставить тогда мануалы по созданию команд/систем/функций, но никак не выкладывать готовое, что могут использовать юзеры.

Нет, по моей логике если ты публикуешь куда-либо код, то этот код должен:
1) Быть качественным.
2) Соответствовать нормам, которые приняты в сообществе, где ты этот самый код публикуешь (это банальная вежливость, если не рассматривать аспекты, связанные с пользой для других).



На официальном форуме удалены всевозможные топики и её не скачать с официального сайта.

Эмм, повторяю ещё раз: до этого, чтоб скачать 0.3DL, приходилось либо вручную вбивать адрес файлопомойки сайта sa-mp.com, где хранятся все версии и к которой Куй, судя по всему, закрыл доступ (files.sa-mp.com), либо выискивать тему на официальном сайте. Как итог: о 0.3DL знают, в основном, за счёт того, что сами сервера активно пиарят себя, а не потому что этому способствует информация с оф.сайта.
Иными словами, "запрет" никак особо не повлияет на 0.3DL, ибо её, фактически, "запретили" ещё в момент, когда Куй отказался продолжать её дорабатывать.


Если какому-либо из юзеров потребовалось бы использовать и скины для 0.3DL ветки, и он бы попросил сбросить код - я бы предоставил, это не столь трудно.

Так а что мешает сразу сделать код более универсальным?

Kovshevoy
17.12.2019, 22:44
Так а что мешает сразу сделать код более универсальным?

Если юзер по ошибке введет значения от 20к до 30к, появиться скин CJ (возможно, это всего лишь догадки)
Юзер сразу прибежит в тему кричать, что БАГАННАЯ КОМАНДА.

- - - Добавлено - - -



Нет, по моей логике если ты публикуешь куда-либо код, то этот код должен:
1) Быть качественным.
2) Соответствовать нормам, которые приняты в сообществе, где ты этот самый код публикуешь (это банальная вежливость, если не рассматривать аспекты, связанные с пользой для других).


Мой код не максимально качественный, но качественный.
Нормы которые приняты в сообществе? Это сообщество - в пределах данного форума.
На лайткоде иногда выбрасывали код схожий который используется в основном на п-п, но не более.

Kovshevoy
17.12.2019, 23:23
Эмм, повторяю ещё раз: до этого, чтоб скачать 0.3DL, приходилось либо вручную вбивать адрес файлопомойки сайта sa-mp.com, где хранятся все версии и к которой Куй, судя по всему, закрыл доступ (files.sa-mp.com), либо выискивать тему на официальном сайте. Как итог: о 0.3DL знают, в основном, за счёт того, что сами сервера активно пиарят себя, а не потому что этому способствует информация с оф.сайта.
Иными словами, "запрет" никак особо не повлияет на 0.3DL, ибо её, фактически, "запретили" ещё в момент, когда Куй отказался продолжать её дорабатывать.

0.3DL файлы (сервер и клиент) лежали не на "файлопомойке" сайта sa-mp.com, а в папках форума (forum.sa-mp.com/files) и где-то там дальше.
Соответственно, ссылки уже невалидные, так как файлы удалены.
Кстати, папка с ДЛ версией удалена, а с 0.3.8 - осталась (клик (https://forum.sa-mp.com/files/038RC/))

- - - Добавлено - - -

Обновлено: Добавлена проверка на версию 0.3DL путем проверки объявленной функции.

execution
18.12.2019, 09:52
static const save_skin_query[] = "UPDATE "TABLE_ACCOUNTS" SET "COLUMN_SKIN" = %d WHERE "COLUMN_ID" = %d";
->
static const save_skin_query[] = "UPDATE "#TABLE_ACCOUNTS" SET "#COLUMN_SKIN" = %d WHERE "#COLUMN_ID" = %d";
Не?

Kovshevoy
18.12.2019, 14:35
static const save_skin_query[] = "UPDATE "TABLE_ACCOUNTS" SET "COLUMN_SKIN" = %d WHERE "COLUMN_ID" = %d";
->
static const save_skin_query[] = "UPDATE "#TABLE_ACCOUNTS" SET "#COLUMN_SKIN" = %d WHERE "#COLUMN_ID" = %d";
Не?

Можно любой из вариантов использовать.

DeimoS
19.12.2019, 02:46
Если юзер по ошибке введет значения от 20к до 30к, появиться скин CJ (возможно, это всего лишь догадки)
Юзер сразу прибежит в тему кричать, что БАГАННАЯ КОМАНДА.

Ну, как я вижу, ты уже сам понял как избежать такого за счёт "#if defined"



Нормы которые приняты в сообществе? Это сообщество - в пределах данного форума.

Ну так и код ты публикуешь на данном форуме, а не где-то.


0.3DL файлы (сервер и клиент) лежали не на "файлопомойке" сайта sa-mp.com, а в папках форума (forum.sa-mp.com/files) и где-то там дальше.

Во-первых, они лежали в одной папке и оба адреса выводили на эту папку.
Во-вторых, там лежали все версии SA-MP, от того я и назвал её файлопомойкой.

И к чему вообще эти уточнения-то? Речь ведь не о том, где лежали файлы, а о том, что 0.3DL не стал менее актуальным только потому, что царьку в очередной раз моча в голову ударила и он решил всё удалить. И случилось так потому, что среднестатистический пользователь и так обычно дальше раздела "download" на официальном сайте не ходил, зная о наличии 0.3DL только за счёт того, что сами сервера пиарили себя, а не за счёт каких-то там разделов на форуме. Есть полно опросов игроков на этот счёт, которые делали в момент, когда пытались Куя убедить вынести информацию о релизе 0.3DL на официальную страницу. Это не мои выдумки.

- - - Добавлено - - -


static const save_skin_query[] = "UPDATE "TABLE_ACCOUNTS" SET "COLUMN_SKIN" = %d WHERE "COLUMN_ID" = %d";
->
static const save_skin_query[] = "UPDATE "#TABLE_ACCOUNTS" SET "#COLUMN_SKIN" = %d WHERE "#COLUMN_ID" = %d";
Не?

У него в макросах уже присутствуют кавычки, так что "#" там не обязательна.