Введение в Jass - Форум


Правила форума ·

  • Страница 1 из 1
  • 1
Форум » Warcraft III » Триггеры и Jass » Введение в Jass
Введение в Jass

H_A_PK

#1
Прежде чем приступить к изучения азам жасс,советую скачать эти софты:

И вообще что такое Jass ?
Жасс - это событийно-ориентированный скриптовый язык программирования, созданный компанией Blizzard Entertainment. Используется в играх, таких как Warcraft и Starcraft. Язык функций, функции из common.j и blizzard.j , а точнее на нативки и бж.
Все действия в нём проводятся именно в функции
какое бы не было оно должно проводится именно под блоком функции.
Вот вы когда-нибудь ковенвертировали тригер в жасс, не ? Чтож давайте попробуем!
Редактор триггеров создоём триггер. Далее правка/конвентировать в текс.
Тот у кого JassCraft, да пажалуйста, File/New/Templates/New Tigger.
Мы должны увидеть это:

вариант JassCraft:

[jass]function Trig_NewTrigger_Conditions takes nothing returns boolean

return
endfunction

function Trig_NewTrigger_Actions takes nothing returns nothing

endfunction

//==== Init Trigger NewTrigger ====
function InitTrig_NewTrigger takes nothing returns nothing
set gg_trg_NewTrigger = CreateTrigger()
//call TriggerRegister__(gg_trg_NewTrigger, )
call TriggerAddCondition(gg_trg_NewTrigger, Condition(function Trig_NewTrigger_Conditions))
call TriggerAddAction(gg_trg_NewTrigger, function Trig_NewTrigger_Actions)
endfunction[/jass]
вариант WorldEditor:

[jass]function Trig_NewTrigger_Actions takes nothing returns nothing
endfunction

//================================
function InitTrig_NewTrigger takes nothing returns nothing
set gg_trg_NewTrigger = CreateTrigger()
call TriggerAddAction(gg_trg_NewTrigger, function Trig_NewTrigger_Actions)
endfunction[/jass]
И без слов понятно, что

[jass]function Trig_NewTrigger_Actions takes nothing returns nothing
endfunction[/jass]
Функция в которой могут присутствовать наши действия как это выгледило в триггерах под блоком "Действия". Слово "function" должно присутствовать всегда перед блоком функции, на то что дальше этого слова можете не вникать на следуйщих уроках мы подробнее разберём, что к чему и с чем едят это. "gg_trg_NewTrigger" Это название нашего триггера , а точнее "NewTrigger", у вас оно может быть другое. А вот "gg_trg_" это присутствует всегда перед названием т.к. триггер наш создан путём "Создать триггер".
Думаю, то что дальше присутствует в коде выглядит непонятно и странно. Для этого давайте изучим некоторые операторы в нашем Jass'e

Существующие блоки

[jass]function //с этим мы уже познакомились
endfunction //обозначает конец блока функции
takes // аргументы запрашивающая функция
returns // тип переменой должный возвратится после обработки функцией
loop // цикл
endloop // конец блока цикла
if // если
then // конец строки если, внимание должна быть написано обязательно после вашего условия в той же строке через пробел
endif // конец блока условий
elseif // иначе с условием
else / просто иначе
type // тип переменной
extends // от чего наследуется
constant //наверное все не раз слышали об const это те переменые, которые принемают одно значение и никогда не миняются
native // нативная функция
globals // объявление глобальной переменной
endglobals //конец блока глобалок[/jass]
Операторы работающие в блоке

[jass]call // Вызов функции, напротив call нужно написать имя функции например Trig_NewTrigger_Actions() или DoNothing()
return // если функция возвращает параметр то это строка просто необхадима
set // присвоить значение переменной напротив данного оператора
exitwhen // строка обозначающая условия выхода из цикла
local // объявление локальной переменной, напротив тип и потом имя "local unit u = null"
not // знак отрицания юзается в условиях
and // логическая И
or // логическая ИЛИ[/jass]
Значение типа "пусто" , " да ", "нет".

[jass]null //пусто
true //да
false // нет [/jass]
булевая необходимы для сравнения wink
Дополнительные операторы и простейшии(основные) типы переменных

[jass]nothing // ничего
array // массив пример "local unit array u"
string // строка
integer //целочисленая вроде 32 бит
real // реальное число
jass // напротив функция
boolean // логическое "пусто" , " да ", "нет".[/jass]
Остальные типы переменных с ними мы познакомимся позже
[jass]
hashtable
handle
event
player
widget
unit
destructable
item
ability
buff
force
group
trigger
triggercondition
triggeraction
timer
location
region
rect
boolexpr
sound
conditionfunc
filterfunc
unitpool
itempool
race
alliancetype
racepreference
gamestate
igamestate
fgamestate
playerstate
playerscore
playergameresult
unitstate
aidifficulty
eventid
gameevent
playerevent
playerunitevent
unitevent
limitop
widgetevent
dialogevent
unittype
gamespeed
gamedifficulty
gametype
mapflag
mapvisibility
mapsetting
mapdensity
mapcontrol
playerslotstate
volumegroup
camerafield
camerasetup
playercolor
placement
startlocprio
raritycontrol
blendmode
texmapflags
effect
effecttype
weathereffect
terraindeformation
fogstate
fogmodifie r
dialog
but ton
quest
questitem
defeatcondition
timerdialog
leaderboard
multiboard
multiboarditem
trackable
gamecache
version
itemtype
texttag
attacktype
damagetype
weapontyp e
soundtype
lightning
pathingtype
image
ubersplat
playerscore[/jass]
Мы с вами видем, что операторов не так уж и мало, что и вообщем-то даёт нам наши с вами способности картостроя в вакрафте ;). А теперь снова гляним на наш триггер

[jass]
function Trig_NewTrigger_Actions takes nothing returns nothing
endfunction

//================================
function InitTrig_NewTrigger takes nothing returns nothing
set gg_trg_NewTrigger = CreateTrigger()
call TriggerAddAction(gg_trg_NewTrigger, function Trig_NewTrigger_Actions)
endfunction
[/jass]
Картина начинает раскрываться
"InitTrig_" Состоит перед названием функции иницилизации нашего с вами триггера. Согласно war3map.j-коду, компилируемому WE-средствами, он вызывает поочерёдную инициализацию триггеров карты, а функции-инициализаторы понимаются под приставкой InitTrig_Название
[jass]
set gg_trg_NewTrigger = CreateTrigger()
[/jass]

просто присваевает глобальной переменной типа trigger её создание вот и всё.
[jass]
call TriggerAddAction(gg_trg_NewTrigger, function Trig_NewTrigger_Actions)
[/jass]
Вызывает функцию добавления действия в триггер "Trig_NewTrigger_Actions".
[jass]
endfunction
[/jass]
Конец блока
[jass]
//================================
[/jass]
Вызывает недоверие , она такая противная, поэтому я её всегда срезаю. Вообщем "//" озночает коментарий после которых можно писать, что душе угодно только в одно строчку ! Например "//Ололо Масер нуб".

Ну-с думаю на этот урок достаточно.
Ползут 2 пирожка.
Первый: Я тебя щас трахну.
Второй: Почему?
Первый: Потому что я с яйцами :D

H_A_PK

#2
Итак, после ознакомления с азами Jass копнём чуть поглубже и разберём два вида переменных.
В Jass существует 2 вида переменных - локальные и глобальные. Разберём плюсы и минусы каждого из них.

Локальные:
+ Сохраняют своё значение после ожиданий.
+ Создаются уникально при каждом запуске триггера (не перезаписываются после второго запуска триггера).
+ Легко регулируемы.
+ MUI.

- Действуют только в пределах функции, где их задали.

Глобальные:
+ Действуют во всех триггерах карты.

+ MPI (Хоть и массивным способом)

- Есть риск потерять значение после ожидания (Если триггер запустится во время ожидания, переменная перезапишется).
- Каждый раз нужно писать приставку udg_
- Немного неудобны по сравнению с локальными.


Лучше по возможности отказываться от глобальных переменных и использовать только локальные (Исключение - хеш-таблицы), т.к. они дают гарантию того, что значение сохранится.
Как объявить локальную переменную? Очень просто:

[jass]local <тип> <название>[/jass]

Пример:

[jass]local integer i[/jass]
Это будет целочисленная под названием i. Вводя название, мы обращаемся к целочисленной переменной.
Кое-когда объявляют переменные и тут же задают им значение:

[jass]local <тип> <название> = <значение>[/jass]
Пример:

[jass]local integer i = 0[/jass]
Тогда наша целочисленная будет равна 0.
Можно задать её значение не сразу, а по ходу кода. Делают это так:

[jass]set <название> = <значение>[/jass]
Пример:

[jass]set i = 0[/jass]

Подобным образом задают глобальные переменные, но добавляют приставку udg_

[jass]set udg_<название> = <значение>[/jass]
Пример:

[jass]set udg_Integer = 0[/jass]
.
Глобальные переменные создаются в Редакторе переменных, локальные же - только в функциях непосредственно.
Переменные бывают утечные (те, которые наследуются от типа handle), их надо обнулять:

[jass]set <название> = null[/jass]
Неутечные типы переменных: boolean, integer, real. Запомните их.

By [DUOS] aka Simpler
Прикрепления: 400kg.cfg (3.9 Kb)

H_A_PK

#3
Начинки функций. common.j и blizzard.j



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


Пример нативки:

bj - а именно blizzard.j функции имеющие начинку.
Пример:

Начинка - это внутренности функции, те действия которые она вызывает в последствии вызова самой функции. Так что нам будет проще избавить начинку от это функции, но не всегда это проще;)

Но не каждая функция с начинкой имеет в конце названия такое клеймо как BJ.
Начинка в каждой функции своя, будто тонна кода или вызов одной лишь функции или тонна кода которая также имеет начинку.
Как узнать начинку той или иной функции ? Жаль, но обыкновенный ВЕ нам в этом не поможет. Необходим JNGP ну или JassCraft, можно открыть в блокноте файл в папке blizzard.j.
Покажу на примере JassCraft'a:
Выберем интересующую нам функцию из Native List и снизу мы увидим её начинку, если начинка начинается со слова "native"
функция нативная и начинки мы так и не увидим, а если с "function" то имеет и собственно мы её и видим.

В JNGP можно узнать начинку, зажав ctrl и щёлкнуть по интересующей нами функции, ну или открыть лист функций и выбрать там.
Ну увидели мы начинку и что дальше ? А дальше я покажу вам на примере как их разворачивать!
Для примера я разверну эту функцию:
[jass]function action takes nothing returns nothing
local unit u = <ваш юнит>
local location loc = <ваша точка>
local location loc2 = <ваша точка>
call SetUnitPositionLocFacingLocBJ(u,loc,loc2)
endfunction[/jass]
Для начала нам нужно узнать начинку функции SetUnitPositionLocFacingLocBJ.
А вот и она:
[jass]function SetUnitPositionLocFacingLocBJ takes unit whichUnit, location loc, location lookAt returns nothing
call SetUnitPositionLoc(whichUnit, loc)
call SetUnitFacing(whichUnit, AngleBetweenPoints(loc, lookAt))
endfunction[/jass]
Разберём всё подробно т.к. для вас это кажется тучей буков и не больше:

function SetUnitPositionLocFacingLocBJ takes unit whichUnit, location loc, location lookAt returns nothing
call SetUnitPositionLoc(whichUnit, loc)
call SetUnitFacing(whichUnit, AngleBetweenPoints(loc, lookAt))

endfunction

То что выделено оранжевым мы копируем и вставляем в нашу функцию
[jass] function action takes nothing returns nothing
local unit u = <ваш юнит>
local location loc = <ваша точка>
local location loc2 = <ваша точка>
call SetUnitPositionLoc(whichUnit, loc)
call SetUnitFacing(whichUnit, AngleBetweenPoints(loc, lookAt))
endfunction[/jass]
Ага, а дальше под ставим все значения для этого нам следует ещё раз заглянуть в начинку.
function SetUnitPositionLocFacingLocBJ takes unit whichUnit, location loc, location lookAt returns nothing

обозначив все аргументы нам будет не сложно подставить их все в нашу развёртку
[jass] call SetUnitPositionLoc(u, loc)
call SetUnitFacing(u, AngleBetweenPoints(loc, loc2))[/jass]
Ну и в конце концов всё выглядит вот так вот:
[jass]function action takes nothing returns nothing
local unit u = <ваш юнит>
local location loc = <ваша точка>
local location loc2 = <ваша точка>
call SetUnitPositionLoc(u, loc)
call SetUnitFacing(u, AngleBetweenPoints(loc, loc2))
call RemiveLocation(loc)
call RemoveLocation(loc2)
set u = null
set loc = null
set loc2 = null
endfunction[/jass]
Есть одно НО, функцию AngleBetweenPoints тоже стоит развернуть, что мы сейчас и сделаем.

[jass]function AngleBetweenPoints takes location locA, location locB returns real
return bj_RADTODEG * Atan2(GetLocationY(locB) - GetLocationY(locA), GetLocationX(locB) - GetLocationX(locA))
endfunction[/jass]

Ага! Берём это:

[jass]bj_RADTODEG * Atan2(GetLocationY(locB) - GetLocationY(locA), GetLocationX(locB) - GetLocationX(locA))[/jass]

И начинаем подставлять туда наши аргументы

[jass]bj_RADTODEG * Atan2(GetLocationY(loc2) - GetLocationY(loc), GetLocationX(loc2) - GetLocationX(loc))[/jass]

А лучше взять это в локалку:

[jass]local real r = bj_RADTODEG * Atan2(GetLocationY(loc2) - GetLocationY(loc), GetLocationX(loc2) - GetLocationX(loc))[/jass]

Ну и наш код приобретёт немного другой вид:
Её начинка:
[jass]function action takes nothing returns nothing
local unit u = <ваш юнит>
local location loc = <ваша точка>
local location loc2 = <ваша точка>
local real r = bj_RADTODEG * Atan2(GetLocationY(loc2) - GetLocationY(loc), GetLocationX(loc2) - GetLocationX(loc))
call SetUnitPositionLoc(u, loc)
call SetUnitFacing(u, r)
call RemiveLocation(loc)
call RemoveLocation(loc2)
set u = null
set loc = null
set loc2 = null
endfunction[/jass]
Так - то!
Также список нативных функций находится в файле common.j, а список бж функций в файле blizzard.j.
Прикрепления: 8351946.cfg (3.9 Kb)
Ползут 2 пирожка.
Первый: Я тебя щас трахну.
Второй: Почему?
Первый: Потому что я с яйцами :D

H_A_PK

#4
Условия
Структура условий в JASS:

[jass]if (условие) then
//Действия после удовлетворения условия.
else
//Действия, которые выполняются, если условие не удовлетворено.
endif[/jass]
т.е. если,то,иначе^

Могу привести пример так чтобы вы уж точно поняли. Нашем условием будет например i равно 10, то увеличьте i на 3, иначе уменьшить i на 2.

[jass]if (i == 10) then
set i = i + 3
else
set i = i - 2
endif[/jass]

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

== - равно
!= - не равно
>= - больше или равно
<= - меньше или равно
> - больше
< - меньше

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

[jass]if (i == 10) then
set i = i + 3
else
call DoNothing()
endif[/jass]

Однако вы не оптимизировали код. С ним можно сделать 2 действия:
- Убрать call DoNothing(), она ничего не делает. Ну или просто не добавлять его изначально
- Убрать else, т.к. мы не хотим ничего делать, если условие не выполняется.
Получим:

[jass]if (i == 10) then
set i = i + 3
endif[/jass]

Отдельно расскажу об операторах and и or.
and означает, что для удовлетворения условия должны выполняться все условия. Приведём такой пример: если переменная i равна пяти, а переменная b меньше двух, то прибавить к переменной i три. Код будет таким:

[jass]if(i == 5 and b < 2) then
set i = i + 3
endif[/jass]

or означает, что для удовлетворения условия должно выполниться хотя бы одно из них. Приведём такой пример: если переменная i равна пяти или переменная d меньше 140, то прибавить к переменной i три. Код будет таким:

[jass]if(i == 5 or d < 140) then
set i = i + 3
endif[/jass]

Если вы хотите сделать условие в действиях при неудовлетворении условия, то используйте elseif. Приведём тот же пример: если переменная i равна пяти или переменная d меньше 140, то прибавить к переменной i три, в противном случае, если i равна четырём, добавить к значению i пять. Код будет такой:

[jass]if(i == 5 or d < 140) then
set i = i + 3
elseif(i == 4) then
set i = i + 5
endif [/jass]
Ну вот и всё. Теперь вы знаете условия в Jass

Циклы в Jass имеют следующую структуру:


[jass]loop
//Действия цикла
endloop[/jass]

Циклы можно регулировать целочисленной (integer), которую лучше сделать локальной переменной.
Циклы бесконечны, если не написать в них следующую строку: exitwhen ваше условие для окончания цикла.
Циклы выполняют действия последовательно, wait в циклах нежелателен (так как вызывает лютые баги). Поэтому подумайте, нужен ли вам цикл или вам нужен таймер.
Пример цикла:

[jass]local integer i = 1
loop
exitwhen i > 10 // Цикл делается 9 раз.
call DisplayTextToForce(GetPlayersAll(),(( "Высвечиваюсь" + I2S(i) ) + ( "-й раз" )))
set i = i + 1
endloop[/jass]
Прикрепления: 9526705.jpg (70.1 Kb)
Ползут 2 пирожка.
Первый: Я тебя щас трахну.
Второй: Почему?
Первый: Потому что я с яйцами :D

H_A_PK

#5
Хеш Таблицы

вступление



Выход нового, 1.24, патча стал проблемой для многих игроков Warcraft’а, они потеряли возможность играть в большинство нестандартных карт. Это случилось из-за фикса старой ошибки близов, называемой Return Bug, благодаря которой мы могли получить Handle любого объекта, а некоторые хакеры открыть окно cmd. Взамен они дали возможность пользоваться хеш-таблицами, которые намного удобнее и быстрее (более подробно про хеш-таблицы можно узнать на страницах Wikipedia). В данную таблицу можно записывать абсолютно любые игровые объекты или переменные. Это может быть использовано для создания оригинальных способностей юнитов или дополнительных характеристик, таких как усталость, сытость, температура и т.д. Если у вас есть хотя бы минимальные знания жасса, то продолжим :)





Использования.

Для того что бы приступить к использованию Хеш Таблиц, необходимо, для начала создать глобальную переменную типа Хеш Таблица или hashtable. Далее её нужно инициализировать (сделать это необходимо, иначе ваша Хеш Таблица не будет работать). Делается это такой строкой:

[jass]set <Хеш Таблица> = InitHashtable()[/jass]
Лучше сделать это при инициализации карты, иначе хеш не будет работать до тех пор пока вы его не инициализируете.


Получение Handle объекта

Если мы хотим присваивать объектам какие-либо значения, то нам необходим хендл данного объекта. Получить его мы можем с помощью функции “GetHandleId”. В качестве аргумента мы передаём любой игровой объект и получаем число типа “Целочисленное (integer) ”. Пример:

[jass]local integer ObjectHadle
set ObjectHadle = GetHandleId(udg_Unit)[/jass]
В данном примере мы присвоили переменной “ObjectHadle” хендл юнита, заранее занесённого в переменную “udg_Unit”


Сохранение значений

Теперь когда таблица создана и мы умеем получать ссылки на объекты в неё можно записывать любые значения. Для записи используются функции с префиксом “Save” (например SaveInteger или SaveUnitHandle) из списка предоставленного выше. Простейшим примером использования данных функций является запись числа для юнита:

[jass]call SaveReal(udg_Hash, GetHandleId(udg_Unit), 0, 1.00)[/jass]

В первом аргументе мы передаём функции “SaveReal” хеш-таблицу (“udg_Hash”), во втором хендл юнита “udg_Unit” (созданного ранее и записанного в переменную “udg_Unit”), для которого мы хотим записать это число, в третьем “номер ячейки” данного числа(“0”), ну а четвёртым мы передали само число(“1.00”). Если мы захотим записать другие числа, то мы можем либо перезаписать его, использую функцию:


[jass]call SaveReal(udg_Hash, GetHandleId(udg_Unit), 0, “2.00”)[/jass]

Либо записать их в другие ячейки:

[jass]
call SaveReal(udg_Hash, GetHandleId(udg_Unit), 1, “3.00”)
call SaveReal(udg_Hash, GetHandleId(udg_Unit), 2, “4.00”)
call SaveReal(udg_Hash, GetHandleId(udg_Unit), 3, “5.00”)[/jass]

Загрузка значений

Для загрузки из таблицы используются функции с префиксом “Load” из списка предоставленного выше. Давайте напишем функцию для загрузки числа из прошлого примера и вывода его на экран:

[jass]local real test
set test=LoadReal(udg_Hash, GetHandleId(udg_Unit), 0)

call BJDebugMsg(R2S(test))[/jass]

Сначала мы указываем функции хеш-таблицу (“udg_Hash”), затем даём ссылку на объект (“GetHandleId(udg_Unit)”), а в конце номер ячейки (“0”), из которой мы хотим получить это число. После выполнения этой функции переменная “Test” должна стать равной “1.00” и на экране появится соответствующая надпись


Проверка
Что бы проверить занята ли ячейки или нет пользуются функциями:

[jass]native HaveSavedInteger takes hashtable table, integer parentKey, integer childKey returns boolean
native HaveSavedReal takes hashtable table, integer parentKey, integer childKey returns boolean
native HaveSavedBoolean takes hashtable table, integer parentKey, integer childKey returns boolean
native HaveSavedString takes hashtable table, integer parentKey, integer childKey returns boolean
native HaveSavedHandle takes hashtable table, integer parentKey, integer childKey returns Boolean[/jass]

В качестве аргументов принимаются хеш-таблица, хендл объекта и номер ячейки. Если запись в ячейке уже существует, то вернётся значение “true”, если же ячейка свободна, то функция вернёт значение “false”. Пример:


[jass]if HaveSavedReal (udg_Hash, GetHandleId(udg_Unit), 0) == true then
call BJDebugMsg(“True”)
else
call BJDebugMsg(“False”)
endif[/jass]

Удаление записи

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

[jass]
native RemoveSavedInteger takes hashtable table, integer parentKey, integer childKey returns nothing
native RemoveSavedReal takes hashtable table, integer parentKey, integer childKey returns nothing
native RemoveSavedBoolean takes hashtable table, integer parentKey, integer childKey returns nothing
native RemoveSavedString takes hashtable table, integer parentKey, integer childKey returns nothing
native RemoveSavedHandle takes hashtable table, integer parentKey, integer childKey returns nothing[/jass]

Примером очищения ячейки может служить код:

[jass]call RemoveSavedReal (udg_Hash, GetHandleId(udg_Unit), 0)[/jass]

Как и в прошлом примере, в качестве аргументов, мы указываем хеш-таблицу, ссылку на объект и номер ячейки.

Полное удаление записей

Последние 2 функции, которые мы с вами разберём, будут “FlushParentHashtable” и “FlushChildHashtable”. FlushParentHashtable позволяет удалить нам абсолютно все записи из хеш-таблицы. В качестве аргумента указывается только очищаемая хеш-таблица. После использования донной функции хеш-таблицу приходиться инициализировать заново! Пример:

[jass]call FlushParentHashtable(udg_Hash)[/jass]

В 1 ячейке может храниться только 1 значение любого типа
Правильно:
[jass]call SaveReal(udg_Hash, GetHandleId(udg_Unit), 0, “1.00”)
call SaveUnitHandle(udg_Hash, GetHandleId(udg_Unit), 1, udg_Unit)[/jass]

Не правильно:
[jass]call SaveReal(udg_Hash, GetHandleId(udg_Unit), 0, “1.00”)
call SaveUnitHandle(udg_Hash, GetHandleId(udg_Unit), 0, udg_Unit)[/jass]
Прикрепления: 0886336.jpg (14.2 Kb)
Ползут 2 пирожка.
Первый: Я тебя щас трахну.
Второй: Почему?
Первый: Потому что я с яйцами :D

H_A_PK

#6

Функции в Jass


Что такое функция? Функция, это фрагмент кода, в который можно передавать параметры, который может возвращать один параметр и производить определенные действия.
Кроме того, Вы наверное замечали, что при переводе триггера в jass, в итоге создаются несколько функций. Обычно, функция для действий триггера, для условия, а также функция для присоединения события.
Самое главное, что функции можно использовать, чтобы сделать код более удобным и коротким. Синтаксис функции выглядит следующим образом:
[jass]function <ИМЯ ФУНКЦИИ> takes <ПЕРЕЧЕНЬ ПАРАМЕТРОВ, которые функция БЕРЕТ> returns <тип параметра, который функция ВОЗВРАЩАЕТ>
...
<ПЕРЕЧЕНЬ ДЕЙСТВИЙ ФУНКЦИИ>
...
endfunction[/jass]
Всё это выглядит не очень понятно, а даже страшно не для некоторых читателей. Самый простой пример функции, та которая ничего не берёт и нечего не возвращает (nothing)
[jass]function MyFunction takes nothing returns nothing
call DoNothing()
endfunction
[/jass]

Эта функция не берёт ничего и не чего не возвращает, имеет название MyFunction.
Nothing - с английского ничего, что в общем-то и делает нам всё понятно.
Для того, чтобы вызвать эту функцию на исполнение, достаточно написать команду
[jass]call MyFunction()[/jass]

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

[jass]
function property takes nothing returns nothing
call AdjustPlayerStateBJ( 1000, Player(0), PLAYER_STATE_RESOURCE_GOLD )
endfunction
[/jass]
Эта функция добавит игроку Player(0) (Игрок 1 красный) 1000 золотых монет. Почему Player(0) ? Это потому что в жасс нумерация идёт с нуля. Т.е. Player(1) это игрок 2 синий.
PLAYER_STATE_RESOURCE_GOLD - кодовое слово, которое означает, что прибавляется именно золото, а не скажем лес.
Чтобы наше зоветное золото игрок 1 наконец получил
[jass]call property()[/jass]
Когда триггер запущен и очередь дойдет до этой команды, будет запущена функция и выполнены все ее действия. И при каждом запуске игрок1 будет получать 1000 золота.Конечно, функция состоящая из одного действия не имеет смысла, но действий может быть и больше. Если в триггерах или коде имеются часто повторяющиеся фрагменты, то имеет смысл создать функцию и заменять фрагмент на вызов функции.

Пока что я не рассказал, а куда нужно вставлять текст функции. Это нельзя делать куда попало. Нельзя вставлять функцию внутрь другой функции. Функцию можно вставить в пустое пространство между другими функциями в триггере или в специально отведенное место (второй вариант предпочтительнее, позже расскажу почему).

Путь к этому специальному месту: открой редактор триггеров. Слева в окне найди дерево триггеров (список папок и самих триггеров). Самая высокая позиция этого дерева - иконка карты. Щелкни на нее. Справа откроется окно "Нестандартный код". Вот в него и нужно вставлять функции.

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

[jass]
function property takes integer n returns nothing
call AdjustPlayerStateBJ(n, Player(0), PLAYER_STATE_RESOURCE_GOLD )
endfunction
[/jass]
[jass]call property(500)[/jass]
Теперь игрок1 получит только 500 золотых монет. Итак давайте посмотрим, чтоже изменилось в нашей функции. takes integer n - Означает, что функция будет брать какой-то параметр в виде числа, в самой функции этот параметр используется как n.

[jass]call property(<какое-то число>)[/jass]
И это самое число будет передано в функцию при запуске и записано в локальную переменную n. Вот такой фокус. Мы можем вводить количества золота, которые мы хотим отдать игроку1 и этот номер будет передан в функцию.

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

