Псевдо-обучение Sourcepawn #1

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

  1. neatek3

    neatek3

    Сообщения:
    124
    Симпатии:
    127
    Привет всем, я Neatek.

    Видео версия.


    Что нужно для скриптинга?
    http://dl.notepad-plus-plus.org/downloads/6.x/6.7.4/npp.6.7.4.Installer.exe
    https://sm.alliedmods.net/dl.php?filename=sourcemod-1.7.0-windows.zip

    Добавить закладку в браузер:
    https://sm.alliedmods.net/new-api/

    Как начать?
    Установите Notepad++, разорхивируйте папку scripting из архива sourcemod1.7.0
    откройте папку scripting, создайте файл Plugin.sp (именно .sp, а не .sp.txt)

    Что дальше?
    Весь скриптинг начинается с типов переменных.
    В нашем случае это:
    PHP:
    int 
    bool
    char
    Это 3 самых основных типа.

    int - Целочисленные. Обычные строчки.
    char - Строковые.
    bool - Булева алгебра. (true и false, правда или ложь)

    Как создавать переменные?
    Синтаксис -> [тип] [название][размер];
    итого создаем 3 типа переменных:
    PHP:
    #include <sourcemod>

    int Chislo;
    char Stroka[86];
    bool Pravda;
    по умолчанию int = 0, bool = false, ну и пустая строка.

    Логический оператор if
    синтаксис простой.
    Код:
    если(то-то то... выполняет условия) { то мы делаем это }
    иначе { петя идёт ****}
    
    пишем это нормальным языком
    PHP:
    if(1) { /* это никогда не произойдет потому что 0 меньше 1 */ 
    else { 
    /* петя в любом случае идёт *****/ 
    Как управлять строками, числами и булевой переменной?
    с числами все легко:
    PHP:
    if(Chislo 0
    /* Число больше 0 */}

    if(
    Chislo 1
    /* Число меньше 1 */}
    И так далее как вам угодно с числами(int).

    теперь давайте с булевыми переменными.
    PHP:
    if(Pravda == false) {
         
    /* О круто! Pravda == false, значит кто-то лжёт. */
    }

    if(
    Pravda == true) {
         
    /* О круто! Pravda == true, значит это правда. */
    }

    bool PravdaNet// создали PravdaNet
    PravdaNet false// Присвоили значение переменной PravdaNet = false (ложь/0)
    if(Pravda == Pravda) {
    // что-то там...
    }
    Если честно, для простого понимания...
    true = 1
    false = 0

    т.е. это как бы та же целочисленная, но оно быстрее выполняется, за счет быстрого нахождения в памяти устройства, поэтому и выделили отдельный тип bool, 0 или 1.
    а для программистов проще писать true или false, дабы не путаться.

    Как сравнивать char(строчки)?
    Ну тут есть уже встроенные функции.
    https://sm.alliedmods.net/new-api/string/StrEqual
    https://sm.alliedmods.net/new-api/string/strcmp
    почитать о них можете по ссылкам.

    пример:
    PHP:
    char stroka1[48];
    char stroka2[48];

    if(
    StrEqual(stroka1stroka2)) {
    // ура они равны!
    }
    else
    {
    // не чувак, ты не прав. они ***** не похожи...
    }
    теперь рассмотрим параметры и возвращаемое значение функции StrEqual.
    PHP:
    bool StrEqual(char[] str1char[] str2bool caseSensitive)
    bool StrEqual(char[] str1, char[] str2, bool caseSensitive)
    жирным текстом я буду выделять то, о чем идет речь.
    значит первое значение перед функцией - это возвращаемое значение.
    в нашем случае bool. оно будет возвращать true или false.

    bool StrEqual(char[] str1, char[] str2, bool caseSensitive)
    название самой функции

    StrEqual(char[] str1, char[] str2, bool caseSensitive)
    параметры функции

    bool StrEqual(char[] str1, char[] str2, bool caseSensitive)
    рассмотрим первый параметр функции StrEqual.
    char[] str1.
    Это строковая переменная, значит первый агрумент принимает только строчки.

    bool StrEqual(char[] str1, char[] str2, bool caseSensitive)
    Это чувствителен или нет к регистру.
    Подробнее здесь.

    Цикл for.
    самый распространенный и простой для понимания.
    можно выполнять определенные действия несколько раз.
    PHP:
    for(int i 0<= 10i++)
    {
    // делаем 10 раз действие
    }
    Рассмотрим for(int i = 0; i <= 10; i++)

    for(int i = 0; i <= 10; i++)
    название цикла.

    for(int i = 0; i <= 10; i++)
    создаем переменную i, со значением 0 для цикла.

    for(int i = 0; i <= 10; i++)
    это условие. если i меньше или равно 10, то будет выполняться i++

    for(int i = 0; i <= 10; i++)
    выполняемое действие, если условие проходит.
    по сути i++ равноценно i = i + 1;
    то есть переменная сама к себе прибавляет +1.
    есть еще i-- и.т.д я в них особо не вникал.

    События Sourcemod.
    основы типо мы якобы поняли, как создавать переменные, как делать условия, как делать цикл for.

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

    заходим на https://wiki.alliedmods.net/Game_Events_(Source)
    нас интересует Counter-Strike: Source, жмакаем по ней.
    https://wiki.alliedmods.net/Counter-Strike:_Source_Events

    жмем на Player_death.
    https://wiki.alliedmods.net/Counter-Strike:_Source_Events#player_death

    PHP:
    player_death // название события
    NoteWhen a client dies // когда происходит событие

    Name:    player_death // название события
    Structure:    // структура события, чо возвращается
    short    userid    user ID who died // userID кто здох
    short    attacker    user ID who killed // userID кто убил
    string    weapon    weapon name killer used // оружие с которого убили, во внимание возмите STRING, строка будет возвращаться.
    bool    headshot    singals a headshot // В голову или нет. Во внимание возьмите BOOL, булева переменная, Ложь или Правда - В кочан или нет. (true, false)
    short    dominated    did killer dominate victim with this kill // а это х*ня какая-то. типо сдоминировал или нет, крч мне срать.
    short    revenge    did killer get revenge on victim with this kill // тоже херня...
    после анализа того, что мы можем получить хукируем событие (регистрируем).
    https://sm.alliedmods.net/new-api/events/HookEvent

    void HookEvent(char[] name, EventHook callback, EventHookMode mode)

    void - функция нихера не возвратит.
    char[] name - название события, в нашем случае player_death
    EventHook callback - Коллбэк для функции, ну это функция для функции... типо событие произошло, делаем это. вот так по простому по пацански определил вам.
    EventHookMode mode - хук мод, он отвечает возвращать значения или нет, или когда делать событие до происхождения события или после. Кароче тупо не указывайте, вы же нупки.

    PHP:
    #include <sourcemod>

    public OnPluginStart() {
        
    HookEvent("player_death"FUNCIAMATTVOY);
    }

    public 
    Action FUNCIAMATTVOY(Event hEvent, const char[] namebool dontBroadcast)
    {
        
    int client GetClientOfUserId(hEvent.GetInt("userid"));
        
    char gWeapon[64];
        
    hEvent.GetString("weapon"gWeaponsizeof(gWeapon));
    }
    Action:FUNCIAMATTVOY(Handle:event, const String:name[], bool:dontBroadcast)
    название действия.

    Action:FUNCIAMATTVOY(Handle:event, const String:name[], bool:dontBroadcast)
    хэндл события, из него вытаскиваем инфу о событии.

    Action:FUNCIAMATTVOY(Handle:event, const String:name[], bool:dontBroadcast)
    ваще не знаю чо это, но наверное название события... типо можно сделать дохера хуков в один коллбэк, и потом определять чо же вам пришло...

    Action:FUNCIAMATTVOY(Handle:event, const String:name[], bool:dontBroadcast)
    отображать событие или нет, этим можно отключать в чате сообщения когда человек заходи на сервер, или изменение переменной сервера, забейте кароч.

    int client = GetClientOfUserId(GetEventInt(event, "userid"));
    создали переменную client

    int client = GetClientOfUserId(GetEventInt(event, "userid"));

    Выдирание значений из событий
    https://sm.alliedmods.net/new-api/events/GetEventInt
    функция GetEventInt, выдирает значение из события, мы о них уже говорили о значениях, когда разбирали само событие.

    на данной странице:
    https://wiki.alliedmods.net/Counter-Strike:_Source_Events#player_death

    GetEventInt типо получаем целочисленное значение из события...
    еще существуют GetEventBool, GetEventString.

    Код:
    Structure:	// структура события, чо возвращается
    short	userid	user ID who died // userID кто здох
    short	attacker	user ID who killed // userID кто убил
    string	weapon	weapon name killer used // оружие с которого убили
    
    урезанную табличку скинул, которая была ранее.

    видим GetEventInt(event, "userid") и в таблице есть userid, только там short.
    short то же самое что и integer (int), только малого размера, но мы его берем как Integer. мы получим userid игрока который здох. (номер игрока).

    Что же еще можно взять из события?
    Код:
    string	weapon	weapon name killer used // оружие с которого убили
    
    Оружие! Почему бы и нет?

    смотрим на https://sm.alliedmods.net/new-api/events/GetEventString
    void GetEventString(Handle event, char[] key, char[] value, int maxlength, char[] defvalue)

    handle event (1) -> хэндл евента
    char[] key -> название чего извлекать, в нашем случае weapon
    char[] value -> куда извлекать будем, в нашем случае создадим переменную char gWeapon
    int maxlength -> размер того, куда записываем, тупо пишем sizeof(gWeapon)
    char defvalue[] -> по умолчанию значение, тупо не указываем.

    можно также писать так:
    hEvent.GetString(char[] key, char[] value, int maxlength);

    hEvent. -> хэндл события, этакий класс. к которому можно обращаться.
    остальное тоже самое что и выше.

    PHP:
    char gWeapon[64];
    hEvent.GetString("weapon"gWeaponsizeof(gWeapon));
    Вот получили оружие!
    то же самое и с userid, только там значение типо userid игрока(номер игрока).

    int client = GetClientOfUserId(GetEventInt(event, "userid"));
    разобрали.

    int client = GetClientOfUserId(GetEventInt(event, "userid"));

    GetEventInt(event, "userid") функция берет значение игрока (userid)
    GetEventInt(event, "userid") = userid

    GetClientOfUserId(userid) = номер клиента, по userid.

    суть: на сервере когда играет игрок он получает номер игрока, он может быть 50 или 346 и так далее... функция GetClientOfUserId как бы делает стандарт для всех игроков. Если на сервере 10 игроков, то и номеров клиента будет 10 штук. без всяких 50 или 346... Тем самым делая легче "проход" по игрокам с помощью цикла.

    int client = значение получило клиента...
    теперь мы можем его кикнуть!
    https://sm.alliedmods.net/new-api/clients/KickClient

    PHP:
    #include <sourcemod>

    public OnPluginStart() {
        
    HookEvent("player_death"FUNCIAMATTVOY);
    }

    public 
    Action FUNCIAMATTVOY(Event hEvent, const char[] namebool dontBroadcast)
    {
        
    int client GetClientOfUserId(hEvent.GetInt("userid"));
        
    char gWeapon[64];
        
    hEvent.GetString("weapon"gWeaponsizeof(gWeapon));
        
    KickClient(client"Ты дно");
    }
    int KickClient(int client, char[] format, any ...)
    как я вас учил, анализируйте...
    возвращает int(integer), параметры -> клиент, и char[] format(текст, строка)...
    any... любое значение...

    мы можем написать даже так.
    PHP:
    #include <sourcemod>

    public OnPluginStart() {
        
    HookEvent("player_death"FUNCIAMATTVOY);
    }

    public 
    Action FUNCIAMATTVOY(Event hEvent, const char[] namebool dontBroadcast)
    {
        
    int client GetClientOfUserId(hEvent.GetInt("userid"));
        
    char gWeapon[64];
        
    hEvent.GetString("weapon"gWeaponsizeof(gWeapon));
        
    KickClient(client"Client номер: %d"client);
    }

    я бы объяснил почему %d %s %i %f ... и так далее, но это долго и геморно.

    Писал сразу на форум, монотонно, без проверки знаний или еще чего...
    просто сел и по быстрому написал. код возможно не рабочий, не проверял.

    устал. пальцы вверх кому понравилось, может еще накатаю.
    пишите про что бы вы хотели узнать.
     
    Последнее редактирование: 11 мар 2015
    alekcei82, ExtaSpeed, Серый™ и 15 другим нравится это.
  2. BatyaMedic

    BatyaMedic Ньюсмейкер

    Сообщения:
    769
    Симпатии:
    123
    Re: Урок Sourcepawn 1.7 #1

    Чувак,я тя люблю.
     
    neatek3 нравится это.
  3. neatek3

    neatek3

    Сообщения:
    124
    Симпатии:
    127
    Re: Урок Sourcepawn 1.7 #1

    Пишите что хотите узнать!
    Скриптинг, кодинг, программирование это весело,
    должно быть бесплатно, доступно всем, и со всеми исходниками :beer:

    А особенно, должен быть конструктивный разговор между скриптерами, некие альянсы для создания стоящего продукта.
    Русского продукта, а не использование уже доустаревших зарубежных плагинов, скриптов, программ.
     
  4. R1KO

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

    Сообщения:
    5.972
    Симпатии:
    2.978
    Re: Урок Sourcepawn 1.7 #1

    Хотелось бы еще отметить что бул занимает памяти меньше чем инт.
    Еще бы убрал мат. В целом - мне нравится. Будет время - дополню
     
    Серый™ и komashchenko нравится это.
  5. neatek3

    neatek3

    Сообщения:
    124
    Симпатии:
    127
    Re: Урок Sourcepawn 1.7 #1

    Каждый в праве выбирать материться или нет)
    Лебедь(Долго. Дорого. Ох*енно) же материться, и все нормально. :victory:
    В данном материале я его использовал для простого донесения смысла до людей и как бы веселые моменты этакие.
     
  6. The End Is Near...

    The End Is Near... Russian Roulette

    Сообщения:
    893
    Симпатии:
    659
    Re: Урок Sourcepawn 1.7 #1

    good work
     
  7. Reiko1231

    Reiko1231 AlexTheRegent

    Сообщения:
    237
    Симпатии:
    569
    Re: Урок Sourcepawn 1.7 #1

    Не хочу придираться, но раз это "урок SourcePawn 1.7", то не могу промолчать:
    1.
    От 0 до 10 включительно! : 0, 1, 2, ..., 10. Это 11 чисел! И действие, соответственно, будет выполнено 11 раз - вот простой код для проверки:
    Код:
    public OnPluginStart()
    {
    	int iCount = 0;
    	for ( int i = 0; i <= 10; ++i )
    	{
    		iCount++;
    	}
    	PrintToServer("iCount = %d", iCount);
    }
    [​IMG]

    2. Статья начинается с
    Код:
    Весь скриптинг начинается с типов переменных.
    В нашем случае это:
    int 
    bool
    char 
    Это 3 самых основных типа.
    Но затем в примере с событиями про это забывается и пишется на старом синтаксисе:
    В новом синтаксисе это выглядит так:
    Код:
    public Action FUNCIAMATTVOY(Handle event, const char[] name, bool dontBroadcast)
    Двоеточия больше не нужны при указании типов.

    3. Опять же, статья о 1.7, и упущена одна из самых важных частей обновления - methodmap, или же оболочки над Handle. В данном случае для событий есть специальная класс-оболочка Event. Так что правильное объявление функции обратного вызова для события выглядит так:
    Код:
    public Action FUNCIAMATTVOY(Event hEvent, const char[] name, bool dontBroadcast)
    Теперь же, исходя из того, что у данного класса есть методы, перепишем код:
    Код:
    public Action FUNCIAMATTVOY(Event hEvent, const char[] name, bool dontBroadcast)
    {
        int client = GetClientOfUserId(hEvent.GetInt("userid"));
        char gWeapon[64];
        hEvent.GetString("weapon", gWeapon, sizeof(gWeapon));
        KickClient(client, "Вы плохо играете");
    }  
    Можно конечно сказать, что это - статья для новичков, но зачем их учить тому, что устаревает? Тем более, что это, что то - одинаково непонятно для них. Так лучше учиться сразу правильно.

    4. Не понятен выбор имен переменных. Я конечно понимаю всё, но ведь эта статья - урок. И не понятно, почему int client, но char gWeapon[64]. Почему у строчной переменной первая буква - g, а дальше слово с большой буквы? Согласно венгерской нотации, которой придерживаются некоторые скриптеры, g означает global, глобальная переменная, но в контексте данной функции это не так. Почему не назвать обе переменные в одном формате - либо int client; char weapon[64], либо оба в венгерской нотации - int iClient, char szWeapon[64], либо в своём варианте, но чтобы прослеживалась логика именования переменных.

    5. Пропущен тип float, а он является немаловажным.

    6. Лично автору. Оффтоп
     
    Последнее редактирование: 10 мар 2015
    BatyaMedic, Серый™, EPacker2 и 5 другим нравится это.
  8. neatek3

    neatek3

    Сообщения:
    124
    Симпатии:
    127
    Re: Урок Sourcepawn 1.7 #1

    Reiko1231, ты исправил - молодец, возьми с полки пирожок.
    я буду вести счет, кто делает поправки, в "уроках", и буду суммировать во всех "уроках", тем самым показывая кто внес "вклад".

    я написал это все на скорую руку, и за 5-10 минут) так что пофиг) кто-то да что-то поймет.
    Это слишком трудно для людей... которые совсем не бум-бум в sourcepawn. может быть потом. Это часть #1

    Изменил название темы на Высер-обучение Sourcepawn от Neatek #1, ой сори, лучше так Псевдо-обучение Sourcepawn #1
    теперь это не урок, теперь это ясно что это. Думаю продолжать свою рубрику высер-обучение, полезно людям и других мотивировать на "уроки".

    Какие жалостливые все...
    чего вы все так к правилам цепляетесь? :\
    убрал мат. теперь это просто звездочки, даже намёка на мат - нету, мне просто нравятся звездочки!

    Суть высера: Дать некую массу информации, на основе которой человек может начать что-то делать, и чтобы вы такие все умные исправляли и писали как надо, иначе вас никак не мотивировать.

    Кароче главное то, что начало положено.
     
    Последнее редактирование: 11 мар 2015
  9. максимка27

    максимка27

    Сообщения:
    517
    Симпатии:
    170
    neatek3, Рейко всё правильно подметил, а ты нет чтобы сказать ему спасибо и поправить свою тему, ты повел себя неадекватно со своей глупой иронией. И вот как ты хочешь чтобы тут к тебе относились, если ты не можешь разговаривать по человечески.
    Оффтоп
     
    Reiko1231 и TWRP нравится это.
  10. neatek3

    neatek3

    Сообщения:
    124
    Симпатии:
    127
    я ему сказал взять пирожок с полки, это некое спасибо, и поправил текст, пишу потому что ты невнимательный, а вот ты меня обижаешь.. как бэ. Мне не нужно чтобы ко мне хорошо относились люди, я хочу заставить людей обучить других людей вместо того чтобы меня грязью поливать, хоть мне и все равно, сделайте урок по сорспавну может даже как видео и выложить это в интернет чтобы каждый желающий мог научиться скриптить, иначе же все равно я буду выкладывать такие псевдо обучения и грамотный человек поймёт что и куда, судя по твоей негативной реакции ты этого не хочешь чтобы люди умели скриптить, это очень плохо... да и ребят не вам судить про мою неадекватность, я будучи неадекватным могу нести больше пользы чем куча адекватов. так что ребята готовтесь скриптить вместе!

    Готовлю первый выпуск программы "Псевдо-код Sourcepawn" под Sourcemod на Youtube
     
    Последнее редактирование: 11 мар 2015
    hunter_zcl14 нравится это.
  11. EPacker2

    EPacker2 3D-моделист

    Сообщения:
    1.005
    Симпатии:
    608
    Оффтоп
     
  12. semjef

    semjef semjef.ru

    Сообщения:
    1.031
    Симпатии:
    473
    А теперь удаляй этот пост и учись сам работать под версию 1.7:D
     
  13. neatek3

    neatek3

    Сообщения:
    124
    Симпатии:
    127
    Чувак, блин не важно как ты пишешь вообще, если это компилятор принимает, утечек памяти нет, это быстро работает, и всё логично,
    не важно как ты пишешь, используя классы, которые появились в Sourcemod 1.7.0 или нет.
    Да, скорее всего функции уберут, но когда это будет, тогда и поговорим, обучение на функциях проще, хотя незнаю, нежели на классах. Так что пофиг)

    Интересы у людей меняются. Теперь я могу всем помочь, абсолютно бесплатно!
    Да, я еврей этакий, но у меня теперь другой хлеб. :acute:

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

    Пишу этот пост, а видео загружается на Youtube.
    Я хочу сказать сразу что я болею, и голос не особо у меня, срывается бывает, и я постоянно покхэкиваю, но я не Владимир Жириновский.
    Но я пытался сделать голос более менее нормальным и веселым, несмотря на то, что я постоянно в мыслях путался и заикался.
    Качество видео не очень, но надеюсь на 720HD виден текст, и этот кот меня уже достал.
     
  14. semjef

    semjef semjef.ru

    Сообщения:
    1.031
    Симпатии:
    473
    neatek3, классы намного проще использовать, серьёзно.
     
  15. neatek3

    neatek3

    Сообщения:
    124
    Симпатии:
    127
    Я в курсе, спасибо.:secret: