Каталог статей
Меню сайта
Форма входа

Категории раздела
Статьи по Garry's Mod [6]
Мини-чат
Поиск
Статус Сервера
Наш опрос
Нравится ли вам наш сервер?
Всего ответов: 629
Друзья сайта
Best For Gamers
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

Приветствую Вас, Гость · RSS 29.03.2024, 17:02

Главная » Статьи » Статьи по Garry's Mod

Туториал по Е2
Туториал по Expression 2
(Туториал переведён с английского языка и слегка изменён,оригинал смотреть тут)

В данном туториале цель - показать основы Е2,причём показать это как можно нагляднее.

Введение

Сначала ознакомимся с первыми пятью строками:

Code
@name  
@inputs  
@outputs  
@persist  
@trigger All

"@name" - имя экспрешина,которое будет видно при
наведении на него взгляда. Необязательно,если оставить пустым то при
наведении взгляда заместо имени будет "generic".

"@inputs" - строка для входов, т.е. что экспрешин будет обрабатывать

"@outputs" - строка для выходов, т.е. результат вычислений экспрешина

«@persist» - строка для переменных,сюда надо добавлять переменные в случае если этого просит чип (например,использование в конструкции if-then-else или дельта)

Для примера разберём несложный код:

Code
@name Add Expression  
@inputs A B  
@outputs Out  
@persist  
@trigger All  
   
Out = A + B

Этот код складывает значения A и B и выводит на выход Out

Кроме этого можно производить другие математические действия:

Out = A – B
Out = A / B
Out = A * B
Out = A ^ B
(возведение A в степень В)

If-then-else конструкция.

Функция if — самая элементарная и частоиспользуемая. Она работает на принципе клапана — если (if) условие верно,то (then) сделать действие1,иначе (else) сделать действие2.Схема такая:

Code
if (A) {Out = B} else {Out = C}

То есть если A — верно (больше нуля) то приравнять Out к В,иначе приравнять к С.

Ну и пример на практике:

Code
@name Control  
  @inputs Button  
  @outputs Out  
  @persist  
  @trigger All  
  if(Button) {Out = 30} else {Out = 5}

Думаю,тут понятно.

Кроме того можно писать и без else:

Code
if (Button) {Out = 30}

В этом случае значение не сбрасывается и после нажатия на нашу кнопку Out продолжит быть 30 пока мы не сделаем условие чтобы оно принимало нужное нам значение (например, if(Button2) {Out = 5} )

Теперь ещё один пример:

Code
@name Speed  
  @inputs Speedometer Button  
  @outputs Out  
  @persist  
  @trigger All  
   
  if(Button) {Out = Speedometer}

То есть когда мы нажимаем на кнопку выход Out принимает значение спидометра,но тут проблема — когда мы выключаем кнопку Out остался как в последний момент перед выключением? Чтоже делать?
Мы забыли сделать возврат к нулю (else),и правильный код будет:

Code
@name Speed  
  @inputs Speedometer Button  
  @outputs Out  
  @persist  
  @trigger All  
   
  if(Button) {Out = Speedometer} else {Out = 0}

Теперь изучем проверки. Они бывают такими:

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

пример:

Code
@name Bell  
  @inputs Timer  
  @outputs Sound  
  @persist  
  @trigger all  

  if (Timer >= 10) {Sound = 1} else {Sound = 0}

В нашем случае это код будильника.Когда таймер (время) больше либо равно 10 то подаём звук, иначе — молчим (просьба не спрашивать меня как делать для этого таймер и как выводить звук,это просто пример — прим.авт)
Так же можно вставлять несколько условий,например:

Code
@name Test  
  @inputs Button1 Button2  
  @outputs Out  
  @persist  
  @trigger All  
  if (Button1 | Button2) {Out = 5} else {Out = 0}

Если нажата либо одна либо друга кнопка,то подать на выход 5.Так же кроме «A | B» (или) есть «A & B» (то есть если и А и В больше нуля).Можно делать и более сложные комбинации:

Code
@name Test  
  @inputs Button1 Button2  
  @outputs Out  
  @persist  
  @trigger All  
  if (Button1 >= 0 & Button2 == 54) {Out = 5} else {Out = 0}

То есть если кнопка 1 больше либо равна нулю И кнопка 2 равна 54 то подать на выход 5.

Интервал

Теперь ознакомимся с функцией interval(),которая задаёт частоту прогона кода, т.е. время через которое код будет заново перезапускаться,в милисекундах.Сделаем простой таймер:

Code
@name Timer
@inputs
@outputs Explode
@persist Time
@trigger All
interval(1000)
Time = Time + 1
if(Time == 10) {Explode = 1, Timer = 0} else {Explode = 0}

Разберём по строкам (минуя первые четыре,их я описал в начале туториала):

«@persist Time» - отмечаем переменную для времени т.к. она используется в конструкции if

«interval(1000)» - делаем так чтобы код перезапускался каждые 1000 мс или каждую секунду

«Time = Time + 1» - при запуске кода прибавляем к времени 1 единицу,а поскольку у нас код прогоняется каждую секунду получается,что каждую секунду мы прибавляем к времени единицу.Так же може записыватся как «Time += 1» или «Time++» (последняя команда означает поднятие на единицу;если бы мы поднимали значение не на единицу то использовать её нельзя было бы)

«if(Time == 10) {Explode = 1, Timer = 0} else {Explode = 0}» - условие, что если время будет равно 10 то на выход «бабах» будет подано 1 а таймер сбросится,а если время меньше его — то на «взрыв» подаём 0

Ну и наконец напишем ещё более сложный код:

Code
@name Timer  
  @inputs Button  
  @outputs Explode  
  @persist Time  
  @trigger All  
  interval(1000)  
  if(Button) {  
  Time = Time + 1  
  if(Time == 10) {Explode = 1} else {Explode = 0}  
  } else {Time = 0}

То есть если включена кнопка то:
Прибавляется время
Если время больше 10 то подать на Explode 1,иначе 0
,а если кнопка выключена то время сбрасывается на ноль.

Векторы

Векторы - одно из нововведений в Е2 в отличии от первого,здесь является небольшим массивом вида X,Y,Z.Зачем же он вообще нужен? В основном для определения местоположения чего-либо и передвижения (см. ниже),так же вектором удобнее задавать какую-то определённую точку.Вектор и простые числа - это разные типы входов,выходов и переменных.Пример:

Code
vec(300,200,300) + 8

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

Code
vec(300,200,300) + vec(8,8,8) = vec(308,208,308)

Естественно что не обязательно чтобы у второго слогаемого были одинаковые XYZ

Code
vec(300,200,300) + vec(23,432,43) = vec(323,632,343)

Чтобы экспрешин различал типы переменных к векторным входам\выходам надо добавлять постфикс :vector

Code
@name GPS  
  @inputs GPS:vector Button  
  @outputs Out:vector  
  @persist  
  @trigger All  
   
  if(Button) {Out = GPS} else {Out = vec()}

Где vec() - нулевой вектор,можно также записать как vec(0,0,0).
Векторам можно отдельно задавать каждый параметр:

Code
V:setX(#)  
  V:setY(#)  
  V:setZ(#)

А если вам надо получить какое-то значение с вектора

Code
V:x()  
  V:y()  
  V:z()

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

Code
@name Height  
  @inputs GPS:vector  
  @outputs Height  
  @persist  
  @trigger All
   
  Height = GPS:z()

Так же к векторам можно отнести applyForce() но о нём расскажу после entity...

Entity

Дословно - объекты,то есть тип переменной,хранящей в себе информацию о пропе\нпц\игроке.из ентити можно узнать местоположение,имя,модель итд. В простом ваире альтернатива - Beacon Sensor,но всётаки у Е2 куда больше возможностей.
Предположим,мы хотим знать точно где расположен наш экспрешин. У экспрешина есть собственная Entity - entity(),из которого можно узнать вектор. Ну а из вектора можно "извлечь" координаты,вот пример:

Code
@name GPS
@outputs X Y Z
@persist Ent:entity Vec:vector
@trigger All
interval(10)
Ent = entity()
Vec = entity():pos()
X = entity():pos():x()
Y = entity():pos():y()
Z = entity():pos():z()

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

applyForce(V)
Теперь можно ознакомится с одной из самых интересных функций экспрешина - применением силы.Вектором задаётся тяга.

Code
@name Force Test
@persist
@trigger All
entity():applyForce( vec(0,0,1000) )

Как видите,тут тоже появляются ентити,именно они тянут. В данном случае на сам экспрешин прилагается сила в 1000 единиц,то есть он летит вверх (если вы конечно его не заморозили).Если бы мы подали не 1000 а -1000 - экспрешин бы стремился вниз,и так по всем трём осям.
Как же сделать простого пропа-убийцу? Давайте попробуем.

Code
@name MingeProp
@inputs Player:entity
@persist
interval(10)
LocalPos = Player:pos() - entity():pos()
entity():applyForce(LocalPos*10000000)

Для того чтобы приложить силу в направлении какого либо нужно знать локальные координаты относительно экспрешина,они узнаются (координата назначения - координата положения экспа).Но поскольку вектор получается не очень большим мы его умножаем на очень большое число (чем больше тем больнее). Поскольку мы ещё не умеем находить игроков самим экспом предусмотрен вход ентити,который можно получить с Target Finder'а. Интервал здесь нужен для обновления информации о местоположении. Когда вы запустите вашего убийцу то он сразу полетит в направлении игрока.

Strings

В Е2 стало появился новый тип данных - strings,"тексты". Они нужны для чат-ботов,Console Screen и Entity Discover (всё это будет ниже). Сами тексты записываются в виде "test" и отображаются серым цветом, в первых четырёх строках у них постфикс S:string .
Тексты можно складывать ("Te" + "st" = "Test"),сравнивать (if (S == "string") {...} ) и использовать команду += ( if (Button) {Text += "a"} )
Разберём простой пример:

Code

@name String Test
@inputs Button
@persist
@trigger All
if (Button) {
  print("Hello world!")
}

И когда мы нажимаем на кнопку у нас в чате появляется Hello world!.
Для следующего примера мы залезем в документацию ( (я вам вообще советую при чтении этого туториала постоянно держать документацию в соседней вкладке\окне) и напишем код чтобы отслеживать статистику сервера.

Code

@name Server Info
@persist
@trigger All
interval(50) #интервал нужен для обновления последнего сообщения чата
if ( lastSaid() == "getinfo") {
  print( hostname() )
  print( "Map: " + map() )
  print( "Players: " + toString(numPlayers()) + "/" + toString(maxPlayers()) )
}

Когда мы в чат пишем getinfo - получаем
Здесь я вобрал несколько наиболее часто используемых команд связаных с текстами
lastSaid() - команда возвращает (понятней - "означает","равняется") последнее сообщение чата

toString(#) - команда которая переводит цифры в текстовой формат ( toString(5) + " test" = "5 test")

А значение других команд найдите сами в документации (подсказка - ищите в Server Information,пункт 4.21),там же можно посмотреть другие команды strings,например,S:toNumber()

Array и Table

Я решил совместить массивы и таблицы потому что по сути это почти одно и то же. Массив - это группа нескольких значений (цифры,тексты,ентити),причём каждое значение имеет свой номер,а таблица - это несколько значений (те же типы) но каждое имеет своё название в форме текста (string). На первых четырёх строках постфиксы переменных R:array и T:table соответственно.
Разберёмся сначала с массивом.
Изменяется информацию в ячейках массива командами:

Code

R:setNumber(<номер ячейки>,<число>)
R:setString(<номер ячейки>,<текст>)
R:setEntity(<номер ячейки>,<объект>)

Получать же значения из ячеек мы будем с помощью команд:

Code

R:<тип>(<номер ячейки>) #где тип - number,string или entity

Пример для демонстрации:
Code

@name Array Test
@persist R:array
@trigger All
R:setString(1,"lolwut?")
R:setString(2,"omg")
R:setString(3,"NOOO")

Мы создали небольшой массив,его можно представить так:

Code

1 lolwut?
2 omg
3 NOOO

Теперь выведем это к нам в чат:

Code

@name Array Test
@persist R:array
@trigger All
R:setString(1,"lolwut?")
R:setString(2,"omg")
R:setString(3,"NOOO")
print( R:string(1) )
print( R:string(2) )
print( R:stirng(3) )

Таблицы - это те же самые массивы только заместо ячеек - названия,то есть код будет выглядеть весьма знакомо:

Code
@name Array Test
@persist R:array
@trigger All
R:setString("ololo1","lolwut?")
R:setString("ololo2","omg")
R:setString("ololo3","NOOO")
print( R:string("ololo1") )
print( R:string("ololo2") )
print( R:stirng("ololo3") )
Категория: Статьи по Garry's Mod | Добавил: temo4ka_024 (10.06.2009)
Просмотров: 17977 | Комментарии: 17 | Рейтинг: 5.0/2 |
Всего комментариев: 151 2 »
15 BLADE  
^2Alex
Исправленый:D
@name Turret control
@inputs W S A D
@outputs Turret A D Freezer
interval(10)
if(W){Turret=Turret+0.15}
if(S){Turret=Turret-0.15}
if(A==0){A=0}
if(D==0){D=0}
if(A){A=1}
if(D){D=1}
if(A>0&D==0){Freezer=0}
if(D>0&A==0){Freezer=0}
if(A==0&D==0){Freezer=1}

14 ^2Alex  
Помоги мне. Найди ошибку в моём чипе.
Чип говно, но я только начал познавать E2. По идее трастеры на A и D должны были турель направлять влево и вправо, а когда их значение (A и D) равно 0 то должен работать Freezer. Но он не работает, уже несколько раз переписывал чип. Помогите. Заранее спасибо.
@name Turret control
@inputs W S A D
@outputs Turret A D Freezer
interval(10)
if(W){Turret=Turret+0.15}
if(S){Turret=Turret-0.15}
if(A==0){A=0}
if(D==0){D=0}
if(A){A=1}
if(D){D=1}
if(A>0&D==0){Freezer=0}
if(D>0&A==0){Freezer=0}
if(A==0&D==0){Freeser=1}

12 0003Spy  
Люди, у меня Ultimate Garry's Mod 2007 StandAlone #57, Е2 не воспринимает некоторые команды должным образом
например:

Code

Prop=Entity():isWeldedTo()

или то что в туторе

Code

@name Server Info  
@persist  
@trigger All  
interval(50) #интервал нужен для обновления последнего сообщения чата  
if ( lastSaid() == "getinfo") {  
  print( hostname() )  
  print( "Map: " + map() )  
  print( "Players: " + toString(numPlayers()) + "/" + toString(maxPlayers()) )  
}

Как мне быть?


13 NarikQUBY  
[color=red]Команды должны работать все. Ну например первый код который ты написал он не будет работать потому что написал не правильно, там перед знаком = и после нужен пробел...
а вот насчет второго... =\ вроде-бы все правильно
может у тебя Е2 глючный? или ваир мод старенький?нужен новый!

11 0003Spy  
Можете плз по подробнее о стринговых переменных рассказать?
Уж больно интересно и в дальнейшем очень пригодится)

10 }{0TT@6bI4  
Отлично!Спасибо админы,п то я Е2 вооще не знал,тперь уже полгче будет) biggrin biggrin

9 freezIDent  
Спасибо вам просто огромнейшее, я давно ждал подобного тутора, но натыкался только на английские версии, и вот нашел, именно то что нужно, спасибо! biggrin

8 LOL  
тот же самый С++ и С# только чуток другой из-за всякой фигни типо еспресионов гатов арифметиков кто знал или изучает С++ или любой другой язык программинга тому все ястно будет и легко даваться

7 temo4ka_024  
Quote
Немнога неточно мы узнаем координату З вектора ГПС
чтобы узнать нашу высоту на которой мы находимся надо брать вектор овнера тоесть owner():pos():z()

Читай туториал по порядку.

1. Я имел ввиду абсолютно рандомный жпс а не владельца
2. Даже если бы я написал бы про аунера то посыпались бы ненужные вопросы,а про ентити написано в конце.

Quote
и еще ненавсех картах координата З в самом низу равна 0
например на таких как фриспейс вайрконстракт

Ичо? Это уже особенности карты. Я тут причём?

Quote
и надо еще умножать V на массу того на что мы применяем силу
тоесть:

entity():isConstrainedTo():applyForce(V * entity():isConstrainedTo():mass())

желательно конечно чтобы неписать постоянно entity():isConstrai... надо брать отдельную переменую которая будет равна этом ентити


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

6 Evil  
и да если надо применять силу на сам е2 ентити вначале моно не писать
и желательно применять силу на ентити к которому прикреплен е2
тоесть:
entity():isConstrainedTo():applyForce(V)

и надо еще умножать V на массу того на что мы применяем силу
тоесть:

entity():isConstrainedTo():applyForce(V * entity():isConstrainedTo():mass())

желательно конечно чтобы неписать постоянно entity():isConstrai... надо брать отдельную переменую которая будет равна этом ентити


5 Evil  
Для примера узнаем высоту на которой мы находимся:

Code
@name Height
@inputs GPS:vector
@outputs Height
@persist
@trigger All

Height = GPS:z()

Немнога неточно мы узнаем координату З вектора ГПС
чтобы узнать нашу высоту на которой мы находимся надо брать вектор овнера тоесть owner():pos():z()

и еще ненавсех картах координата З в самом низу равна 0
например на таких как фриспейс вайрконстракт


1-10 11-14
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
© og-tifle.ucoz.ru | Хостинг от uCoz