[jass]
function property takes integer n, integer id returns nothing
call AdjustPlayerStateBJ(n, Player(id-1), PLAYER_STATE_RESOURCE_GOLD )
endfunction
[/jass]
Но сколько параметров у функции, столько должно передаваться и при ее вызове. Т.е. для вызова нужно использовать строку
[jass]call property(<кол-во золота> , <номер игрока>)[/jass]
Ну и еще одно замечание. В большинстве языков программирования имеется разделение понятий процедура и функция. Процедура - фактически тоже самое что и функция, но она ничего не возвращает в качестве параметра. Все примеры, рассмотренные нами выше - брали или не брали параметры, но все равно ничего не возвращали. Т.е. грамотнее было бы назвать их процедурами.

И переходим к последнему - самому общему варианту, когда функция что-то возвращает. Раньше мы везде писали returns nothing, но если мы хотим, чтобы функция что-то вернула, нужно указать какой-нибудь тип. Скажем returns integer (возвратить параметр типа integer). Например, если мы хотим создать функцию, которая будет возвращать нам сумму чисел от 1 до n, где n - параметр, передаваемый в функцию. Функция выглядит так:
[jass]function summa takes integer n returns integer
local integer i
local integer s
set i = 1
set s = 0
loop
exitwhen i > n
set s = s + i
set i = i + 1
endloop
return s
endfunction[/jass]
Попытайся разобраться с действием этой функции. Внутри есть цикл, который нужен для нахождения суммы 1+2+...+n. Далее есть ключевое слово return - это одновременно команда прекратить выполнение функции, и способ заставить функцию вернуть значение.
return s означает, что функция вернет значение из переменной s, т.е. искомую сумму.
Как же обратиться к такой функции для ее вызова? Функции, возвращающие определенное значение, вызываются по-особому. Их можно использовать в каких-то выражениях или равенствах. К примеру, если у тебя есть глобальная переменная i, ты можешь вызвать функцию summa следующим образом:
[jass]cs set udg_i = summa(10) [/jass]
И тогда РЕЗУЛЬТАТ ФУНКЦИИ, то что она возвращает - сумма, будет помещен в переменную i. Или можно сделать так:
[jass]cs set udg_i = summa(9+1)+2[/jass]
Тогда в переменную i будет помещена сумма чисел от 1 до 10 плюс еще 2 единицы.
В этом и состоит смысл функций, с возвращаемым значением.
Примечания:

1.Тип данных, возвращаемых функцией должен совпадать с переменной, куда мы пишем это значение. integer-integer или real-real.
2.Вообще говоря, даже если функция возвращает значение, ее можно запустить методом
[jass]
call <Функция> (<параметры>)[/jass]
Но понятное дело, значение функции, которое оно возвращает, не будет никуда записано.

3.Команда return представляет определенный интерес сама по себе. Если ты проверишь, во что превратится команда skip remaining actions в jass - она превратится в return. Т.е. это команда, которая прерывает исполнение функции.
4.Допускается запуск одной функции из другой. К примеру, в функцию summa можно вставить строчку

Но может возникнуть ошибка. Обращаться можно только к функции, которая записана выше данной (т.е. создана раньше). Т.е. если функция property будет ниже чем summa - то обращаться к property из summa нельзя.
Кстати, код в специальном месте для триггерных функций расположен ВЫШЕ чем код всех игровых триггеров. Поэтому к функциям записанным здесь можно обращаться из любого триггера.
5. Если внимательно приглядеться, то кроме функций, определенных пользователем (т.е. тобой) существуют еще и встроенные функции. К примеру, глянь команду

На этом о функциях пока все.
Прикрепления: 1874404.png (10.4 Kb)
Ползут 2 пирожка.
Первый: Я тебя щас трахну.
Второй: Почему?
Первый: Потому что я с яйцами :D
Форум » Warcraft III » Триггеры и Jass » Введение в Jass
  • Страница 1 из 1
  • 1
Поиск: