F.A.Q. по скриптингу by sbelov020

Сообщения
631
Реакции
145
Итак, наконец у меня дошли руки создать данную тему.
Предпосылки к созданию: https://dev-cs.ru/threads/4242/

Краткое описание: в этой теме я буду задавать интересующие меня вопросы по скриптингу, а после получения ответа, (если Sonyx немного поможет мне с таймингом редактирования поста:smile3:) ответы будут размещаться здесь, в шапке темы, по виду:

Q: Вопрос
A: (автор ответа) Ответ

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

Итак, мой первый вопрос: какое меню лучше? Которое создается через menu_create (я так понял, это т.н. "новое" меню?), или через register_menu? Попрошу дать развернутый ответ, почему то или иное меню лучше.

/* Начало F.A.Q. */
  • Q: Какое меню лучше? "Старое" или "новое"?
  • A: BlackSignature, gyxoBka: Это зависит от требуемых задач. Зачастую "новое" меню не может выполнить те задачи, которые может выполнить "старое", но иногда всё-же наоборот, удобнее использовать "новое" меню.

  • Q: В чём разница между static и new const?
  • A: BlackSignature: const делает переменную/массив read-only, т.е. можно читать, но нельзя изменять.
    static создаёт переменную при первом обращении в функции, и после завершения функции переменная не удаляется, т.е. сохраняет своё текущее значение.
    1) В очень часто вызываемых функциях (каллбеки пофреймовых хуков вроде PreThink, AddToFullPack и т.п.) позволяет сэкономить процессорное время на создании переменных/массивов. Особенно актуально для последних (чем они больше, тем больше выигрыш).
    2) Сохранение значения в локальных масштабах (в пределах функции).

  • Q; Что такое #pragma, и какие они бывают?
  • A; wopox1337: это директивы препроцессора. Диктуют компилятору условия.

  • Q: ShowSyncHudMsg() работает только внутри одного плагина, или синхронизирует весь худ со всеми плагинами, где он есть?
  • A: fantom: Всех. Ибо HUD имеет всего 4 канала. Вся работа SyncHud заключается в том, чтобы запомнить последний канал по которому было отправлено sync сообщение, и его же использовать при следующей отправке сообщения. Таким образом у вас не получится наложения предыдущего HUD на текущий. Ведь предыдущий будет заменен.
    При этом последний аргумент в set_hudmessage() можно не указывать.

  • Q: Что за операторы += и -= ? В чем их отличие от + и - ?
  • A: the_hunter: допустим, у тебя есть переменная new variable = 5;. Тебе нужно добавить какое-то значение к этой переменной. Как это сделать? Можно вот так: variable = variable + 10;. Но оператор += позволяет сократить код который выше, до такого: variable += 10;.
    То есть, += это синтаксический "сахар", который позволяет сократить код.

  • Q: За что отвечает pev_gaitsecuence?
  • A: Garey: за текущую анимацию нижней части модели игрока (для прыжков, бега, приседания и т.д.) на обычных энтитях не проигрывается и за чего криво анимации игрока выставляются при проигрывании.

  • Q: Какие лимиты по кол-ву символов у HUD/DHUD?
  • A: BalbuR: У обычного HUD 512, у DHUD 128.
 
Последнее редактирование:
Сообщения
360
Реакции
712
Итак, мой первый вопрос: какое меню лучше? Которое создается через menu_create (я так понял, это т.н. "новое" меню?), или через register_menu? Попрошу дать развернутый ответ, почему то или иное меню лучше.
Вопрос не совсем понятен. Что подразумевается под "лучше"? Всё всегда зависит от задачи, а в данном случае, ещё и от предпочтения. Многостраничные меню (особенно, динамические, т.е. меняющиеся), как по мне, удобнее делать через систему "нового меню". Но это не всегда так, всё зависит от условий.
 
Сообщения
116
Реакции
131
Новая система меню это лишь обертка для "старого" меню и зачастую на новом меню нетипичные задачи не решить.
 
Сообщения
631
Реакции
145
BlackSignature, "лучше" для меня, в данном случае, удобнее, полезнее, надежнее.
Потому что сейчас я все свои меню пишу по старой системе. Вот и думаю, может я совершаю ошибку, и давно пора использовать новые меню?
15 Дек 2018
gyxoBka, иначе говоря, особой разницы нет? Кроме нюансов
15 Дек 2018
BlackSignature, вот у меня как раз в одном плагине многостраничное меню, в другом динамическое меню. (С переключателями вкл/выкл) сейчас они реализованы как несколько меню (страницы) и if-else для переключателей. Стоит переписать эти меню по новой системе?
 
Сообщения
360
Реакции
712
sbelov020, На данном этапе используйте тот вариант, который удобнее вам. Просто покажу пример старой системы, где при генерации составляется меню игроков + технические пункты, которые в системе "нового" меню описывались бы проще (меньше кода). В новой системе так же проще с определением страницы. Однако, конкретно этот вариант имеет ряд нюансов, которые не позволяют заюзать тут "новое меню" без лишних заморочек. Духовка верно подметил. Чем сложнее собирается меню, тем сложнее с ним работать при помощи "новой" системы.

Код:
stock func_TransferMenu(id, iPage = _PAGE1_) {
    new iPlayerCount, iPlayer

    for(iPlayer = 1; iPlayer <= MaxClients; iPlayer++) {
        if(iPlayer == id || !ps_is_player_loaded(iPlayer)) {
            continue
        }

        g_iPlayers[id][iPlayerCount] = iPlayer
        g_iPlayerIDs[id][iPlayerCount] = get_user_userid(iPlayer)
        iPlayerCount++
    }

    new i = min(iPage * ITEMS_PER_PAGE__TRANSFER_MENU, iPlayerCount)
    new iStart = i - (i % ITEMS_PER_PAGE__TRANSFER_MENU)
    new iEnd = min(iStart + ITEMS_PER_PAGE__TRANSFER_MENU, iPlayerCount)

    g_iMenuPage[id] = iPage = iStart / ITEMS_PER_PAGE__TRANSFER_MENU

    new iPos, iMenuItem, iKeys = MENU_KEY_0,
        iPagesNum = max(1, (iPlayerCount / ITEMS_PER_PAGE__TRANSFER_MENU + ((iPlayerCount % ITEMS_PER_PAGE__TRANSFER_MENU) ? 1 : 0)))

    new iCommission = g_eCvar[CVAR__COMM_PERCENT_USER], iFlags = get_user_flags(id)

    if(iFlags & g_eCvar[CVAR__SUPERVIP_FLAG]) {
        iCommission = g_eCvar[CVAR__COMM_PERCENT_SUPERVIP]
    }
    else if(iFlags & g_eCvar[CVAR__VIP_FLAG]) {
        iCommission = g_eCvar[CVAR__COMM_PERCENT_VIP]
    }

    new iLen = formatex( g_szMenu, chx(g_szMenu),
        "\yВыберите получателя [%d/%d]^n\
        \wУ вас \y%d \wочков \y(комиссия %d%%)^n^n",

        iPage + 1, iPagesNum,
        ps_get_points(id), iCommission
    );

    for(i = iStart; i < iEnd; i++) {
        iKeys |= (1 << iMenuItem)
        iPlayer = g_iPlayers[id][i]
        iLen += formatex(g_szMenu[iLen], chx(g_szMenu) - iLen, "\y%d. \w%n^n", ++iMenuItem, iPlayer)
    }

    if(!iMenuItem) {
        if(iPage) {
            return func_TransferMenu(id, --iPage)
        }

        g_iPlayers[id][0] = 0
        iKeys |= MENU_KEY_1
        iLen += formatex(g_szMenu[iLen], chx(g_szMenu) - iLen, "\y1. \dНет подходящих \y[обновить]")
    }

    if(iPage) {
        iPos++
        iKeys |= MENU_KEY_8
        iLen += formatex(g_szMenu[iLen], chx(g_szMenu) - iLen, "^n\y8. Назад")
    }

    if(iEnd < iPlayerCount)    {
        iPos++
        iKeys |= MENU_KEY_9
        iLen += formatex(g_szMenu[iLen], chx(g_szMenu) - iLen, "^n\y9. Далее")
    }

    formatex(g_szMenu[iLen], chx(g_szMenu) - iLen, "%s^n\y0. Выход", iPos ? "^n" : "")

    return func_ShowMenu(id, iKeys, MENU_MODE__TRANSFER)
}

stock func_TransferMenu_SubHandler(id, iKey) {
    new iMenuPage = g_iMenuPage[id]

    switch(iKey) {
        case _KEY8_: func_TransferMenu(id, --iMenuPage)
        case _KEY9_: func_TransferMenu(id, ++iMenuPage)
        case _KEY0_: return PLUGIN_HANDLED
        default: { // _KEY1_.._KEY7_
            new iPos = (iMenuPage * ITEMS_PER_PAGE__TRANSFER_MENU) + iKey
            new iTarget = g_iPlayers[id][iPos]
            new iTargetID = get_user_userid(iTarget) // SafeToUse для отключённых (возвращает -1)

            if(iTargetID != g_iPlayerIDs[id][iPos] || !g_iPlayers[id][0] || !ps_is_player_loaded(id))
                return func_TransferMenu(id, iMenuPage)

            g_iTarget[id] = iTarget
            g_iPlayerIDs[id][0] = iTargetID
            g_iInputMode[id] = INPUT_MODE__TRANSFER

            rg_send_audio(id, SOUND__BLIP1)
            client_print_color(id, iTarget, "^4* ^1Напишите в чат, сколько очков вы хотите передать игроку^3 %n", iTarget)
            client_print_color(id, print_team_default, "^4* ^1Если передумаете, напишите^4 %s ^1для отмены запроса", g_szCancelCmd)
        }
    }

    return PLUGIN_HANDLED
}
 
Сообщения
132
Реакции
109
В новом меню нельзя поставить номер пункта в квадратные скобочки :smile3:
 
Сообщения
631
Реакции
145
Следующий вопрос: в чём разница между static и new const?
 
Последнее редактирование:
Сообщения
360
Реакции
712
sbelov020, const делает переменную/массив read-only, т.е. можно читать, но нельзя изменять.
Вне функций нет разницы, static или new используйте new (причина через один пост ниже)
Внутри функции:
new заново создаёт переменную при каждом обращении к функции, и соотвественно, после завершения функции переменная удаляется, освобождая занятую память (значение пропадает).
static создаёт переменную при первом обращении в функции, и после завершения функции переменная не удаляется, т.е. сохраняет своё текущее значение.

Практическая польза от static внутри функции:
1) В очень часто вызываемых функциях (каллбеки пофреймовых хуков вроде PreThink, AddToFullPack и т.п.) позволяет сэкономить процессорное время на создании переменных/массивов. Особенно актуально для последних (чем они больше, тем больше выигрыш).
2) Сохранение значения в локальных масштабах (в пределах функции).
Код:
#include <amxmodx>

public plugin_init() {
    register_srvcmd("test", "myfunc")
}

public myfunc() {
    static iStatic
    new iNonStatic
  
    server_print("BEFORE -> iStatic: %d | iNonStatic: %d", iStatic, iNonStatic)
  
    iStatic++
    iNonStatic++

    server_print("AFTER -> iStatic: %d | iNonStatic: %d", iStatic, iNonStatic)
}
 
Последнее редактирование:
Сообщения
388
Реакции
676
В очень часто вызываемых функциях (каллбеки пофреймовых хуков вроде PreThink, AddToFullPack и т.п.) позволяет сэкономить процессорное время на создании переменных/массивов. Особенно актуально для последних (чем они больше, тем больше выигрыш).
Мнимый выигрыш, мало чем подтвержденный. Что будет, если статик осел в ОЗУ, а new в кэш процессора?
 
Сообщения
360
Реакции
712
Mistrick, может и так. Я не мерил, просто рассказал о применении как "деды с оленей завещали".
wopox1337, Какие файлы? Не понял. Переменная, объявленная в пределах функции, недоступна за пределами этой функции, если только она прямо не передаётся из этой функции куда-то наружу в виде аргумента. Ну это ты и так знаешь, это я ТС'у, чтобы понимал. :)
 
Сообщения
360
Реакции
712
wopox1337, Да, проверил, так и есть. Не знал об этом, т.к. никогда статики вне функций не использовал.
 

wopox1337

😈 самый злой модератор
Сообщения
2.187
Реакции
2.196
Если я правильно понял вопрос.
Код:
#define FIELD "Field #1"
или
new const FIELD[] = "Field #1";
То, лучше пользоваться вариантом new const. Почему? Проблемы компилятора AMXX по сей день не решены, хоть и не критичны.
Цитата от Prostotema:
Для строк в AMXX лучше использовать константы, потому что компилятор настолько божественен, что он записывает несколько одинаковых строчек (если это не константы) в .DATA
В компиляторах C++ такого мне не встречалось.
P.S: только не в угоду функциональности. (Там, где комментированием макроса можно повлиять на настройку)
 
Сообщения
360
Реакции
712
sbelov020, я же объяснил уже всё. const означает что значение после инициализации уже нельзя изменить. А static, созданный в рамках функции, означает что "объект" не удаляется из памяти, а продолжает в ней висеть, и при следующем к нему обращении(при чтении) можно получить его значение, которое никуда не делось.
new iVar = 1
const iVar = 1
static iVar = 1
static const iVar = 1
Суньте себе в тестовый плагин и поиграйтесь (запись, чтение), и всё станет ясно.
 
Сообщения
631
Реакции
145
Следующий вопрос:

Объясните, пожалуйста, что такое, какие бывают #pragma, и в каких случаях их нужно применять?

Пока что знаю только #pragma semicolon 1 - чтоб компилятор был требователен к точкам с запятой после каждой строки
и #pragma tabsize 0 - при компиляции размер табуляции устанавливается в 0.

Еще видел #pramga unused <..> - это чтоб в какой-то функции не использовать указанные аргументы?

И еще где-то видел #pragma compress 1 - но что он делает, мне не ясно.
 

Пользователи, просматривающие эту тему

Сейчас на форуме нет ни одного пользователя.
Сверху Снизу