на главную
об игре
Grand Theft Auto: San Andreas 26.10.2004

Pawn-скриптинг

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

Комментарии: 28
Ваш комментарий

вот некоторая полезная информация для начинающих:
как создать детматч:

Нет ничего проще. Открываем Pawno и нажимаем New. Вот он, Ваш первый скрипт. Чтобы запустить его, надо сначала его сохранить (большинство людей сохраняют в директорию "/samp/gamemodes/src/", но будет проще (для локального тестирования) сохранить его в "/samp/gamemodes/"). Затем кликните по кнопке с изображением синей стрелочки. Это действие компилирует Ваш файл .pwn в файл .amx, который появится в том же каталоге, однако чтобы запустить его в игре, этот файл должен лежать в "/samp/gamemodes/" (теперь понятно, зачем было сохранять Ваш скрипт в этом каталоге - теперь не придется ничего никуда переносить в ручную, все уже на своих местах после компиляции). Теперь, чтобы опробовать свой новый мод, Вы должны настроить локальный сервер и сменить игровой режим (наберите "changemode " в окне сервера).

Если все прошло удачно, когда подключитесь к своему серверу через клиент sa-mp, в игре Вы окажетесь снаружи казино в Las Venturas. К сожалению Вы не сможете выбрать себе персонажа, так как на данный момент доступен только один, но это можно будет легко исправить в будущем. Кроме того это не очень уж и интересный ДМ – из оружия у Вас только кулаки а вокруг ни души. Но это локальный сервер и по поводу второй проблемы на данный момент ничего нельзя поделать.

Следующим шагом, который Вы скорее всего захотите сделать, будет добавление в игровой режим оружия (контролируется на основе «каждому классу свое»). Каждый игрок, которого Вы выберете в начале игры (или позже в случае замены) будет принимать значение "класса". У классов может быть одинаковое оружие, или у всех разное, или комбинация. Вы назначаете оружие для каждого класса отдельно. Поэтому, чтобы дать всем классам одинаковое оружие, Вам просто нужно скопировать информацию об оружии и добавить ее к описанию каждого из существующих в Вашем игровом режиме классов. Это действие обеспечит сбалансированную игру, хотя играть будет не так интересно, если все будут бегать с одинаковым оружием. Однако выбор остается за Вами. В редакторе найдите следующую строку:


Код:
AddPlayerClass(0, 1958.3783, 1343.1572, 15.3746, 269.1425, 0, 0, 0, 0, 0, 0);

Это описание класса, параметры в том же порядке:


Код:
AddPlayerClass(Player model, X, Y, Z, A, Weapon 0, Ammo 0, Weapon 1, Ammo 1, Weapon 2, Ammo 2);
Модель персонажа можно взять из файла "peds.ide". "X", "Y" и "Z" – это координаты места появления игрока в игре, после выбора персонажа. "A" – это угол, под которым игрок будет развернут (направление камеры). Есть только одна точка появления для каждого класса, однако это можно обойти с помощью других средств, которые будут рассмотрены позже. Номера оружия можно узнать здесь. А цифры рядом с ammo – это точное количество патронов к каждому оружию, которым будет располагать игрок (у оружия ближнего боя количество патронов всегда 0).
Теперь скопируйте эту строку:


Код:
AddPlayerClass(102, 1958.3783, 1343.1572, 15.3746, 269.1425, 5, 0, 22, 100, 32, 50);

И поместите ее под той, что Вы нашли в Вашем скрипте. Теперь в игре у Вас будет выбор между CJ (без оружия) и Balla (с бейсбольной битой, пистолетом и Tec9). Если хотите, можете сами дать оружие для CJ или добавить больше других классов с другим оружием.

Примечание: некоторое оружие, которое перечислено на странице по ссылке выше, рядом с которым есть пометка "(crashes if you try to fire)" или "(Unusable)" не работает в данной версии SA-MP. В список оружия, которое нельзя использовать, входят и гранаты, однако эта досадность будет исправлена в будущем.

Узнаём координаты, углы и ID моделей

Вам, возможно, захочется изменить координаты появления игроков, чтобы они все не появлялись в одном и том же месте. Если оставить как есть, то ДМ выйдет не самый интересный, а так же это идеальная возможность для кемперства. В этом деле нам поможет Режим Отладки. Запустите "samp_debug.exe" в основном каталоге с игрой и когда бы Вам ни потребовалось, напишите "/save" прямо в игре (для этого нажмите "t" или тильду, чтобы вызвать строку чата). Это действие сохранит Ваше текущее положение в игре (в координатах), угол и ID игрока в файл "savedpositions.txt" в основном каталоге игры SA. Чтобы изменить персонажа в Режиме Отладки нажимайте F11 и F12, переключаясь по кругу между доступными в данном моде моделями.

Знакомство с функциями и callbacks

Прежде, чем мы продолжим, Вы должны узнать, что такое callbacks, или callback`и. Это – массивы кода, внутри Вашего игрового режима, представляющие из себя нечто похожее на следующее:


Код:
public OnPlayerDisconnect(playerid)
{
printf("OnPlayerDisconnect(%d)", playerid);
return 1;
}
Это - OnPlayerDisconnect callback, который означает, что эта секция кода будет запускаться при отключении игрока от сервера. Если Вы захотите, чтобы появлялось большое сообщение о том, что тот или иной игрок покидает сервер, то Вы добавляете для этого код именно в этот массив. Все callback`и, которые использует игра (кроме 2, они используются в filterscripts, а не в gamemodes. О них мы рассказывать не будем), находятся в Вашем файле. Вы не сможете сделать другие. Большинство из них появляется так же, как и та, что выше. Но некоторые из них ("OnPlayerCommandText", "OnPlayerRequestClass", "OnGameModeInit" и "main" (который является не совсем callback`ом и нигде больше не фигурирует, кроме как на титульном экране вашего игрового режима)) призваны заставлять игровой режим работать или показать игрокам, что нужно делать. Вы так же можете использовать и другие, похожие блоки (на те, о которых ниже), которые выглядят так же, но являются вызываемыми функциями. Они должны быть вызваны Вами самим. Вот функция "IMadeThis" (обратите внимание на полное отсутствие пробелов).


Код:
public IMadeThis()
{
// Это однострочный комментарий, он будет проигнорирован

/* Это
многострочный
комментарий */

print("This will be printed to the server window");
return 0;
}Вы, должно быть, обратили внимание на небольшое описание комментариев. Все, что находится в строке за "//" будет игнорироваться. То же будет происходить и с текстом между "/*" и "*/". Так как функция не вызывается игрой, мы должны вызвать ее сами с помощью callback, это смертельно просто, совсем так же, как вы вызываете большинство команд в своем коде. Итак, если вы добавите строку:


Код:
IMadeThis();В Ваш OnPlayerDisconnect callback (она должно находиться между "{" и "}", а так же перед "return 1;"), она должна запускаться как функция и печатать сообщение в окне сервера, когда Вы покидаете сервер во время игры (помните, что другие вещи, описанные там, будут игнорироваться). Мы не хотели, чтобы что-либо печаталось в окне сервера и все "print" и "printf" функции, что были в файле, удалены скриптером. Только строки, заключенные между фигурными скобками находятся в функции/callback`е (функция относится к callback`ам так же, как будто они - специальный случай функции), строка выше - имя функции. "public" подразумевает, что функция может быть выполнена любым другим кусочком кода, это в основном означает, что ваш код может быть выполнен, когда Вы вызываете функцию по имени. Мы не волнуемся о частных функциях, поскольку они вообще не используются в SA-MP. Скобки после имени функции включают список параметров, мы не охватили их все, но Вы можете увидеть пример их использования в некоторых из callback`ов в вашем чистом скрипте. Отметим, что эти параметры автоматически передаются, когда игра вызывает функцию. Если мы используем сторонние функции (то есть не callback`и), и мы хотим использовать некоторые параметры, мы должны будем передать их непосредственно. Одна крошечная вещь, которая должна быть упомянута, - то, что все строки, кроме строк с фигурными скобками (и даже они при определенных обстоятельствах, но они будут охвачены позже), и строки непосредственно перед открытой скобкой (фигурные скобки могут быть в конце той строки или, как показано здесь, на новой строке), требуют постановки в своем конце точки с запятой, чтобы обозначить конец процесса.

0

создание tdm:

Основа командного дефматча - команды игроков. Сейчас Вы узнаете, как создавать классы, и делить по принадлежностии к тому или иному классу игроков на команды. Это будет первым шагом в мир скриптинга, но довольно просто. Классы пронумерованы начиная от 0, таким образом первый класс в вашем скрипте имеет номер 0, второй - 1 и так далее (в компьютерных программах почти всегда отсчет ведется от 0 (например, playerid первого подключившегося игрока - тоже 0)). Мы хотим разбить игроков на команды, основываясь на том, какой класс они выбрали при подключении (Groove или Balla). Вы можете посмотреть на то, что возвращают callback`и, и решить, что это войдет в функцию OnPlayerRequestClass. Вы не ошибетесь. Мы собираемся разбивать игроков на команды, основываясь на том, какой класс они выбрали, и мы не можем сделать этого в функции OnPlayerSpawn, так как в этой точке мы не знаем класс, который выбрал игрок (это параметр, только те параметры, которые являются глобальными в вашем скрипте (мы охватим это позже), могут использоваться в любой функции). Сначала мы должны задать наши команды. Для этого под строкой "#include" наверху вашего файла добавьте эти строки:

Код:
#define TEAM_GROVE 1
#define TEAM_BALLA 2
#define TEAM_GROVE_COLOR 0x00FF00AA // Ярко-зеленый (в формате RGBA)
#define TEAM_BALLA_COLOR 0xFF00FFAA // Яркий ФиолетовыйЕсли Вы хотите изменить цвета, это прекрасно, только помните, что последние две цифры - альфа и lower, который определяет, насколько Вы можете видеть цвет. На самом деле, #define - просто замена. Если теперь Вы когда-либо захотите использовать номер 1 в вашем скрипте, Вы сможете использовать TEAM_GROVE взамен. Это не очень хорошая идея для нормальных скриптов, поскольку делает их трудночитаемыми, но при использовании этого для того, чтобы обозначить команды, которые обозначены только числом, Вы сможете яснее понять, что происходит (замена команд тоже станет очень простой, поскольку Вы должны будете изменить 1 только в строке с #define, а не во всем коде). Когда код будет скомпилирован, все "TEAM_GROVE" будут заменены на 1, это не переменная, это - константа, она не изменяется. Теперь под теми строками добавьте:

Код:
new gTeam [MAX_PLAYERS];Это называют глобальным массивом. Массив в основе своей есть много переменных (размещают Ваши данные, позволяя читать и записывать их), собранных в группу вместе, чтобы хранить много данных сразу. "MAX_PLAYERS" - предопределенная константа (делается точно тем же самым путем, которым мы делали наши #define). MAX_PLAYERS фактически установлен в 100, таким образом это означает, что наш массив может хранить до 100 частей данных. Символ "g" в имени переменной означает "глобальный", но это не делает ее действительно глобальной (это только облегчает возможность указывать, каким переменным что делать). Переменная, заданная вне какой-либо функции, является глобальной. Любая переменная, определенная в функции является местной к той функции, и будет работать только в ней, она также не может иметь такое же имя, как другая переменная в той же самой функции или какая-либо глобальная переменная (что еще раз доказывает, как полезен символ "g"), она может однако иметь такое же имя как другая переменная в другой функции. Все переменные "playerid" в вашем скрипте - в действительности независимые переменные, каждая из них является местной к своей функции, однако все они передают те же самые данные, так что помните, что любые функции, которые Вы делаете, не будут автоматически иметь те данные. Теперь мы можем добавить функцию разбиения игроков на команды:

Код:
public SetPlayerTeamFromClass (playerid, classid)
{
if (classid == 0)
{
gTeam [playerid] = TEAM_GROVE;
}
else
{
gTeam [playerid] = TEAM_BALLA;
}
}Вставьте этот код ВНЕ каких-либо функций в вашем коде (поскольку это - новая функция) и поместите нижеуказанный код сразу после открытых изогнутых фигурных скобок в вашем callback`е OnPlayerRequestClass (обратите внимание на способ, при которым переменные не глобальны, так что мы должны передать их, чтобы все функционировало):

Код:
SetPlayerTeamFromClass (playerid, classid);Это сохранит команду игрока в массив через нашу новую функцию. На данные в массиве ссылаются числа, таким образом массив[0] - первый элемент данных, массив[1] - второй и так далее. Поскольку мы используем gTeam [playerid], номер места для данных в массиве будет определяться параметром playerid, таким образом для игрока с id 5 данные будут сохранены в массиве под номером 5 (помните, это - 6-ая часть данных). Теперь скопируйте эту функцию:

Код:
public SetPlayerToTeamColor (playerid)
{
if (gTeam [playerid] == TEAM_GROVE)
{
SetPlayerColor (playerid, TEAM_GROVE_COLOR);
}
esle if (gTeam [playerid] == TEAM_BALLA)
{
SetPlayerColor (playerid, TEAM_BALLA_COLOR);
}
}И добавьте следующую строку к OnPlayerSpawn:

Код:
SetPlayerToTeamColor (playerid);Теперь мы имеем наши команды, но что мы фактически сделали?

Код:
if (classid == 0)
{
gTeam [playerid] = TEAM_GROVE;
}В нашей первой функции мы проверяем, какой класс выбрал игрок (помните, как мы сказали, что первый класс, заданный в вашем скрипте, будет иметь номер 0?) "==" означает "является равным", "=" же используется для того, чтобы задавать значения переменным (как это делается во второй строке). В изогнутые фигурные скобки сразу после условия заключают следствие функции. В нашем случае оно выполнится только если игрок выберет класс с номером 0 (это скин cj), если же он выберет иной класс, в игру вступят команды else (они выполняется всякий раз, когда условие "if" ложное (то есть выбранный игроком класс имеет номер, отличный от 0)). Так как мы имеем только два класса, класс, чей номер отличен от 0, должен означать, что мы - Balla:

Код:
else
{
gTeam [playerid] = TEAM_BALLA;
}Мы не нуждаемся в возвращении здесь, поскольку нет никаких данных для возврата.
Вторая половина кода устанавливает цвет игроков, когда они появляются. Благодаря этому Вы сразу можете определить, в какой команде находится тот или иной игрок. Поскольку мы сохранили команду игрока в глобальном массиве, мы можем обращаться к данным даже при том, что они были получены в отдельной функции.

Код:
if (gTeam [playerid] == TEAM_GROVE)
{
SetPlayerColor (playerid, TEAM_GROVE_COLOR);
}Мы надеемся, что Вы поняли, как работает эта функция. Если игрок, который только что появился (как ссылается playerid), находится в TEAM_GROVE, мы задаем ему цвет TEAM_GROVE.

Код:
else if (gTeam [playerid] == TEAM_BALLA)
{
SetPlayerColor (playerid, TEAM_BALLA_COLOR);
}То, что мы сделали выше, могло быть сделано проще, с помощью этого кода:

Код:
else
{
SetPlayerColor (playerid, TEAM_BALLA_COLOR);
}Но этот способ устанавливает TEAM_BALLA цвет TEAM_BALLA_COLOR только если первая часть - ложь (т.к. используется else) И если игрок находится в TEAM_BALLA, вам придется вводить больше опций, добавляя больше блоков "else if ()" до конца, так как только одно условие выполнится, если все блоки до него окажутся ложными.

0

а занимаюсь PWN в сампе и у меня получается ( можно сказать я в нем разбираюсь)

0

XCept.ion это то, вчем делаются и как делаются моды для сампа!
В эту тему можно пихать свои вопросы.

0

Какой еще XCertion? Впервые слышу. Ссылки в студию.

ЗЫ Здесь есть кто, хорошо разбирающийся в pawno?

0

DurBeZl, раскрой по-шире глаза и возможно ты увидишь здесь ник некого игрока, который "XCept.ion"!
Я разбираюсь в PAWNO

0

Если никто не хочет задавать вопросы и все такие умные, вопрос задам я:
Хочу создать в своём моде систему регистрации и, как минимум, сохранения бабла.Сам знаю,что это требует использования команд архива dini и работы с файлами, но не могу.Напишите плз здесь коды для этого,а лучше все части создания с объяснением, буду очень благодарен.

0

samp-rus.com

здесь всё для самп есичо)

0

Жалко самп забросил был мастером да и ваши тутореалы для нубов.

0

Ну в принцие могу объяснить что к чему, ZeoK... итак приступим...
Во-первых, статистика должна сохраняться только у зарегистрированного игрока. Для этого мы должны выделить переменную, принимающую положительные и отрицательные значения, зависящие от факта регистрации игрока. Конечно, работа с dini нам тоже понадобится. Допустим, в моём моде такой переменной является IsPlayerRegistered[playerid]. Её значение при регистрации прописывается в файл. Этот файл статистики сохраняется при коннекте так(только в том случае, если он не существует):
file = GetPlayerFile(playerid);
if(!dini_Exists(file)) CreateUserFile(playerid);

соответствующие процедуры(стоки):

stock GetPlayerFile(playerid) { new string[256], PlayerName[24]; GetPlayerName(playerid,PlayerName,24); format(string,256,"/Users/%s.ini",udb_encode(PlayerName)); return string; }

stock CreateUserFile(playerid) {
new file[256],name[24],config[256],tmp[256],tmp2[256]; config = "/Configuration/Variables.ini"; GetPlayerName(playerid,name,24); format(file,256,"/Users/%s.ini",udb_encode(name));
if(!dini_Exists(file)) dini_Create(file); if(!dini_Exists(config)) dini_Create(config);
for(new i = 0; i < dini_Int(config,"Count"); i++) { valstr(tmp,i); tmp2 = dini_Get(config,tmp); if(!dini_Isset(file,tmp2)) dini_IntSet(file,tmp2,0); }
}

проверять, зарегнут ли игрок, естественно, if(IsPlayerRegistered[playerid]) ... - действие будет выполняться, если игрок зарегнут

if(!IsPlayerRegistered[playerid]) - если не зарегнут

символ "!" означает значение переменной "Нет-отрицание"

итак, файл при коннекте создаётся. Теперь уже можно написать процедуры, прописывающие переменные в файлы с разными значениями(это и будет статистика).

Для этого используются функции dini:

dini_Set("файл(путь)","строка","значение"); - создаёт символьное значение

dini_Int("путь", "строка") - возвращает числовое значение строки

dini_Get("путь", "строка") - возвращает символьное значение строки

dini_Intset("путь", "строка" ) - создаёт числовое значение

ещё и другие есть, но пока этого достаточно.

P.S. Не вини меня, если что-то из вышеперечисленного ты уже знал и я тебе повторно объяснил =)

0

zeok поставь копирайты на инфу с вики

0

Простейший способ создать самп сервер:
1.Скачать шаблон с http://files.sa-mp.com/samp02Xserver.win32.zip
2.Открыть в БЛОКНОТЕ файл server.cfg
3.После слов rcon_password впишите свой пародь для входа на сервер администратором.
4.Впринципе, сервер уже должен работать.(Запуск файлом samp-server.exe)

Теперь расскажу что значит каждая строка в server.cfg
lanmode (1;0) 1 - сервер для игры по локалке. 0 - по интернету
rcon_password (Сказано выше. пароль для входа администратором)
maxplayers (Максимальное кол-во игроков на сервере)
port (Порт сервера. Можно оставить 7777)
hostname (Название сервера.)
gamemode (Игровой мод. Их вы можете посмотреть в папке gamemodes)
filterscripts (Фильтрскрипты для сервера)
announce (Хз. Не меняем))
query (тоже самое)
weburl (Сайт вашего сервера. Или напишите sa-mp.com)
anticheat (Античит. 1 - вкл . 0 - выкл.

Потом расскажу как расставлять свои тачки на сервере.

0

А так в павно я мало чего умею делать. Поэтому расскажите мне кто нибудь(!!!), как сдлеать команду, для покупки оружия? Я почти сделал, но есть проблема. надо чтоб она проверяла, хватает ли у игрока денег на это оружие, а если нет, ччтобы писала соответствующее сообщение.

0

Вот скрипт покуки винтовки.Как сделать условие? Как я сказал выше

if (strcmp("/buy rifle", cmdtext, true, 10) == 0)
{
GivePlayerMoney(playerid, -6000);
GivePlayerWeapon(playerid, 34, 1000);
return 1;

0

Раз не хотите отвечать в моей теме, так ответьте тут:

как сдлеать команду, для покупки оружия? Я почти сделал, но есть проблема. надо чтоб она проверяла, хватает ли у игрока денег на это оружие, а если нет, ччтобы писала соответствующее сообщение в чат

Вот скрипт покуки винтовки.Как сделать условие?
if (strcmp("/buy rifle", cmdtext, true, 10) == 0)
{
GivePlayerMoney(playerid, -6000);
GivePlayerWeapon(playerid, 34, 1000);
return 1;

0

НАУЧИТЕ МЕНЯ ДЕЛАТЬ УСЛОВИЯ!!(и снова сорри за капс))

0

Похоже нет таких мастеров Pawno.

0

НАУЧИТЕ МЕНЯ ДЕЛАТЬ УСЛОВИЯ!!

Команда:
if (strcmp("/buy rifle", cmdtext, true, 10) == 0)
{
if(GetPlayerMoney(playerid) >= 6000)
{
GivePlayerWeapon(playerid, 34, 1000);
GivePlayerMoney(playerid, -6000);
}
else
{
SendClientMessage(playerid,COLOR_WHITE,"Hе хватает деньжат!");
}
}

0

spasibo! (u menya na pc ne rabotaet internet. pishu s telefona) okazivaetsya v pawno legko delat usloviya! dovolno silno otli4aiutsya ot uslovii v sanny buildere

0

Так. Вопрос номер два!

Как сделать так, чтобы... Блин, как же сказать... Вот так короче:

if (strcmp("/send ТЕКСТ", cmdtext, true, 10) == 0)

SendClientMessage(playerid,COLOR_WHITE, ТЕКСТ ИЗ КОМАНДЫ);

Это я в упрощенном виде написал

0

Послать текст самому себе чтоли?

0

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

0

Можно так:

if(strcmp(cmd, "/send", true) == 0)
{
new result[128];
result = bigstrtok(cmdtext, idx);
if(!strlen(result))
{
SendClientMessage(playerid, WHITE, "Hе ввел текст.");
return 1;
}
format(string, sizeof(string), " %s", result);
SendClientMessageToAll(WHITE, string);
return 1;
}

Сообщение пойдет всем игрокам.

Это, куда нибудь в конец мода:

stock bigstrtok(const string[], &idx){
new length = strlen(string);
while ((idx < length) && (string[idx] <= ' ')){
idx++;}
new offset = idx;
new result[128];
while ((idx < length) && ((idx - offset) < (sizeof(result) - 1))){
result[idx - offset] = string[idx];
idx++;}
result[idx - offset] = EOS;
return result;}

0

А как создать маркер и проверку находится ли игрок в нем?

0

ПРошла неделя. Все молчат. ответьте мне плиз. Я всетаки сервер делаю.

0