как добавить казино через pawno / Скачать Программа Pawno на русском языке для GTA San Andreas

Как Добавить Казино Через Pawno

как добавить казино через pawno

ИЛИ if(Left (!Left && Right))
НЕ ИЛИ ИЛИ if(!((Left && !Right)

Добро пожаловать!

- Исправлены все недочёты, которые успел заметить
- Переписал создание домов (криво создавались)
- Исправил недоработку с прорисовкой объектов
- Переписал donate
- Добавил Perfomance для личного т.с
- Добавил финансовую статистику для бизнесов/АЗС
- В систему семей добавил банк
- Добавил в семью заместителя (возможность назначать/снимать)
- Добавил систему багажника для личного т.с /baggage (реализация так себе конечно)
- В донат добавил возможность покупки попугая (можно придумать ему имя, улучшить, чем больше уровень улучшений - тем чаще повторяет /toy)
- В донате можно купить любой номерной знак
- Добавил команду /park - возможность самостоятельно припарковать авто в радиусе м от дома
- Переделал оформление немного
- Новые команды для админов (/msgr - сообщение в радиусе для игроков, /gfinka /bfinka - просмотр финки бизнеса/АЗС, /crashed - крашнуть игрока)
- Если у админа различаются последний и текущий IP-адрес его права должен подтвердить старший администратор (/acceptadmin)
- Добавил возможность изменять освещение в доме
- Добавил новые интерьеры для домов (маппинг с паблика)
- В мэрии можно посмотреть статистику игроков (самые богатые, старые, донатеры и т.д.)
- Теперь создать семью можно в семейном центре (5 уровень и $)
- Теперь, чтобы вступить в организацию или стать лидером - нужно пройти простой RP-тест (/menu)
- Убрал поочерёдную систему репорта (теперь стандартная)
- Добавил новые функции для VIP (в планах полностью её переписать)
- В /menu теперь доступен ежедневный подарок (может выпасть что угодно, доступно с 3 уровня)
- В /apanel теперь можно посмотреть список игроков онлайн с мутом, в тюрьме
- В /apanel для старшей администрации теперь доступна функция отключать/включать доступ к казино
- Поменял интерьер в казино (переделать /dice и сделать крупье)
- Добавил команду /boostinfo (посмотреть текущие акции для игроков)
- Теперь при наличии более $ на руках у игрока появляется мешок с деньгами (можно убрать в настройках)
- В настройках можно изменить стиль игрового чата (как на Advance RP)
- Добавил /lmenu (возможность зареспавнить незанятый транспорт организации, посмотреть список игроков во фракции, управление банком организации)
- В /lmenu для президента добавлена возможность просмотра казны и управления налогом
- Для лидеров банд добавлена команда /fpay - выдать премию членам организации в сети
- Добавил команду /vacancy (можно посмотреть доступные вакансии, а лидерам организаций добавить их)
- Сделал систему репутации для администраторов (после ответа на репорт игрок может оценить ответ)
- Добавлена справочная книжка (/dir - посмотреть заместителей и т.д.)
- Полностью переписана система обработки объявлений для СМИ
- Система погоды (каждые 20 минут меняется погода в штате)
- В /apanel основателю можно изменять название сервера
- При создании дома можно указать наличие гаража (0 - нет, 1 - да), добавлена система гаражей, он есть не у всех домов. Если в доме имеется гараж, то нельзя использовать /park
- Исправил недочёты с попугаем (сохранение)
- Добавил в /apanel телепорт в goalma.org (также доступна /az [id игрока] для телепорта в зону)
- Добавил новый интерьер для армий
- В /donate добавлена возможность обнулить трудовую книжку
- Теперь, чтобы убрать временный скин, можно ввести команду /end
- МВД и мафиям сделана команда /object (заграждения, объекты), также при установке пишет ID игрока, который его установил (/break убрана)
- Добавлена система аксессуаров (можно приобрести пока что только в донате или выдать от имени администратора или получить в семейном центре)
- Добавлена команда /vad. С помощью неё Вы сможете выделить своё объявление как VIP (стоимость услуги $)
- Для бандитов добавил возможность грабить транспорт в гетто (/robcar, copy Advance). Владельцы ограбленного авто должны
будут оплатить его ремонт в полицейском участке.
- Помимо VIP сделан статус PREMIUM, у которого есть свои привилегии
- Добавлены печенья (их можно обменять на что-то ценное)
- Сотрудникам СМИ добавлена команда /skin > продать костюм игроку
- Добавлен новый класс дома - Luxury, у этого класса желтый пикап (отличие от остальных)
- Теперь вместо чекпоинтов у домов - пикапы
- В семья добавлены ранги. Всего 5 рангов, названия может менять только владелец семьи. Теперь игрок с 4 рангом в семье может принимать и выгонять из семьи
- Добавлен семейный центр в ЛС (у автошколы). Там можно создать семью, посмотреть рейтинг семей, обменять печенье на призы
- Переписаны банки. Теперь есть Центральный банк в ЛС и его филиалы в СФ и ЛВ, в ЦБ можно создавать счета и т.д., а в филиалах
доступны депозитные счета. Процентная ставка зависит от статуса (обычный - %, ВИП - %, ПРЕМИУМ - %), пополнять и снимать
средства с депозитного счёта можно раз в сутки
- В банки добавлены говорящие актеры (анимка и текст над головой)
- Переписана команда /tp
- Сделал систему репутации для администраторов (после ответа на репорт, игрок может оценить ответ)
- Сделал тип бизнеса - бар (свой интерьер добавил)
- Сделан функционал обмена печенья на ценные призы в "Семейном центре". Вы можете обменять 20 шт. печенья на рандомный приз.
Печенье выдаётся каждый час по 1 шт. (вип игрокам - 3 шт., премиум игрокам - 5 шт.)
P.S В скором времени планирую добавить квесты, за выполнение тоже будут выдаваться печенья
- Администраторам добавлена команда /getowner (посмотреть владельца т/с)
- Управление семьей перенесено в /mn > управление аккаунтом > управление семьей
- Владелец семьи теперь может привязать дом к семье, игроки смогут в нем спавниться, правда для этого класс дома
должен быть как минимум "Элитный".
- Покинуть и удалить семью теперь можно только в семейном центре
- В 3D тексте у дома пишет название семьи, которой принадлежит дом
- Теперь в семейном центре можно изменить название семьи
- Когда разгружаешь ящики с патронами или медикаментами на склад организации (об этом пишет в чат фракции)
- Исправлен баг с отображением времени при bizwar у мафий
- Теперь античит не срабатывает на SpeedHack, если Вы используете Perfomance Tuning
- При смене ника в таблице MySQL теперь изменяется ник зама и лидера (если игрок таковым является)
- В /time пишет время заключения и затычки (если они есть)
- В больницы добавлены регистратуры, там можно пройти курс платного лечения (мгновенно вылечиться), если на сервере отсутсвуют
goalma.orgики учереждения, в котором находится игрок (если работники есть - вылечиться будет нельзя)
- Исправлен баг с пикапом на сдачу экзамена в АШ
- В автошколу добавлен вертолёт, а также возможность сдать экзамен на воздушный транспорт (сделана практическая сдача)
- В /lmenu добавлена возможность создавать объявления для сотрудников (они смогут его посмотреть с помощью команды /advert)
- Добавлен PREMIUM авторынок в СФ для обладателей PREMIUM аккаунта. Там можно приобрести транспорт, который не купишь в обычном автосалоне.
На авторынке доступно ограниченное количество автомобилей (админы могут добавить командой /addcar [модель машины] [цена])
- Добавлены ключи от камеры в КПЗ, при наличии ключа Вы сможете выйти из тюрьмы с помощью команды /unjail. Ключи можно получить через донат
или обменяв на печенье в семейном центре.
- В семейном центре при обмене печенья теперь можно получить PREMIUM (шанс очень маленький, но всё же)
- Исправил команду /respv (выдавало в лог ошибку)
- Исправлен баг со сдачей прав
- Исправлен баг с выдачей аксессуаров командой /giveaccs (путались слоты)
- При регистрации можно указать национальность персонажа (в дальнейшем будет функционал для этого)
- В порту СФ добавлен продавец семян Ричи. Он появляется в , , и по серверному времени.
У него бандиты могут приобрести семена, с помощью которых можно выращивать куст конопли (/plant), после выращивания куста
получаются наркотики. Их бандиты могут продать в притон (в гетто).
- Переписан притон в гетто. Теперь лидеру банды, которая контролирует территорию с притоном доступна команда /hangout.
Там можно изменить цену на продажу и покупку наркотиков, а также пополнить баланс или снять с баланса притона денежные средства
- Исправлен баг с аксессуарами (путались слоты)
- Убрана команда /selldrugs (за ненадобностью)
- Исправлен баг с /alogin, когда аккаунт только что зарегистрирован
- Теперь проверка на совпадение IP действует на всех администраторов кроме 6 уровня
- В /report теперь нельзя подать жалобу на самого себя
- Добавлена система достижений. На данный момент сделано 5 достижений, за выполнение которых игроку выдаётся уникальный аксессуар,
который нигде нельзя приобрести. Информацию о достижениях можно посмтреть в меню /mn > 10 пункт
- Переписана система промокодов. Отныне существует 3 типа промокодов - для гос, банд и ловцов имущества.
Администраторы могут создавать и удалять промокоды командами /addpromo, /dellpromo. Также можно смотреть статистику промокодов /promolist.
Промокод устанавливается на определенного игрока (держатель промо), он может просматривать подробную статистику промокода (кол-во активаций, дата создания)
Игрок, который активировал промокод, может просматривать информацию о бонусах, которые ему достанутся по достижении определенного уровня.
- Игрокам от 3 уровня добавлена команда /pame - установить описание персонажа (сохраняется при перезаходе)
- Администраторам добавлена команда /apame - удалить описание персонажа у игрока
- Теперь при бане/варне слетает админка
- Переписано обнуление игроков при подключении/отключении с сервера
- Теперь в 24/7 можно купить шашку Taxi и работать таксистом на личном авто, при этом трудоустраиваться не нужно (/taxi)
- В /lmenu лидер теперь может изменять цвет организации в формате hex-color
- Команда /logs теперь работает исправно (просмотр последних 25 действий администратора к игроку)
- Теперь в личном меню игрок может посмотреть 25 последних наказаний на своём аккаунте
- Теперь каждый PayDay обновляется рейтинг семей (рейтинг даётся семье если игрок лидер, имеет VIP или PREMIUM)
- Администраторам 6 уровня добавлена команда /bizlock (заблокировать доступ к бизнесу)
- В /apanel для 5 уровней добавлен топ донатеров
- Добавлена команда /jp (получить jetpack) для администраторов 3 уровня
- В /apanel возвращены настройки администратора (информация о подключении игроков, просмотр килллиста)
- Добавлена реклама на сервер с полезной информацией
- Добавлена система подсказок (/hint). Теперь с получением нового уровня, игроку будет доступна подсказка об игре на сервере (пока сделал для 3 уровней)
- Добавлен TextDraw телефона (показывается дата, можно позвонить, посмотреть контакты, отправить смс)
- Убраны команды /contacts, /call - вместо них добавлена /phone (меню телефона)
- Исправлена смена имени за донат и /okay
- Теперь корректно списывается донат (сохранение)
- Исправлен баг, когда по окончанию войны за территорию у бандитов не пропадали 3D текста над головой
- Переписаны гангзоны (теперь ровные квадратики, всего территорий)
- Добавлена админ комната (телепортироваться можно через /apanel)
- Добавлена команда /az, для того чтобы телепортировать игрока на собеседование в goalma.orgу
- В админ комнату добавлена общая статистика сервера

Нажмите для раскрытия

GTA Vice City skins pack

Я думаю, и даже знаю, что на этом сайте есть любители не только Сана, но и Вайс Сити. Поэтому этот пак для вас (Я не находил подобных паков).В него входят. Сонни, Кен, Рикардо Диаз, Полковник Кортез, Лэнс, Авери (Чувак в шляпе) и оружейник goalma.org

Конвертированный транспорт из GTA 4 и GTA 5

Полностью авторский пак транспорта, сконвертированного из GTA 4 и GTA 5 от _F_ (Birdie)! Пак насчитывает чуть больше goalma.orgлита актуальная VehFuncs версия от 10 новых моделей добавлено- 10 старых моделей обновлено- 13 моделей а

Mobile HUD

Мобильный Худ, который изменяет старый HUD на новый из GTA SA Mobile. За основу взята версия Hud'a Автором является DK22Pac. Я лишь настроил HUD под PC.

GTA Vice City Stories PC Edition Beta 3

Долгожданная 3-я Бета порта консольной игры GTA Vice City Stories на PC:-Весь Западный Остров+Starfish Island и Prawn Island-Первые 16 миссий оригинальной игры (до прибытия Ленса в Вайс Сити)-Больше оригинальных педов, машин и звуков-Атмосфера максим

CLEO+ v (Обновление от )

CLEO+ CLEOPlusОбновление от 01/10/Добавлено 28 новых команд! Новые моды могут работать только в этой новой версии;Настройки для всех команд были пересмотрены, и все теперь документировано в библиотеке Sanny Builder Library. Спасибо OrionSR;Выдел

CLEO (Обновление от )

CLEOCLEO — популярнейшее дополнения к серии игр Grand Theft Auto от Rockstar Games. CLEO расширяет возможности скриптинга и позволяет использовать тысячи уникальных модов, которые изменяют и дополняют процесс goalma.orgение от Добавлена п

Колесо оружия

Простое и удобное колесо оружия, не выбивающееся из общего стиля goalma.orgение v Исправлена ошибка, когда можно было менять оружие во время миссии OG Loc- Исправлены ошибки, когда можно было менять оружие во время телефонного звонка, во время

Радио из GTA Vice City

После выхода моего мода "радио из GTA VCS" некоторые пользователи попросили выложить радио из обычного "GTA VC" так вот это goalma.orgе и наслаждайтесь музыкой!PS: Кому нужно "Радио из GTA Vice City Stories"

GTA: Vice TakeDown (DEMO v4)

Было добавлено 11 миссий, улучшен свободный режим и обновлены прошлые миссииСоздатели модификации:Naloger — Основатель проекта, разработчик, скриптер, модмейкер, маппер. —
(!Left && Right)))

If – это условный оператор, в скобках перед оператором пишется условие. После скобок точка с запятой
не ставится. В фигурных скобках пишется код который выполнится, если условие истинно. Если условие ложно,
код не выполнится. Else – это также условный оператор, но он выполняет свои функции, только в том случае,
если условие в if ложно. То есть, оператор if можно назвать как оператор «если», а еlse как оператор «иначе».
Давайте поставим простейшее условие. У нас есть две заранее проинициализированных переменных:

1 new a = 5;
2 new b = 25;

Поставим такое условие, если a < b, в консоль сервера выведется текст: «a меньше b». Если же значение
переменной a не меньше b, в консоль сервера выведется текст: «a больше b».

1 if(a < b)
2 {
3 print(“a меньше b”);
4 }
5 else
6 {
7 print(“a больше b”);
8 }

В данном примере выполнится кол в if, так как 5 меньше Но что если a равно b. Тогда мы поступим
следующим образом: (между строкой) вставим, операторы else if и условие, в общем, так как показано на
примере ниже:
1 if(a < b)
2 {
3 print(“a меньше b”);
4 }
5 else if (a == b)
6 {
7 print(“a равно b”);
8 }
9 else
10 {
11 print(“a больше b”);
12 }

Для некоторых случаев совсем необязателен оператор else, например, в командах чата. Например,
случай такой, нам нужно, чтобы команда не выполнялась до тех пор, пока игрок не авторизуется на сервере.
Мы пишем условие внутри команды, при котором команда не выполнится, и ставим в конце кода return 1. В
приведенном ниже примере Return завершает работу функции OnPlayerCommandText и не дает ей
выполниться до конца. Под данным условием уже можно будет писать код команды.

1 public OnPlayerCommandText(playerid, cmdtext[])


2 {
3 if (strcmp("/mycommand", cmdtext, true, 10) == 0)
4 {
5 if (pLogged[playerid] == false)
6 {
7 SendClientMessage(playerid,0xAAAA,”Вы не авторизованы на сервере”);
8 return 1; // Если это условие истинно, функция прекращает работу на этом месте
9 }
10 // Код команды
11 return 1;
12 }
13 return 0;
14 }
Урок №07 – Оператор инкремента и декремента

Инкремент увеличивает значение переменной на единицу, а декремент наоборот уменьшается значение


переменной на единицу. Инкременты и декременты используются в циклах, о которых я расскажу на
следующем уроке. У нас есть одна из переменных из прошлого урока, мы можем ее инкрементировать или
наоборот декрементировать двумя способами: с помощью pre и post инкремента или декремента.
Pre-инкремент/декремент или (префиксный инкремент/декремент) увеличивает/уменьшает значение
переменной в данном примере a на единицу, а затем возвращает ее значение.

1 ++a;

Post-инкремент/декремент или (постфиксный инкремент/декремент) сначала возвращает значение


переменной, а затем увеличивает/уменьшает ее значение на единицу.

1 a++;

Когда мы прибавляем к значению переменной единицу при помощи инкремента, таким образом, мы
инкрементируем переменную. Когда мы отнимает от значения переменной единицу при помощи декремента,
таким образом, мы декрементируем переменную.
Разницу между префиксным или постфиксным инкрементом и декрементов вы увидите в следующем
примере, для этого в функции OnGameModeInit нужно добавить эти строчки и запустить сервер.

1 new a = 25;
2 printf(“%d”,a++);

В вышеуказанном примере показана работа постинкремента. Мы увидим число 25 а не 26, потому что
постинкремент сначала возвратит нам старое значение переменой до ее инкрементирования. Если мы
поставим вместо постинкремента – преинкремент, то мы увидим число Аналогично и с декрементом.
Урок №08 – Циклы while и do while

Цикл While и любой другой цикл, повторяет свою функцию бесконечно до тех пор, пока его условие
истинно. Если его условие будет ложно, цикл прекращает работу. Цикл выглядит следующим образом:

1 new a;
2 while(a <= 3)
3 {
4 a++;
5 print("Hello, World!");
6 }

Как это работает? Все очень просто. Цикл проверяет условие, если, а меньше или равно 5, он выполняет
свою функцию. В вышеуказанном примере так оно и есть, так как наша переменная была создана, но не
проинициализирована, то есть ей не задано значение и оно равно – 0. Инкрементируем переменную Post-
инкрементом. То есть сначала возвращается старое значение, а потом только оно увеличивается на единицу и
затем идет печать текста «Hello, World!» в консоль сервера функцией print. В итоге мы в консоли сервера
получим четыре раза текст «Hello, World!».
Перейдем к следующему циклу, do while. Если while сначала проверял условие, а затем выполнял свою
функцию, то do while делает все с точностью да наоборот. Сначала он выполняет свою функцию, а потом
проверяет условие.
Чтобы сделать из вышеуказанного цикла, цикл do while, достаточно верхнюю часть цикла вместе с
условием перенести под фигурные скобки и в конце после условия после закрывающей круглой скобки
поставить точку с запятой, а на то место, откуда вы вырезали while, поставить оператор do.

1 new a;
2 do
3 {
4 a++;
5 print("Hello, World!");
6 }
7 while(a <= 3);

Тут принцип работы аналогичен, и в результате мы получаем то же самое, что и при простом цикле while.
Урок №09 – Цикл for

Цикл For – это, по сути, упрощенный цикл While, поэтому я не буду долго заострять на этом внимание.
Сейчас вы убедитесь на примере из прошлого урока, который продемонстрирован ниже:

1 new a;
2 while(a <= 3)
3 {
4 a++;
5 print("Hello, World!");
6 }

Ниже приведена конструкция цикла For:

1 for(переменная; условие; операция с переменной-счетчиком)


2 {
3 //здесь будет код, который выполнится если условие цикла истинно;
4 }

Цикл for выполнять аналогичные функции, что и цикл while. Сейчас я покажу, как превратить данный цикл
в цикл for. Для этого, оператор while заменяем на for. Переменную a вместе с оператором new и точкой
запятой перемещаем перед условием в скобках, в конце условия также ставим точку с запятой. Берем
инкремент полностью, как мы брали переменную и перемещаем после условия. А все остальное остается на
месте, в результате мы получаем цикл For.

1 for(new a; a <= 3; a++;)


2 {
3 print("Hello, World!");
4 }

И на заметку, не рекомендуется скрипт перегружать циклами. И еще что особенно важно нежелательно
использовать конструкцию: «цикл в цикле» это дает сильную нагрузку на сервер.
Но тем не менее циклы очень полезны. Их очень удобно использовать для поиска по массивам, а также
для выполнения одной и той же операции для всех или определенных игроков одновременно.
Урок №10 – Операторы Break и Continue

Данные операторы используются в циклах: for, while, do-while. Оператор break завершает работу цикла,
а оператор continue, пропускает оставшееся действие цикла и повторяется снова. Рассмотрим два оператора в
действии. У нас есть цикл for из прошлого урока:

1 new a;
2 while(a <= 3)
3 {
4 a++;
5 print("Hello, World!");
6 }

Сделаем так, чтобы в консоль сервера вывелся текст «Hello World!» не 3, а 2 раза. Вспоминаем урок про
условные конструкции и создаем такое условие: если a равен 3, то завершаем работу цикла.

1 new a;
2 while(a <= 3)
3 {
4 if(a == 2)
5 {
6 break;
7 }
8 a++;
9 print("Hello, World!");
10 }

Если вместо оператора break подставить оператор continue результат получится тот же. Вы спросите, в
чем же тогда разница, если результат один и тот же. В этом цикле есть один подводный камень. Если вы
прочитаете последовательность действий цикла, то поймете в чем причина. А причина вот в чем:
Цикл проверяет последовательно условия, начиная с 0, так как переменная а – равна 0. В первом и во
втором случае, условия истинны, так как 0 и 1 меньше 3 и не равны 2. Соответственно в чат выводится 2 раза
текст «Hello, World». Что break, что continue они не дают до конца выполнить цикл, то есть все функции, что
находятся после самого оператора (инкремент и функцию print).
Для того, чтобы увидеть отличие этих двух операторов нужно инкремент переместить перед условием,
вот так:

1 new a;
2 while(a <= 3)
3 {
4 a++;
5 if(a == 2)
6 {
7 break;
8 }
9 print("Hello, World!");
10 }

В случае с оператором break, в консоль выведется текст «Hello, World!» всего один раз. Так как
пропускается одно условие из-за инкремента, где переменная «а» должна быть равна 0. В случае с оператором
continue текст выведется три раза, так как оператор пропускает под собой все оставшиеся функции цикла и
начинает следующий цикл.
Урок №11 – Форматирование строки c помощью printf и format

С помощью оператора format можно передать в строку значения переменных или функций, других
строк и просто текст, который нужно передать в строку. У функции если не считать, сколько всего будет
передано в строку, всего 4 аргумента. Первый аргумент, это имя строки, в которой сохранятся
форматированная строка. Второй аргумент длина этой строки, обычно вместо длины строки используют
функцию sizeof с именем строки в качестве аргумента этой функции. Затем третьим аргументом следует текст в
кавычках и управляющие символы. Управляющие символы приведены в таблице ниже:

%b Бинарный тип
%c Символьный тип
%d, %i Целочисленный тип
%f Число с плавающей точкой – вещественный тип
%s Строка

В строку можно передать неограниченное количество значений, сколько значений передается, столько
и управляющих символов в строке. Главное соблюдать типы передаваемых данных. При передачи целого числа
в строку, нужно использовать управляющий символ (%d) целочисленного типа, при передачи десятичного числа
(%f) управляющий символ вещественного типа, при передаче другой строки нужно использовать управляющий
символ - %s и так далее.
Привожу для следующего примера инициализированные строки и заранее одну пустую строку где будет
сохранен форматированный текст:

1 new Pawn[6] = “world!”;


2 new Samp[7] = “Hello, ”;
3 new string[13];

Принцип работы функции такой. Он берет значение из переменной Samp указанной в нижеприведенном
примере и подставляет вместо управляющего символа %s, получает текст «Hello, world!».

1 format(string,sizeof(string),”%s world!”,Samp);

Можно передать в строку сразу 2 или более значения. Для этого в 3-ем аргументе в кавычках ставим
управляющий символ в то место, куда нужно будет вставить значение. Затем в зависимости от того куда мы
поставили управляющий символ, в 4-ом аргументе через запятую указываем строку или переменную, из
которой будет браться значение. Главное соблюдать порядок. Первая переменная или строка в 4-ом аргументе
передается свое значение в 1-ый управляющий символ в 3-ем аргументе, вторая во второй, третья в третий, как
показано на примере ниже:

1 format(string,sizeof(string),”%s %s”,Samp, Pawn);

Можно не указывать ни строк, ни переменных, а текст, который нам нужно вставить, вот пример:

1 format(string,sizeof(string),”%s” , ”Hello, world!”);

Все вышеуказанные примеры имеют одинаковый результат. Кроме всего вышеуказанного в строку
можно вставлять следующее символы, приведенные в таблице:
\b backspaсe
\f Form feed
\n переход на новую строку
\r возврат каретки
\t табуляция
\v вертикальная табуляция
\' одиночная кавычка
\" двойные кавычки
\? вопросительный знак

Функция printf аналогичная, она как функция format только без первого и второго аргумента, и
значительно проще, так как ей не нужно никаких строк. Она выводит форматированную строку в консоль. Вот
так выглядит функция, аналогичная функции на примере выше.

1 printf(”%s” , ”Hello, world!”);

Итак, для закрепления урока рассмотрим нижеприведенный пример:

1 public OnPlayerConnect(playerid)
2 {
3 new plname[MAX_PLAYER_NAME];
4 new string[50];
5 GetPlayerName(playerid,plname,24);
6 format(string,sizeof(string),"*** %s зашел на сервер. (ID:%d)",plname,playerid);
7 SendClientMessageToAll(COLOR_GREEN,string);
8 return 1;
9 }

Для того чтобы вывести сообщение всем игрокам, существует функция SendClientMessageToAll. В
скобках функции два аргумента. Первый аргумент, цвет сообщения, куда мы подставляем HEX-код цвета либо
заменяем его константой для удобства, второй аргумент – текст, выводимый в чат всем игрокам.
Итак, для того чтобы вывести сообщение всем игрокам, для начала нам нужно 2 строки (одномерных
массива). MAX_PLAYER_NAME – это встроенная константа, она равна 24, то есть максимальной длине имени
игрока. Первая строка будет хранить имя игрока, вторая будет хранить отформатированный текст сообщения,
передаваемый игрокам. Функция GetPlayerName получает имя игрока, и как показано во 2 аргументе функции,
передает в переменную plname это имя.
Имя нам известно, ID игрока тоже, теперь пора приступить к форматированию строки. Пишем функцию
format и первым аргументом функции указываем переменную string, где будет храниться сообщение. Вторым
аргументом при помощи функции sizeof, передаем размер этой переменной. В третьем аргументе функции
пишем текст. Имя, это строка, для передачи в строку, нужен управляющий символ «строка» (%s), ID игрока, это
целое число, для передачи в строку, нужен управляющий символ целочисленного типа (%d).

1 format(string,sizeof(string),"*** %s зашел на сервер. (ID:%d)",plname,playerid); // Это правильно

Функция по порядку передаст значения между 3 и 4 аргументами функции. Из переменной plname в


первый управляющий символ в строке (%s), ID игрока мы передаем из параметра playerid во второй
управляющий символ (%d).

1 format(string,sizeof(string),"*** %s зашел на сервер. (ID:%d)",playerid,plname); // Это не правильно

Выше показан заведомо неправильный пример. Мы не можем передать ID игрока то есть целое число в
управляющий символ «строка», так как число это не текст (не строка). Имя игрока мы также не можем передать
в управляющий символ целочисленного типа, так как строка (или текст) это не число. При форматировании
строки соблюдайте типы передеваемых данных и управляющие символы для этих типов.
Урок №12 – Арифметические выражения в Pawn

Переменные целочисленного и вещественного типа, могут принимать различные числовые значения. Со


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

Оператор Обозначение Примерное использование


Оператор сложения + result = pawn + samp;
Оператор вычитания - result = pawn - samp;
Оператор умножения * result = pawn * samp;
Оператор деления / result = pawn / samp;
Оператор деления с остатком % result = pawn % samp;

Примеры, указанные в таблице выше четко отображают простейшие математические операции между
значениями двух переменных pawn и samp. Давайте рассмотрим данные примеры на переменных, которые
приведены ниже:

1 new pawn = 24;


2 new samp = 6 ;
3 new result;

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

1 result = pawn + samp; //result = 30


2 result = pawn - samp; //result = 18
3 result = pawn * samp; //result =
4 result = pawn / samp; //result = 4

Ну и напоследок о делении с остатком, в нижеприведенном примере показан пример деления с


остатком:

1 result = (pawn + samp) % 7; //result = 2

Как получилось 2? Все просто, складываем значения переменных, так как они в скобках и делим на 7. Мы
получаем приблизительно 4,2. Если умножим 4 на 7, получим 28, ближайшее к 30 число. Если отнимем 30 от 28,
получим тот самый остаток.
Решим еще одно выражение, пусть переменная pawn будет равна В итоге сумму переменных то есть
36 делим на 7 и получаем 5. Умножаем 5 на 7, получаем Отнимаем его из 36, в результате чего получаем тот
остаток 1.
Урок №13 – Оператор switch

Оператор switch – это оператор выбора. Он удобен в первую очередь тем, что может заменить много
условий if, которые проверяют значение одной переменной. Представим себе такой пример. У нас есть
целочисленная переменная pawn, значение которой нужно проверить. И в зависимости от того, какое значение
у данной переменной выполнить соответствующий код.

1 new pawn;
2 switch(samp)
3 {
4 case 0: //аналог условия if(samp == 0)
5 {
6 print(”Переменная samp = 0”);
7 }
8 case 1: //аналог условия if(samp == 1)
9 {
10 print(”Переменная samp = 1”);
11 }
12 }

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

Но, что если переменная не попадает ни под одно условие в операторе switch. Тогда можно
использовать default, он выполняется только в том случае, если switch не попадает ни в один из case.

1 new pawn;
2 switch(samp)
3 {
4 case 0: printf(”Переменная samp = 0”);
5 case 1: printf(”Переменная samp = 1” );
6 default: printf(”Переменная samp = %d” , samp);
7 }

То же самое можно сделать и с помощью обычной условной конструкции if, тогда код выглядел бы
следующим образом:

1 if(samp == 0)
2 {
3 printf(”Переменная samp = 0”); //все равно что case 0
4 }
5 else if(samp == 1)
6 {
7 printf(”Переменная samp = 1”); //все равно что case 1
8 }
9 else
10 {
11 printf(”Переменная samp = %d” , samp); //все равно что default
12 }

Этот способ удобнее и читабельнее чем много if конструкций идущих подряд. Еще одно отличие, что в
case можно указать диапазон значений куда проще, чем в обычной условной конструкции if.

1 case printf(”Переменная samp = %d” , samp); //условие внутри switch


2 if(samp > 0 && samp < 2) printf(”Переменная samp = %d” , samp); //то же условие, но уже в if

Для закрепления знаний по данному урока продемонстрирую вам один из примеров использования
данного оператора в функции OnPlayerDisconnect. В данной функции параметр reason возвращает ID причины
отключения игрока от сервера. Благодаря этому параметру можно сделать вот такой код оповещения игроков
о уходе игрока с сервера с пояснением причины.
1 switch(reason)
2 {
3 case 0:
4 {
5 GetPlayerName(playerid,plname,24);
6 format(string,sizeof(string), "*** %s вылетел с сервера.(ID:%d)",plname,playerid);
7 SendClientMessageToAll(0xAAAA,string);
8 }
9 case 1:
10 {
11 GetPlayerName(playerid,plname,24);
12 format(string,sizeof(string), "*** %s покинул сервер.(ID:%d)",plname,playerid);
13 SendClientMessageToAll(0xAAAA,string);
14 }
15 case 2:
16 {
17 GetPlayerName(playerid,plname,24);
18 format(string,sizeof(string), "*** %s был кикнут.(ID:%d)",plname,playerid);
19 SendClientMessageToAll(0xAAAA,string);
20 }
21 }

Этот пример можно упростить с помощью вот такой stock функции.

1 stock GetName(playerid)
2 {
3 new nick[MAX_PLAYER_NAME];
4 GetPlayerName(playerid, nick, sizeof(nick));
5 return nick;
6 }

В этом случае функцию GetPlayerName можно просто убрать из switch, а вместо переменной plname
подставить вызов данной функции. Саму переменную plname также нужно удалить.
Урок №14 – Создание простейшей команды

Функция OnPlayerCommandText, выполняется, в том случае если игрок введет команду в чат. Первый
параметр функции, это ID игрока, который ввел команду, второй параметр, это строка, которая хранит
введённую игроком команду. Чтобы создать простейшую команду, нам нужно проверить правильно ли ввел ее
игрок. Для этого нам надо сравнить введенную игроком команду с ее оригиналом.
Для сравнивания строк существует функция strcmp.

1 public OnPlayerCommandText(playerid, cmdtext[])


2 {
3 if(strcmp("/mycommand", cmdtext, true, 10) == 0)
4 {
5 //код команды
6 return 1;
7 }
8 }

strcmp – имеет четыре аргумента. Первый аргумент имя строки, которая будет сравниваться с другой
строкой, второй аргумент – имя строки, с которой будет сравниваться предыдущая строка. Третий аргумент
логический аргумент. Если указать true – то при сравнении строк регистр букв не учитывается, по умолчанию,
если даже его не указать регистр учитываться будет.
Хочу отметить, что если вы не указали третий аргумент, то и четвертый аргумент уже указать не
получится, поскольку пустой аргумент оставлять нельзя. Также если третий аргумент не обязательный для
указания, а четвёртый аргумент обязательный, то третий аргумент, так или иначе, придется указать, пропускать
аргументы нельзя. Так как у функции strcmp два последних аргумента не обязательны, их можно не указывать,
поскольку они последние. Сама функция возвращает 0 – если совпадение %, в противном случае возвратит 1.
Ну а дальше все зависит от вас. Если условие по сравнению команд выполняется, команда обязательно
должна возвратить true (return 1;), потому что функция OnPlayerCommandText всегда возвращает false. Если
функция возвратит false, в чат будет выведено сообщение «Неизвестная команда», а сама команда сработает.
Урок №15 – Перебор значений в массиве

Что если нужно узнать, если определенное число в массиве или нет. Но функции поиска по массиву в
Pawn нет. Что делать? Поможет только перебор значений. Для этого нам нужен сам массив и цикл for. Вы уже
знакомы с массивами и циклами из прошлых уроков. Сейчас я на простом примере покажу, как сделать перебор
значений в массиве. И при появлении совпадения, должен выполниться скрипт.
Допустим, у нас есть большой одномерный массив со всеми ID машин, т. е только легкового транспорта.
Но сначала нам нужна новая автовызываемая функция, допустим, она будет называться IsPlayerInBike. В
скобках пишем два параметра – playerid и vehicleid. Функция будет выглядеть следующим образом:

1 stock IsPlayerInBike(playerid,vehicleid)
2 {
3 return 0;
4 }

Поскольку функция не нуждается в таймере, то есть ее не нужно выполнять по истечению


определенного количества времени или повторять, то лучше сделать эту функцию не через public, а через stock.
Функция должна возвращать 0, потому что мы делаем функцию проверки и соответственно функция должна
возвращать либо true, либо false. Внутри функции мы добавим одномерный массив.

1 stock IsPlayerInBike(playerid,vehicleid)
2 {
3 new IsBikeA[10] = {,,,,,,,,,};
4 return 0;
5 }

Теперь нам нужно присвоить второму аргументу нашей функции vehicleid - ID транспорта, в котором
сидит игрок. Чтобы узнать ID машины, существует функция GetPlayerVehicleID, которая возвращает ID
транспорта, в котором сидит игрок. Для этого мы присвоим аргументу значение, которое возвратит нам
вышеуказанная функция. Делаем это следующим образом, под массивом мы добавляем следующую строку:

1 vehicleid = GetPlayerVehicleID(playerid);

Дальше нам нужно проверить сидит ли игрок в машине с указанным ID. Функция IsPlayerInVehicle,
проверяет: сидит ли игрок в транспорте с указанным во 2 аргументе функции ID транспорта. На следующей
строчке пишем следующую условную конструкцию;

1 if(IsPlayerInVehicle(playerid,vehicleid))
2 {
3
4 }

В теле этой условной конструкции будет располагаться цикл, который будет искать требуемое значение
в массиве. Условие цикла должно быть следующее, если I < Переменная I у нас, это переменная счетчик, как
в любом цикле. То есть мы должны выполнить цикл 10 раз, так как в массиве у нас всего 10 ячеек или ID 10
мотоциклов.

1 for(new i = 0; i < 10; i++)


2 {
3 if(GetVehicleModel(vehicleid) == IsBikeA[i]) return true;
4 }

Если совпадение найдено, функция должна вернуть true, если нет false. Под циклом обязательно должен
быть return 0, так как если совпадений не найдется, функция возвратит false.
Урок №16 – Расстановка транспорта

Расставить транспорт можно несколькими способами:


Расстановка транспорта с помощью Samp Debug:
Для начала запускаем Samp Debug из папки с GTA San Andreas. Как только все загрузится, вы
появляетесь Карлом Джонсоном возле надписи Vinewood.
Теперь с помощью команды /v вызываем нужную нам машину, например INFERNUS, для этого пишем в
чате /v и получаем машину. Если вы не знаете ID машины, которую хотите вызвать, введите /vmenu, и вы
попадете в меню выбора транспорта.
Садитесь в машину и паркуйте ее там, где вам нужно. После этого, не выходя из машины, вводите
команду /save. В директории: Мои документы\GTA San Andreas User Files\Samp\ будет файл goalma.org, с
примерно таким содержанием:

1 AddStaticVehicle(, , , , , 0, 0);

Функция AddStaticVehicle может использоваться только внутри автовызываемой функции


OnGameModeInit, в других функциях она работать не будет.
Можно расставить транспорт с помощью фильтрскриптов, таких как cars. Данный скрипт прилагается к
учебнику. Достаточно ввести ID транспорта, как команда, например / и вы окажетесь прямо в машине.
Также для расстановки транспорта существует функция AddStaticVehicleEx, большое отличие данной
функций от вышеуказанной в том, что данная функция возвращает ID созданного транспорта, а вышеуказанная
функция ничего не возвращает. Это расширенная функция.

1 AddStaticVehicle(, , , , , 0, 0, );

Последняя цифра в функции указывает на время в миллисекундах до следующего появления транспорта


на точке возрождения (spawn).
Урок №17 – Проверка игрока в зоне

Чтобы проверить игрока в зоне, нам нужно написать в любом месте скрипта такую функцию:

1 stock IsPlayerInArea(playerid, Float:minx, Float:miny, Float:maxx, Float:maxy)


2 {
3 new Float:X, Float:Y, Float:Z;
4 GetPlayerPos(playerid, X, Y, Z);
5 if(X >= minx && X <= maxx && Y >= miny && Y <= maxy)
6 {
7 return 1;
8 }
9 return 0;
10 }

Теперь мы можем ставить такие условия:

1 if(IsPlayerInArea(playerid,,,,))

Последняя цифра в функции указывает на время в миллисекундах до следующего появления транспорта


на точке возрождения (spawn). Эту проверку можно поместить, например, внутри команды.
Теперь о том, как правильно получить все 4 координаты, указанные в скобках функции. Синтаксис
условия такой:

1 if(IsPlayerInArea(playerid,Xmin,Ymin,Xmax,Ymax))

Итак, встаем в левый нижний угол создаваемой вами зоны, получаем координаты командой save. Далее
встаем в правый верхний угол и снова получаем координаты. Допустим, мы уже получили вот такие
координаты:

1 AddPlayerClass(0,,,,,0,0,0,0,0,0);
2 AddPlayerClass(0,,,,,0,0,0,0,0,0);

Нужные нам координаты, я выделил цветом, т.е. это все координаты X и Y. Берем из этих координат
минимальную X-координату - Ставим ее первой в скобках, затем через запятую минимальную Y-
координату - Дальше то же самое, но уже максимальные координаты. Должно получиться так:

1 if(IsPlayerInArea(playerid,,, ,))
Урок №18 – Проверка игрока в кубе

Чтобы проверить игрока в кубе, нам нужно написать в любом месте скрипта такую функцию:

1 stock IsPlayerInCube(playerid, Float:xmin, Float:ymin, Float:zmin, Float:xmax, Float:ymax, Float:zmax)


2 {
3 new Float:x, Float:y, Float:z;
4 GetPlayerPos(playerid, x, y, z);
5 if(x > xmin && y > ymin && z > zmin && x < xmax && y < ymax && z < zmax)return 1;
6 return 0;
7 }

Теперь мы можем ставить такие условия:

1 if(IsPlayerInCube(playerid, , , , , , ))

Эту проверку можно поместить, например, внутри команды. Теперь о том, как правильно получить все 4
координаты, указанные в скобках функции. Синтаксис условия такой:

1 if(IsPlayerInCube (playerid,Xmin,Ymin,Zmin,Xmax,Ymax,Zmax))

Итак, встаем в левый нижний угол создаваемой вами зоны, получаем координаты командой save. Далее
встаем в правый верхний угол и снова получаем координаты. Допустим, мы уже получили вот такие
координаты:

1 AddPlayerClass(0,,,,,0,0,0,0,0,0);
2 AddPlayerClass(0,,,,,0,0,0,0,0,0);

Нужные нам координаты, я выделил цветом, т.е. это все координаты X и Y. Берем из этих координат
минимальную X-координату - Ставим ее первой в скобках, затем через запятую минимальную Y-
координату - Дальше то же самое, но уже максимальные координаты. Должно получиться так:

1 if(IsPlayerInCube(playerid,,,, , ,))


Урок №19 – Проверка игрока в радиусе

Чтобы проверить игрока в радиусе, нам нужно написать в любом месте скрипта такую функцию:

1 stock PlayerToPoint(Float:radi, playerid, Float:x, Float:y, Float:z)


2 {
3 if(IsPlayerConnected(playerid))
4 {
5 new Float:oldposx, Float:oldposy, Float:oldposz;
6 new Float:tempposx, Float:tempposy, Float:tempposz;
7 GetPlayerPos(playerid, oldposx, oldposy, oldposz);
8 tempposx = (oldposx -x);
9 tempposy = (oldposy -y);
10 tempposz = (oldposz -z);
11 if (((tempposx < radi) && (tempposx > -radi)) && ((tempposy < radi) && (tempposy > -radi)) && ((tempposz <
radi) && (tempposz > -radi)))
12 {
13 return 1;
14 }
15 }
16 return 0;
17 }

В отличие от проверки в зоне или кубе тут достаточно получить 1 раз координаты и вручную
вписать радиус. Написав автовызываемую функцию PlayerToPoint, мы можем ставить такие условия:

1 if(PlayerToPoint(,playerid, , , ))

Эту проверку можно поместить, например, внутри команды. Но в целях оптимизации


рекомендуют использовать стандартную функцию под названием IsPlayerInRangeOfPoint, это аналог
данной функции, в котором только первый и второй параметры переставлены местами. Синтаксис
функции такой:

1 IsPlayerInRangeOfPoint(playerid, Float:range, Float:x, Float:y, Float:z);

Соответственно проверка при использовании данной функции выглядела бы таким образом:

1 if(IsPlayerInRangeOfPoint(playerid, , , , ))


Урок №20 – Создание простого диалога
В дальнейших уроках мы рассмотрим все типы диалогов и работу с ними. Для начала я ознакомлю вас со
всеми диалогами, а затем в каждом уроке мы будем рассматривать по каждому типу диалога. Итак, приступим
к теории. Диалоги бывают трех типов:

0 - DIALOG_STYLE_MSGBOX - обычный диалог с 2мя кнопками,


1 - DIALOG_STYLE_INPUT - диалог с полем для ввода,
2 - DIALOG_STYLE_LIST - список из нескольких элементов.
3 - DIALOG_STYLE_PASSWORD – диалог с полем ввода пароля.

Вызывается диалоговое окно функцией ShowPlayerDialog, структура функции такая:

1 ShowPlayerDialog(playerid,<ID диалога>,<ID стиля>,<Название>,<Текст>,<Первая кнопка>,<Вторая>);

Обычно, чтобы не запоминать цифры и не писать длинное название стилей диалогов, я заменяю их
такими константами:

1 #define DSL DIALOG_STYLE_LIST


2 #define DSI DIALOG_STYLE_INPUT
3 #define DSM DIALOG_STYLE_MSGBOX
4 #define DSP DIALOG_STYLE_PASSWORD

Для написания основного текста диалогового окна вы можете использовать нижеприведенную таблицу:

\b backspaсe
\f Form feed
\n переход на новую строку
\r возврат каретки
\t табуляция
\v вертикальная табуляция
\' одиночная кавычка
\" двойные кавычки
\? вопросительный знак

Итак, переходим к практике или к разбору первого стиля: DIALOG_STYLE_MSGBOX. Рассмотрим


обычный пример: Мы вводим команду, и появляется диалоговое окно с запросом о подтверждении
выполнения команды. Для начала мы напишем скрипт простейшей команды в автовызываемую функцию
OnPlayerCommandText.

1 if (strcmp("/test", cmdtext, true, 10) == 0)


2 {
3 return 1;
4 }

Затем с помощью функции ShowPlayerDialog мы вызовем данное диалоговое окно. Так как вызывать
меню мы будем с помощью команды, то и пишем данную функцию, приведенную ниже внутри нее.

1 ShowPlayerDialog(playerid,0,DSM,"Подтверждение","Вы точно хотите выполнить команду","Да","Нет");

Цифра 0 – это идентификатор (ID) диалога, у каждого диалога свой ID. После идентификатора пишем
название стиля диалога, но я заменил его константой, поэтому я написал DSM (DIALOG_STYLE_MSGBOX). После
стиля пишем название диалога. Далее пишем текст диалога и название первой и второй кнопки.
В общем, код будет выглядеть следующим образом:
1 if (strcmp("/test", cmdtext, true, 10) == 0)
2 {
3 ShowPlayerDialog(playerid,0,DSM,"Подтверждение", "Вы точно хотите выполнить команду","Да","Нет");
4 return 1;
5 }

А диалоговое окно будет выглядеть так:

Но данное диалоговое окно работать не будет, если мы не напишем для него функцию. Допустим, наша
команда выдаст в чат всю информацию об игроке, т.е. при нажатии кнопки «Да» все так и будет, но при нажатии
кнопки «Нет», мы выдадим сообщение красным цветом о том, что данная команда не была выполнена.
Писать функцию диалогового окна мы будем в автовызываемой функции OnDialogResponse. Сначала
внутри функции мы напишем условную конструкцию, которая будет проверять, что данное диалоговое окно
было вызвано. Код условия такой:

1 if(dialogid == 0) //Условие: если мы вызвали диалог с ID = 0


2 {
3
4 }

Условие проверяет: было ли вызвано диалоговое окно с ID = 0. Внутрь этой условной конструкции
добавляем еще одно условие:

1 if(response) //Условие: если мы нажали первую кнопку


2 {
3
4 }
5 else //Условие: если мы нажали вторую кнопку
6 {
7
8 }

Условие проверяет, была ли нажата первая кнопка, если нажата вторая кнопка, то выполняется код
после else. Внутри этой условной конструкции для первой кнопки мы пишем следующий код.

1 if(response)
2 {
3 new string[]; //Переменная с основным текстом диалога
4 new plname[MAX_PLAYER_NAME]; //Переменная с именем игрока
5 new money; //Переменные для хранения кол-ва наличных денег игрока
6 new Float: health, Float: armor; //Переменные для хранения кол-ва здоровья и брони игрока
7 GetPlayerName(playerid,plname,MAX_PLAYER_NAME); //Записываем имя игрока в переменную plname
8 money = GetPlayerMoney(playerid); //Записываем деньги игрока в переменную money и т.д.
9 GetPlayerHealth(playerid,health);
10 GetPlayerArmour(playerid,armor);
12 format(string,sizeof(string),”Игрок: %s(ID:%d). Деньги: %d $.\n Здоровье: %.2f\n Броня: %.2f”,
plname,playerid,money,health,armor);
13 ShowPlayerDialog(playerid,1,DSM,"Информация об игроке",string,"ОК","");
14 }else{}

Сначала мы создаем все необходимые переменные, а потом получаем данные и сразу же их записываем
их во всех переменные. Обратите внимание на функцию GetPlayerMoney, в скобках она имеет всего один
аргумент (playerid), в отличие от других, и она возвращает количество денег игрока. Поэтому мы присваиваем
переменной money, эту функцию, которая возвратит значение, которое и будет значением этой переменной.
Еще обратите внимание на %.2f, я мог бы использовать просто %f, как показано в таблице. Точка и цифра
означает, сколько чисел должно быть после запятой у десятичного числа. Дальше мы форматируем сообщение,
после чего вызываем новое диалоговое окно с новым ID. Обратите внимание, что имя второй кнопки не
указано, в таком случае, эта кнопка просто будет отсутствовать в диалоге. А вместо основного текста мы
подставляем переменную string в которой уже есть готовое отформатированное сообщение.
Второе диалоговое окно будет выглядеть следующим образом:

Вернемся к условию, если будет нажата вторая кнопка в первом диалоге, тут все просто без объяснений
в else пишем:

1 SendClientMessage(playerid,COLOR_RED,"Команда отменена");

Вот в принципе и все, В следующем уроке мы рассмотрим другой стиль диалога. Переходим к
следующему уроку.
Урок №21 – Создание простого диалога с полем ввода

В этом уроке мы переходим к разбору второго стиля диалога: DIALOG_STYLE_INPUT. Работать с


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

1 ShowPlayerDialog(playerid,0,DSI,"Отправить сообщение всем","Введите текст сообщения","ОК","Отмена");

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

1 #define DSI DIALOG_STYLE_INPUT

Итак, диалоговое окно мы создали, и оно будет выглядеть следующим образом.

Приступим к написанию функции для этого диалога. Как и в прошлом уроке, внутрь функции
OnDialogResponse, пишем условную конструкцию проверки на вызов диалога с ID = 0. Внутрь этой
условной конструкции пишем еще одну, проверку на нажатие кнопки. Дальше внутри этой проверки
будет еще одна проверка на то, что поле ввода у нас содержит какие-либо символы. Ведь мы же не
можем отправить пустой текст. Условная конструкция будет такая:

1 if(!strlen(inputtext))
2 {
3
4 }
5 else
6 {
7
8 }

Данную условную конструкцию мы пишем внутри условной конструкции if(response). А теперь я


вам объясню, что значит strlen и inputtext:
Strlen – возвращает количество символов в строке.
Inputtext – этот аргумент содержит в себе текст, который мы вводим в поле ввода.

В общем, думаю, вам будет все понятно, посмотрев нижеприведенный готовый скрипт, но все
же я вам кратко его объясню на всякий случай. Сначала идет проверка на вызов диалогового окна с ID
= 0. Мы данное окно вызывали функцией ShowPlayerDailog(playerid,0…); - я специально выделил
цифру, это dialogid. После проверки, внутри идет еще одна проверка на нажатие кнопки. Если нажата
кнопка 1, т.е. кнопка «ОК», идет следующая проверка на то, что в поле ввода есть какой-либо текст.
Если он есть, функция SendClientMessage отправляет в чат значение аргумента inputtext, т.е то, что
игрок введет в поле ввода диалогового окна. Если игрок не введет в поле ввода ничего, функция
SendClientMessage отправит в чат сообщение с ошибкой, о том, что текст сообщения не был введен в
поле ввода.

1 public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])


2 {
3 if(dialogid == 0)
4 {
5 if(response) //Если была нажата 1 кнопка
6 {
7 if(!strlen(inputtext)) //Если в поле не был введен текст при отправке
8 {
9 SendClientMessage(playerid,COLOR_RED,"Вы не написали текст сообщения в поле ввода");
10 return 1;
11 }
12 else
13 {
14 SendClientMessage(playerid,COLOR_WHITE,inputtext);
15 }
16 }
17 }
18 return 1;
19 }
Урок №22 – Создание простого диалога списка

В этом уроке мы переходим к разбору третьего стиля диалога: DIALOG_STYLE_LIST. Давайте


рассмотрим данный стиль диалога на следующем примере. Допустим нам нужно командой, вызвать
меню со списком оружия на выбор.
Создаем простейшую команду и внутрь ее пишем функцию вызова диалога. Так как это будет
список, нам нужно использовать \n – переход на новую строчку. Т.е. мы пишем название пункта \n
название пункта и снова \n.

1 if (strcmp("/weaponlist", cmdtext, true, 10) == 0)


2 {
3 ShowPlayerDialog(playerid,0,DSL,"Список оружия»,«Кольт\nКольт с глушителем\nПустынный орел", "Выбор", "Отмена");
return 1;
4 }
5

Диалог будет выглядеть следующим образом:

Перед тем как написать функцию для этого диалогового окна, давайте посмотрим на
следующую конструкцию приведенную ниже.

1 public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])


2 {
3 if(dialogid == 0)
4 {
5 if(listitem == 1) //Если был выбран 1 пункт списка
6 {
7 //Выполнить этот код
8 }
9 if(listitem == 2) //Если был выбран 2 пункт списка
10 {
11 //Выполнить этот код
12 }
13 }
14 return 1;
15 }

Вот так должен выглядеть код для данного стиля диалога. Тут мы проверяем значение listitem,
т.е. пункта списка которого мы выберем в диалоге. listitem = 1 – это кольт, значит, в условную
конструкцию listitem == 1 мы должны вписать функцию GivePlayerWeapon, чтобы дать оружие игроку.
1 if(listitem == 1) //Если был выбран 1 пункт списка
2 {
3 GivePlayerWeapon(playerid,22,); //Дать игроку кольт и патронов
4 }

То же самое делаем и для остальных listitem. Вписываем ту же строчку, только вместо 22,
пишем следующее: 23 – для кольта с глушителем, 24 – для пустынного орла (эти цифры, это ID модели
этого оружия). ID модели смотрите на странице «ID оружия».
Вообще, приведенный выше пример, очень схож с оператором switch, т.к. мы проверяем
значение одного аргумента и в зависимости от этого значения выполняем действие. Тоесть, это все
можно заменить на оператор switch, таким образом:

1 public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])


2 {
3 if(dialogid == 0)
4 {
5 switch(listitem)
6 {
7 case 1: //Если был выбран 1 пункт списка
8 {
9 //Выполнить этот код
10 }
11 case 2: //Если был выбран 1 пункт списка
12 {
13 //Выполнить этот код
14 }
15 }
16 }
17 return 1;
18 }

Точно также можно поступить и с параметром dialogid, кому как удобнее.


Урок №23 – Расстановка объектов в Ingame Object Editor

В этом уроке я научу вас создавать простые двери, открываемые по команде. Таким же
образом вы сможете потом ставить ворота и шлагбаумы. И начну я с фильтр скрипта Ingame Object
Editor. (данный скрипт прилагается к учебнику). Почему именно он, когда предлагают много раз MTA
Map Editor. Во-первых, это как один из простых способов расставить небольшое количество объектов,
если ставить много объектов, на это уйдет больше времени, чем в MTA Map Editor. Во-вторых, это
тоже было бы полезно знать. В-третьих, не нужно конвертировать код из map в pwn, все объекты
будут в вашем моде вместе с этим фильтр скриптом. Доступ к его опциям имеет только RCON
администратор, поэтому вам необходимо будет войти на сервер как RCON администратор.
Начнем с создания двери. Войдите на сервер как RCON администратор. Итак, вот место куда
мы, например, хотим поставить дверь.

Мы можем поставить деревянную дверь с ID = , это дверь, которая


открывается, когда ее толкаешь, но нам нет смысла сейчас ее ставить,
потому что мы делаем закрытую дверь, которую нужно будет открыть по
команде. Поставим дверь, например с ID = Итак, в чате пишем
следующую команду /oadd door. Команда /oadd – добавляет новый
объект, через пробел пишется ID объекта и далее имя объекта, любое.

Итак, мы создали нашу дверь, но она оказалась в воздухе. Давайте ее


опустим. Пишем следующую команду в чат: /omode m_z – эта команда
позволит двигать дверь в двух направлениях (вверх или вниз). Дальше
садимся на кнопку C и камера переключается на сам объект. Стрелками
двигаем дверь вниз к полу. Итак, мы опустили дверь, мы можем снова
нажать С, и встать в удобное вам место для обзора объекта и снова
сесть. Дальше нам нужно повернуть дверь левее (исходя из рисунка).
Пишем туже команду, но уже не m_z а m_xy.
Это команда позволит двигать объект во все четыре стороны (вперед,
назад, влево и вправо). Таким образом, двигаем дверь в дверной проем.
Нам нужно записать куда-нибудь координаты этой двери в положении
закрыто. Координаты этой двери находится в
scriptfiles/oed/BREAD_goalma.org и выглядеть они будут следующим
образом (чтобы не запутаться, после координат написано имя объекта,
имеющего эти координаты, его мы не трогаем, но при вставке в скрипт
имя необходимо удалить вместе с лишней запятой):

1 ,,,,,,,1

Итак, мы записали координаты в безопасное место. А теперь


повернем дверь в положение открыто. Чтобы повернуть дверь, мы все
также используем команду /o_mode, только теперь вместо m_xy пишем
r_z. И поворачиваем дверь в такое положение:
Теперь снова записываем те же координаты двери в положении
закрыто. В координатах ничего не изменилось, кроме предпоследней
цифры.

1 ,,,,,,,1

/o_mode r_z – позволяет нам вращать объект таким образом, чтобы дверь открывалась и
закрывалась. Есть также r_xy – с помощью, которой уже вращаем дверь в другом направлении.
Запомните m_z и m_xy – это перемещение по осям: z и xy, а r_z и r_xy – это вращение по тем же
осям.
Итак, мы получили координаты закрытой и открытой двери. Теперь мы можем удалить этот
объект, т.к. у нас есть его координаты. Удаляем его командой /odel [имя объекта] в данном случае
имя объекта – door, значит, пишем /odel door. Удаляем мы его для того, чтобы у нас не получилось 2
копии двери, т.к. одну дверь мы вставим в мод.
Прежде чем приступить к делу объясню ниже приведенные цифры. Первая цифра означает ID
модели, следующие 3 цифры это координаты положения объекта, далее идут 3 цифры это координаты
вращения объекта, последняя цифра это видимость объекта.

1 ,,,,,,,1

Итак, приступим к написанию команды. Сначала в начале скрипта мы объявляем глобальную


переменную, например door. Затем внутри автовызываемой функции OnGameModeInit – мы
присваиваем этой переменной, созданный объект.

1 cpd = CreateObject(,,,,,,,);

Видимость мы ставим , иначе вы будете видеть дверь, только подойдя к ней вплотную.
Затем пишем две команды, одну для открытия двери, другую для закрытия:

1 if(strcmp("/open", cmdtext, true, 10) == 0)


2 {
3 SetObjectRot(cpd,,,);
4 return 1;
5 }
6 if(strcmp("/close", cmdtext, true, 10) == 0)
7 {
8 SetObjectRot(cpd,,,);
9 return 1;
10 }

В функции мы указывает координаты вращения, т.к. мы будем вращать объект.


Недостаток этого скрипта только в том, что дверь открывается мгновенно. Все из-за того, что в
функции SetObjectRot которая, устанавливает координаты вращения объекта, нет последнего
аргумента speed, который есть в функции MoveObject.
MoveObject – передвигает объекты в указанное место и так как у него есть аргумент speed,
передвигает он объекты плавно. На его основе делают выдвижные двери.
Так вот, давайте сделаем раздвижные двери. Естественно нашу дверь нужно подвинуть
немного вперед в дверной проем, чтобы, когда дверь открывалась, ручки двери не торчали из стены.
Т.е мы заново получаем координаты открытой и закрытой двери. И теперь мы из полученных
координат берем координаты положения, а не координаты вращения.

1 if(strcmp("/open", cmdtext, true, 10) == 0)


2 {
3 MoveObject (cpd,,,,);
4 return 1;
5 }
6 if(strcmp("/close", cmdtext, true, 10) == 0)
7 {
8 MoveObject(cpd,,,,);
9 return 1;
10 }
Урок №24 – Запись в файл

В этом уроке я научу вас записывать в файл данные стандартными средствами Pawn, т.е. без
использования посторонних инклудов. Итак, приступим.
Сначала мы рассмотрим запись в файл. Нам нужно вручную создать новый файл в папке
scriptfiles. Создадим файл goalma.org Дальше переходим к написанию скрипта, создаем переменную
для хранения имени игрока и дальше открываем файл, как это показано в скрипте ниже:

1 new plname[24];
2 File:nFile = fopen(“goalma.org”,io_append); //Открывает файл для добавления в него записи

nFile – это как идентификатор файла, название его может быть любое, я выбрал nFile.
fopen – открывает файл.
io_append – это метод открытия файла, все методы приведены в таблице ниже:

io_write Записывает в файл, очищает весь ранее записанный текст


io_read Читает файл, файл должен существовать или крах сервера
io_append Добавление в файл записи
io_readwrite Читает файл или создает новый

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

1 public OnPlayerConnect(playerid)
2 {
3 new plname[24];
4 GetPlayerName(playerid,plname,MAX_PLAYER_NAME); //Получаем имя и записываем в plname
5 File:nFile = fopen(“goalma.org”,io_append); //Открывает файл для добавления в него записи
6 fwrite(nFile, plname); //Записываем имя игрока в файл
7 fclose(nFile); //Закрываем файл
8 }

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

1 public OnPlayerConnect(playerid)
2 {
3 new plname[24], string[24];
4 GetPlayerName(playerid,plname,MAX_PLAYER_NAME);
5 format(string,sizeof(string),”%s\r\n”,plname);
6 File:nFile = fopen(“goalma.org”,io_append); //Открывает файл для добавления в него записи
7 fwrite(nFile, string); //Записываем имя игрока в файл
8 fclose(nFile); //Закрываем файл
9 }

\n – начинает новую строку


\r – убеждается, что строка начинается сначала, а не где-нибудь посередине.
После записи в файл, его обязательно нужно закрывать.
Урок №25 - Чтение и запись файлов с помощью mxINI

В этом уроке я расскажу, как научится работать с include – mxINI. На момент написания
этого урока последняя актуальная версия инклуда Прежде чем приступить к изучению инклуда,
рекомендую его скачать. На основе этого инклуда в основном делают регистрацию на сервере. В
этом уроке я не буду показывать вам, как написать простейшую регистрацию на сервере, а всего
лишь объясню, как с помощью mxINI происходит запись и чтение из файла. Думаю, выяснив, как
работает данный инклуд, вы сами сможете написать простую регистрацию, возможно даже на
диалогах, так как урок с диалогами вы уже проходили.
Файл goalma.org нужно скопировать в папку include в директории с редактором Pawno. В
начале вашего скрипта обязательно нужно объявить этот инклуд, также как объявляется инклуд
a_samp.
Итак, приступим к разбору основных функций mxINI:

1 ini_createFile(“goalma.org”); //Создает файл с именем goalma.org в папке scriptfiles.


2 ini_openFile(“goalma.org”); //Открывает файл
3 ini_closeFile(ID открытого файла); //Закрывает файл

Запись данных в файл:

1 ini_setString(ID файла, "имя ключа", "текст"); // Эта функция записывает текст в ключ.
2 ini_setInteger(ID файла, "имя ключа", ); // Эта функция записывает целое число в ключ.
3 ini_setFloat(ID файла, "имя ключа", ); // Эта функция записывает десятичное число в ключ.

Чтение данных из файла

1 ini_getString(ID файла, "имя ключа", <имя переменной>); // Эта функция записывает текст в переменную из
файла.
2 ini_getInteger(ID файла, "имя ключа", <имя переменной>); // Эта функция записывает целое число в
переменную из файла.
3 ini_getFloat(ID файла, "имя ключа", <имя переменной>); // Эта функция записывает десятичное число в
переменную из файла.

Запись в файл

Давайте на простом примере с помощью команды, запишем данные игрока: имя, деньги и
количество здоровья. Сначала мы создаем 2 переменные, где у нас будут храниться имя игрока и
отформатированное сообщение.

1 new string[], PlayerName[32];


2 GetPlayerName(playerid,PlayerName,32);
3 format(string,64,”%goalma.org”,PlayerName);
4 new iniFile = ini_createFile(string);

После переменных мы узнаем имя игрока функцией GetPlayerName. Дальше форматируем


строку, как будет называться файл, в который будет производиться запись. В данном случае файл
будет называться по имени игрока. Дальше создаем переменную IniFile, которая будет хранить
handle файла, по которому мы будем обращаться к файлу. Handle файла возвращают функции
открытия и создания файла, как показано на 4 (строке) на примере функции создания файла.
Перед тем как записать количество денег и здоровья игрока, нужно сначала их узнать:
1 new money = GetPlayerMoney(playerid);
2 new Float:health = GetPlayerHealth(playerid);
Теперь пишем проверку, если файл выдаст ошибку, открыть файл снова.

1 if(iniFile < 0)
2 iniFile = ini_openFile(string);

Дальше записываем данные в файл и закрываем его:

1 ini_setString(iniFile, "Name", PlayerName); //Записываем имя игрока


2 ini_setInteger(iniFile, "Money", money); //Записываем количество денег
3 ini_setFloat(iniFile, "Health", health); //Записываем количество здоровья
4 ini_closeFile(iniFile); //Закрываем файл

Вот так производится запись данных в файл. Запись в файле будет выглядеть примерно следующим
образом:

1 Name = Player
2 Money =
3 Health =

Чтение из файла

Чтение из файла ничем не сложнее записи, все аналогично. Только тут не нужно проверок, условий:
if(iniFile < 0), и в переменной iniFile мы не создаем, а уже открываем созданный нами файл. Весь код будет
выглядеть следующим образом:

1 new string[], PlayerName[32];


2 new Float:health, money;
3 GetPlayerName(playerid,PlayerName,32);
4 format(string,64,”%goalma.org”,PlayerName);
5 new iniFile = ini_openFile(string); //Открываем файл
6 ini_getString(iniFile, "Name", PlayerName); //Узнаем имя игрока и записываем его в переменную
7 ini_getInteger(iniFile, "Money", money); // Узнаем количество денег и записываем в переменную
8 ini_getFloat(iniFile, "Health", health); // Узнаем количество здоровья и записываем в переменную
9 ini_closeFile(iniFile); //Закрываем файл
10 GivePlayerMoney(playerid,money);
11 SetPlayerHealth(playerid,health);
Урок №26 – Оптимизация функции GetPlayerName

Во многих скриптах, очень часто используется переменная для хранения имени игрока. Она очень
много раз создается в различных частях кода. Но можно избежать создания такого большого количества
переменных и обойтись одной. Так как в этом случае очень часто используется функция GetPlayerName,
логично создать отдельную функцию, которая будет вызываться в разных частях кода. Поскольку return
может возвращать только целое число или строку, можно написать вот такую простейшую функцию.

1 stock PlayerName(playerid)
2 {
3 new PlayerName[MAX_PLAYER_NAME];
4 GetPlayerName(playerid,PlayerName,sizeof(PlayerName));
5 return PlayerName;
6 }

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

1 new string[60], plname[MAX_PLAYER_NAME];


2 GetPlayerName(playerid,plname,sizeof(plname));
3 format(string,sizeof(string),”Добро пожаловать к нам на сервер: %s”, plname);
4 SendClientMessage(playerid,COLOR_YELLOW,string);

А вот так выглядит код с использованием функции, правда стало лучше?

1 new string[60];
2 format(string,sizeof(string),”Добро пожаловать к нам на сервер: %s”,PlayerName(playerid));
3 SendClientMessage(playerid,COLOR_YELLOW,string);

Непонятным остается только одно. Почему разработчики SAMP не решили переделать функцию
GetPlayerName подобным образом.
Урок №27 – Проверка расстояния между игроками

В этом уроке я научу вас, как делается проверка на расстояние между игроками. Допустим, у
нас есть команда передачи денег и нам нужно, чтобы игроки были близко друг к другу, чтобы они
могли передавать деньги между собой. В этом уроке я покажу, как делается всего лишь проверка.
Итак, приступаем:
Для организации проверки в начало скрипта мы добавляем следующую строку, которая
объявит новую автовызываемую функцию, которая будет отвечать за проверку на расстояние
между игроками.

1 forward ProxDetectorS(Float:radi, playerid, targetid);

Теперь в любом месте вашего скрипта добавляем эту функцию.

1 public ProxDetectorS(Float:radi, playerid, targetid)


2 {
3 if(IsPlayerConnected(playerid)&&IsPlayerConnected(targetid))
4 {
5 new Float:posx, Float:posy, Float:posz;
6 new Float:oldposx, Float:oldposy, Float:oldposz;
7 new Float:tempposx, Float:tempposy, Float:tempposz;
8 GetPlayerPos(playerid, oldposx, oldposy, oldposz);
9 GetPlayerPos(targetid, posx, posy, posz);
10 tempposx = (oldposx -posx);
11 tempposy = (oldposy -posy);
12 tempposz = (oldposz -posz);
13 if (((tempposx < radi) && (tempposx > -radi)) && ((tempposy < radi) && (tempposy > -radi)) && ((tempposz <
14 radi) && (tempposz > -radi)))
15 {
16 return 1;
17 }
18 }
19 return 0;
20 }

Ну, думаю из кода понятно, что сначала мы проверяем, подключены ли к серверу оба
игроками. Затем мы получаем координаты обоих игроков функцией GetPlayerPos. Далее мы
вычитаем X-координату игрока передающего деньги, от X-координаты получающего деньги и
записываем результат в переменную tempposx, то же самое делаем и с остальными координатами.
Ну а дальше простая математическая проверка, думаю, вам там будет все понятно. Теперь,
когда у вас уже готов этот скрипт, можно ставить такие условия:

1 if (ProxDetectorS(, playerid, giveplayerid))


2 {
3 //Тут должен быть код передачи денег или другой код
4 }
5 else
6 {
7 SendClientMessage(playerid, COLOR_RED, "Вы находитесь далеко от цели");
8 }

Также в OnPlayerCommandText в начале должна быть объявлена переменная giveplayerid,


которая используется в этой проверке. На этом все, тут довольно все просто если вы уже хорошо
знаете условные конструкции, то проблем это не составит.
Урок №28 – Построение сложных команд
Итак, в этом уроке я научу вас писать сложные команды, которые требуют ввода
дополнительных параметров после пробела, вы уже знакомы с такими. Вообще даже я сам еще ни
разу не писал такого типа команды, однако мне уже ясен принцип работы и написание таких
команд. Поэтому я объясню вам, как смогу, а в дальнейшем урок буду корректировать.
Я познакомлю вас с функцией strtok - это функция, используется, чтобы определить пробел между
командой и параметром.
Для этого урока мы рассмотрим команду передачи денег. Для начала нужно, чтобы в начале
автовызываемой функции OnPlayerCommandText были объявлены все перечисленные
переменные:

1 new string[];
2 new cmd[];
3 new playermoney;
4 new sendername[MAX_PLAYER_NAME];
5 new giveplayer[MAX_PLAYER_NAME];
6 new giveplayerid, moneys, idx;
7 cmd = strtok(cmdtext, idx);

Переменная string у нас будет хранить текст сообщения о передачи денег между игроками,
cmd будет хранить весь текст команды. Sendername будет хранить имя игрока передающего
деньги, giveplayer – имя получающего деньги. Переменная giveplayerid будет хранить ID игрока
получающего деньги, money – будет хранить количество передаваемых денег, а idx будет хранить
параметры команды. Теперь собственно приступаем к разбору самой команды. После переменных
в переменной cmd определяем пробел между командой и параметром (7 строка). Все начинается с
простейшей команды:

1 if(strcmp(cmd, "/givemoney", true) == 0)


2 {
3 return 0;
4 }

Внутрь этой команды пишем следующее:

1 new tmp[];
2 tmp = strtok(cmdtext, idx);
3 if(!strlen(tmp))
4 {
5 SendClientMessage(playerid, COLOR_WHITE, "Введите: /givemoney [id игрока] [сумма]");
6 return 1;
7 }
8 giveplayerid = strval(tmp);
9 tmp = strtok(cmdtext, idx);
10 if(!strlen(tmp))
11 {
12 SendClientMessage(playerid, COLOR_WHITE, " Введите: /givemoney [id игрока] [сумма]");
13 return 1;
14 }
15 moneys = strval(tmp);

Объясняю. Создаем переменную tmp, которая будет хранить параметры команды, это
текст, который будет после пробела. Определяем функцией strtok, проблем между командой и
параметром (2 строчка). Ставим условие, если параметр не введен, отправляем в чат сообщение.
Присваиваем переменной giveplayerid, значение первого параметра, которой мы ввели (8
строчка). Снова определяем пробел, но уже между двумя параметрами. Поскольку в команде
вводится 2 параметра: ID игрока и сумма денег. Также проверяем, что параметр введен и
присваиваем переменной money, значение 2 параметра, которое мы ввели в команде.
Вот пример: ввели вы команду: /givemoney 1 Переменная giveplayerid получает
значение 1 параметра, то есть будет равно 1, переменная money получает значение 2 параметра и
будет равна Итак, идем дальше:
Дальше мы пишем проверку, подключен ли игрок, получающий деньги к серверу.

1 if (IsPlayerConnected(giveplayerid))
2 {
3 GetPlayerName(giveplayerid, giveplayer, sizeof(giveplayer));
4 GetPlayerName(playerid, sendername, sizeof(sendername));
5 playermoney = GetPlayerMoney(playerid);

Внутри проверки функцией GetPlayerName мы получаем имена обоих игроков. Переменной


playermoney мы присваиваем количество денег игрока передающего деньги. Итак, мы знаем
текущее количество денег игрока и количество денег, которое игрок хочет передать, теперь нам
нужно поставить условие, что игрок передает сумму денег не больше той суммы, которая у него с
собой есть, пишем такое условие:

1 if (moneys > 0 && playermoney >= moneys)


2 {
3 GivePlayerMoney(playerid, (0 - moneys));
4 GivePlayerMoney(giveplayerid, moneys);
5 format(string, sizeof(string), "Вы передали %s (id: %d), $%d.", giveplayer,giveplayerid, moneys);
6 SendClientMessage(playerid, COLOR_YELLOW, string);
7 format(string, sizeof(string), "Вы получили $%d от %s (id: %d).", moneys, sendername, playerid);
8 SendClientMessage(giveplayerid, COLOR_YELLOW, string);
9 }
10 else
11 {
12 SendClientMessage(playerid, COLOR_YELLOW, "Вы не можете передать столько денег.");
13 }

Читаю условие: если количество денег, которые игрок хочет передать другому игроку
(moneys) больше 0 и количество денег, которое у него есть (playermoney) больше или равно тому
количеству, которое он хочет передать (moneys), то мы передаем деньги игроку функцией
GivePlayerMoney. Отнимаем у игрока передающего количество передаваемых денег, и даем их
игроку получающему деньги.
Ну и не забудьте для проверки на подключение игрока получающего деньги поставить else,
действие, если игрок не подключен к серверу.

1 }
2 else
3 {
4 format(string, sizeof(string), "%d не подключен к серверу.", giveplayerid);
5 SendClientMessage(playerid, COLOR_YELLOW, string);
6 }
Ну и напоследок. Если все же при компиляции скрипта pawno будет ругаться на strtok, то
добавьте в скрипт эту функцию:

1 strtok(const string[], &index)


2 {
3 new length = strlen(string);
4 while ((index < length) && (string[index] <= ' '))
5 {
6 index++;
7 }
8
9 new offset = index;
10 new result[20];
11 while ((index < length) && (string[index] > ' ') && ((index - offset) < (sizeof(result) - 1)))
12 {
13 result[index - offset] = string[index];
14 index++;
15 }
16 result[index - offset] = EOS;
17 return result;
18 }

Лично мне это функция не понадобилась, сервер я качаю с официального сайта


goalma.org и там видно эта функция вместе с редактором pawno есть.
Урок №29 – Использование return

Return всегда возвращает чего-либо. В данном уроке я научу вас использовать его. При построении
сложных команд, будет очень важно знать этот урок. Допустим, у нас есть одно условие внутри команды из
функции OnPlayerCommandText:

1 if(pLogged[playerid] == false)
2 {
3 SendClientMessage(playerid, COLOR_RED, "Вы не авторизованы на сервере");
4 }
5 else
6 {
7 //Выполнить код команды
8 }

С помощью return мы можем упростить это условие, отбросив оператор else. Для это убираем
оператор else и фигурные скобки, выравниваем код команды и получаем следующее:

1 if(pLogged[playerid] == false)
2 {
3 SendClientMessage(playerid, COLOR_RED, "Вы не авторизованы на сервере");
4 return 1;
5 }
6 //Выполнить код команды

Если условие выполнится функция прекратит дальнейшее свое выполнение, то есть все что после нее
будет проигнорировано и функция возвратит true. Также return может возврать какое-либо значение. Взять
например вот такую функцию, которую вы видели на одном из уроков.

1 stock GetName(playerid)
2 {
3 new nick[MAX_PLAYER_NAME];
4 GetPlayerName(playerid, nick, sizeof(nick));
5 return nick;
6 }

Функция возвращает имя игрока, то есть строку содержащее имя игрока. Раз функция возвращает
имя, можно подставлять функцию в любую часть кода где нужно узнать имя игрока, а не переменную
вместо нее, что является оптимизированным способом, чем заводиться для каждой функции переменную.
Урок №30 – Таймер
Таймер – вызывает определённый функцию (public) в определённое время. Функция может
вызваться единожды, либо повторяться через заданные промежутки времени. Для того, чтобы
закрепить таймер на определенной функцией (public), создаётся такая функция:

1 SetTimer("NewFunction",,1);

Таймер показан на примере public NewFunction. Давайте его вызовем в функции


OnGameModeInit. Нам нужно объявить функцию имя которой указано в таймере.

1 forward NefFunction();

Вот код простейший код этой функции.

1 public NewFunction(playerid)
2 {
3 print(“Hello, World”);
4 return 1;
5 }

В результате всего вышеуказанного, запустив сервер, в консоли каждые 1,5 (полторы)


секунды будет выводиться текст «Hello, World».
Урок №31 – Таймер с передачей параметров
Есть еще один вид таймера, который выполняет функцию, в которую необходимо также
передать параметр. Перед тем как мы рассмотрим пример давайте ознакомимся с типами
параметров передаваемых данным видом таймера.

Параметр Тип параметра


b Вставка числа в двоичной системе счисления.
c Вставка одного символа.
d Вставка (целого) числа.
f Вставка десятичного числа.
i Вставка числа (integer).
s Вставка строки.
x Вставка числа в шестнадцатеричной системе счисления.
% Вставка символа '%'

Давайте рассмотрим следующий пример.

1 SetTimerEx("Say",,1,”s”,”Hello,World”);

У нас есть таймер вызывающий функцию NewFunction ежесекундно с параметров


передающим целочисленное значение переменной value. Создадим эту public функцию. Сначала
мы ее объявим в начале скрипта:

1 forward Say(str[]);

Ну а теперь код самой функции

1 public Say(str[])
2 {
3 printf("%s",str);
4 return 1;
5 }

В итоге мы каждую секунду передаем строку «Hello, World» в функцию Say, которая
выполняется ежесекундно и отправляет ежесекундно эту строку в консоль сервера.
Урок №32 – Создание сложных команд с помощью dcmd

DCMD - командный процессор, с помощью которого можно более просто (обходя strtok)
создавать команды с параметрами после пробела. Функция создается с помощью константы
(#define). В начале скрипта пишем следующее:

1 #define dcmd(%1,%2,%3) if (!strcmp((%3)[1], #%1, true, (%2)) && ((((%3)[(%2) + 1] == '\0') && (dcmd_%1(playerid, "")))

nest...

казино с бесплатным фрибетом Игровой автомат Won Won Rich играть бесплатно ᐈ Игровой Автомат Big Panda Играть Онлайн Бесплатно Amatic™ играть онлайн бесплатно 3 лет Игровой автомат Yamato играть бесплатно рекламе казино vulkan игровые автоматы бесплатно игры онлайн казино на деньги Treasure Island игровой автомат Quickspin казино калигула гта са фото вабанк казино отзывы казино фрэнк синатра slottica казино бездепозитный бонус отзывы мопс казино большое казино монтекарло вкладка с реклама казино вулкан в хроме биткоин казино 999 вулкан россия казино гаминатор игровые автоматы бесплатно лицензионное казино как проверить подлинность CandyLicious игровой автомат Gameplay Interactive Безкоштовний ігровий автомат Just Jewels Deluxe как использовать на 888 poker ставку на казино почему закрывают онлайн казино Игровой автомат Prohibition играть бесплатно