April 06, 2020, 04:16 am

Author Topic: [Tutorial] A BEGINNER\'S GUIDE TO E2  (Read 22732 times)

Offline Ginny Weasley

  • Supporter
  • ByB Fanatic
  • *
  • Posts: 612
  • I'm not here. Sod off.
    • View Profile
[Tutorial] A BEGINNER\'S GUIDE TO E2
« on: June 27, 2013, 05:31 pm »
NOTE: This tutorial is in two parts - the first reply is the second half.
I do NOT presume this to be a complete be-all-and-end-all to E2. This should hopefully get you onto your feet and starting to independently create E2s, and more importantly learn how they work.
Apologies for any mistakes, and as ever any additional info/advice is gratefully accepted.

In this tutorial, I'm hoping to cover all the basics of E2 syntax.
E2 (short for expression 2) is a programming language used in Garry's Mod for... well, pretty much anything.
Each block of e2 starts with up to six @ lines:


############################### THE BASICS - FIRST FIVE (SIX) LINES ###############################

The first 6 lines are found at the beginning of every e2 code. While it's not essentially, by any means, to have them all, most will have @persist, @name and at least one @input or @output.
Variables in the @lines need to be declared with a data type, unless they're a normal (see below).

Code: [Select]
@name An intro to E2!This one is fairly straight-forward! @name sets the name of the e2, which you see when you look at it and is also the default save name.

Code: [Select]
@inputsWhen you link up your e2 with other wiremod items and entities, inputs are the things which you see when you look at the chip. As the name suggests, they allow other items to input data (we'll look at the different data types later on) into the e2 code, to be used for whatever purpose you need. @inputs only deals with wired inputs - there's other ways of adding information that do not need to be declared, such as find functions.

Code: [Select]
@outputsSimilar to @inputs, outputs are the things you see after you've selected something else. These allow the chip to directly influence other pieces of wire. Note that not only wiremod entities have wire properties - many others, including keypads and fading doors, also have wire connections that can be made. For example, I can wire 'Fade' on a fading door to an E2 output - that's the basis of a smart-opener code. As with @inputs, this is only for wired outputs.

Code: [Select]
@persist Test:normalIf you already know about coding, @persist is where global variables are stored, as well as variables that are kept between each code execution.
If you don't, then @persist stores variables (again, read on to find out more) which can be used many different times, in different blocks of code, and which will keep their value between each time you run the code.

Code: [Select]
@trigger@trigger is one of the more-complicated and less-used @lines. It basically influences which inputs can cause the code to run. For example, '@trigger all' will mean a change in any input will run the code. Generally however, it's not used very much.

Code: [Select]
@modelPretty self-explanatory. @model sets the model that the chip takes. For example, you might create a radio, with
'models/props_lab/reciever01b.mdl' as the model just to make it look a tad better. @model isn't included in the first 5 lines by default -
you'll have to add it in if you want to use it.

OK, that concludes the @lines. Next up, data types:


#################################### THE BASICS - DATA TYPES ####################################

Code: [Select]
MyName = "Chik"In this line, MyName is a variable. For those who don't know, a variable is a piece of memory that can be assigned a value, which can the be used, re-used and adapted as many times as you want. The value here is "Chik". This is a data type known as a string, because it's a string of characters. Easy, right? In E2, as with many other coding languages, strings are encased with double quotation marks - "<string>". Different to other languages, however, single speech marks will NOT work.

Code: [Select]
MyAge = 87MyAge has ben assigned the value '87'. Which is, you guessed it, a number! That's what it's called. In E2, numbers may also
be referred to as normals, which will hopefully be explained later
Code: [Select]
MySelf = owner()This is an entity. There are many different types of entity in GMod. Almost anything can be an entity, provided it is linked up correctly. Players are also included in the entity data type. This means they can have certain things read about them, for example their name. Entities are pretty hard to use unless assigned to a variable - they can't be written normally. The owner() shown here is just a function telling the variable who spawned the e2.

Code: [Select]
MyVec = vec(0,0,0)This is a data type known as a vector. In E2, vectors have a number of uses - they can represent positions, angles, colours, and much more besides. This is useful for creating programs based on WHERE something is in relation to something else. Vectors can have between 2 and 4 arguments, dictated by saying vec2() or vec4() when creating them. Vec2 generally determines X-and-Y co-ordinates, and vec4 is generally for colours with a transparency needed.

Code: [Select]
MyRanger = rangerOffset(1, entity():pos(), entity():forward())Damn, these things have obvious names, don't they? A ranger, just like a standard wire ranger, is a (invisible) beam which can detect an entity, and return anything about it, depending on what you ask it for.

Code: [Select]
#MyCommentA comment isn't a data type, but I'll need to explain it here. Comments are lines of text that are ignored by the chip, allowing you to write things that aren't actual programs. Every single bit of tutorial in here is a comment. In E2, there's two ways of writing comments. A single hash # will comment out a single line, leaving the rest untouched. Using '#[' creates a comment that can span multiple lines, until it is ended with a ']#'. Comments are also useful for cutting out specific pieces of code, for example when trying to fix errors.

Code: [Select]
@inputs EGP:wirelink Wirelink is special. You'll notice that it's declared in @inputs. Wirelinks are a way of connecting an entity to the E2, giving a two-way relationship. Using a ranger, we could find out what an entity's class was. Using a wirelink, we can find out everything about it, relay inputs back to it and control it on a far greater scale. One way of creating an E2 fading door is by connecting the fading door entity to a wirelink.

Code: [Select]
MyNorm = 1In many coding languages, there's a data type known as a Boolean. Quite simply, these are true-or-false statements. In E2 however, booleans are represented by a 'normal'. Basically, if a number is 0, this equates to false. Any other number (typically 1) is true.

Code: [Select]
MyArray = array("dog", "cat", "panda")An array is a form of data type known collectively as an aggregate. This basically means it can store more than one thing at once. This array, for example, has three different strings within it. To access an element in array, you use the syntax:
   
Arrayname[index, data type]

The index of an element is its position in the array. For our array above, index 1 is "dog", 2 is "cat" and 3 is "panda". In e2, the data type you're getting from the array must be included. For example...


Code: [Select]
MyAccessFail = MyArray[1,entity]
 
...would not work, because the first element in the MyArray that we created is a string, not an entity.
This would create an error that prevents your e2 from running (hence why I had to comment it out. On the other hand...
Code: [Select]
MyAccessWorks = MyArray[1,string]...would store the value "dog" to the MyAccessWorks variable, because "dog" has both the index 1 and the type 'string'. There are a few limits on what data types can be stored in arrays. For example, tables (another aggregate data type) and arrays cannot be stored in an array.



#################################### CONTROL FLOW STRUCTURES ####################################

### IF/ELSEIF/ELSE STATEMENTS ###
'if statements' are blocks of code that are only executed if a certain condition is met. For example, you might have a smart opener, which only opens IF a certain player is nearby. The syntax for an if statement is:

    if(<condition>){
        <code to be executed>
    }

The condition in an if statement can be almost anything. It could be a numerical comparison, seeing if a player is allowed to do something, almost anything.
The outcome on a comparison is a normal data type. This means putting:
Code: [Select]
if(1){
    print(MyAccessWorks)   
}
...would immediately work, because a normal 1 is equivalent to 'true' Similarly, if(0){} wouldn't do anything, since 0 equates to false.
Next up, adding an 'elseif' section.
elseif is a second comparison to be made, that is only checked if the first one evaulates to false. If the first condition is true, all elseif/else will be completely ignored. Other than that, elseif is completely identical to if. It takes a condition, evaulates it, if true then it runs a block of code. Also, if an elseif is true, all other else/elseifs will be skipped. 'else' only runs if no other statements evaluate true. A fully typed-out if/elseif/else statement might look something like this:
Code: [Select]
X = 3
if(X==1){
    print("Not executed - X isn't 1")   
}
elseif(X>5){
    print("Not executed - X isn't greater than 5")   
}
else{
    print("Doesn't really matter what X is - else will be run without condition if everything else is false!")   
}


##### COMPARATORS IN E2 #######

    < Less than
    > Greater than
    <= Less than or equal to
    >= Greater than or equal to
    == Equal to (Using a single equals is for assignment to a variable, not a comparison.)
    != Not equal to


##### LOGICAL OPERATORS IN E2 #######
Logical operators allow you to have multiple conditions for an if statement, and to affect how these conditions are evaluted.

    & - AND: returns 1 if BOTH conditions are true, 0 otherwise.
    | - OR: returns 1 if EITHER condition is true, 0 if both are false.
    ! - NOT: returns 1 if condition is false, 0 if it's true.
   
Putting these into an example:

Code: [Select]
X=1
Y=0
if(X & !Y){
    print("LOGIC!")   
}

This if statement would run. First, it finds the value of Y (0 for false) and inverts it. This gives us both X and Y as 1. Next, the & operator looks at both statements. Since they are BOTH true, the code will execute. If X was 0 or Y was 1 then we would need to use an OR gate to get this to run, as only one of the statements would be true.


### SWITCH STATEMENTS ###
Switch statements are a little known replacement for the repetitive if/elseif/else structures. Switch statements use a 'case' system to test conditions.
It's worth noting that they aren't QUITE as diverse - where two potential conditions are completely unrelated, for example, they can't be used very easily.
Using X from before, a switch statement might look like this:

Code: [Select]
switch(X){
    case 1,
        print("Not executed - X isn't 1")
    break
    case X>5,
        print("Not executed - X isn't greater than 5")
    break   
    default,
        print("Doesn't really matter what X is - default will be run without condition if everything else is false!")
    break
}

The X>5 case demonstrates one way in which switches can become more complicated. Because the comparison operator needs a statement either side of it, it was necessary to put in X there, even though it was in the switch statement's argument. In this way, switch CAN be used for unrelated conditions. It's just a lot more confusing. It is required to have at least one argument for a switch statement, whether it is used or not. The 'default' case is equivalent to else - it is run when none of the other cases are fulfilled.
Put generally, switch statement syntax is:

    switch(<variable>){
        case <value>,
            <code for this condition>
        break
        case <value>,
            <code for this condition>
        break
        default,
            <code to be executed in the absence of another true case>
        break   
    }

Switch statements also have the ability to fulfill more than one case if no breaks are included between them, in a cascading structure:

Code: [Select]
X = 6
print("Greater than...")
switch(X){
    case X>5,
        print("5")   
    case X>3,
        print("3")
    case X>1,
        print("1")
    case X>0,
        print("0")
}

Here, X fulfills every comparison made. Since no breaks are included, the code for every case is run. If we had included breaks, only the first condition to be fulfilled would be run.


AutoMerge: June 27, 2013, 05:36 pm
Ok, automerge is being annoying. I can't post the second half until someone comments if I understand correctly. Otherwise, the messages merge and exceed the limit.
« Last Edit: June 27, 2013, 05:36 pm by Chikanman »

Offline Ginny Weasley

  • Supporter
  • ByB Fanatic
  • *
  • Posts: 612
  • I'm not here. Sod off.
    • View Profile
Re: [Tutorial] A BEGINNER\\\'S GUIDE TO E2
« Reply #1 on: June 27, 2013, 05:44 pm »
(This better bloody work.)

##################### CONTROL FLOW PART 2 - LOOPS #####################

### WHILE LOOPS ###

As the name suggests, while loops keep repeating a section of code while a certain condition is true. This is useful for when you don't have a certain number of repeats to do. While loop

syntax is:

    while(condition){
        <lovely lovely code to repeat>   
    }



                                <<<<<<<<< IMPORTANT NOTICE >>>>>>>>>>>>>>
MAKE SURE SOMETHING WILL EVENTUALLY CHANGE YOUR LOOP'S CONDITION TO FALSE. IF IT DOESN'T, THE CODE WILL REPEAT FOREVER, WHICH TENDS TO MAKE THINGS CRASH AND BREAK AND LAG AND OH MY GOD WILL

YOU BE HATED.

Example while loop:

Code: [Select]
X=1
while(X<10){
print(X:toString())
X++   
}

For reference, the toString() just takes a number and makes it a string, and X++ makes X increase by one - so that eventually, X will be larger than 10 and the loop will end.
So, the second that X>=10, the loop is broken and the code will move on to the next part. Until then, it keeps going round and round.


### FOR LOOPS ###

'for' loops are the other type of loop in E2. They execute a code block repeatedly, but they do it a fixed number of times. For loops look
like this:

Code: [Select]
for(I=0,10,2){
    print(I:toString())   
}

This code will take a local variable (one which is only used in this loop and loses is forgotten afterwards) and assign it a value of 10. From there until it reaches 10, it will print out its

value, then increase by a step of two.The 'I' in this loop represents the variable known as the 'iterator'. The iterator in a loop is the number that will change and determine how many times

the loop runs.
Generic for loop syntax is:

    for(<iterator>=start,finish,step){
        <code to be looped>
    }
   
If no step is specified, it will default to 1, meaning that the following code won't work:
Code: [Select]
for(I = 10,1){
print(I)   
}

The code is cancelled after a single iteration - the only output to the chatbox is 10. To fix it, I would simply have to put ',-1' at the end of the
brackets.
As with while loops, it's important to have a condition that won't keep going forever. While a for loop will always break eventually, having too many
iterations will make your code really inefficient.


All control flow structures in E2 can be embedded. This means you can place one inside another to accumulate the effects. Examples:

Code: [Select]
    for(I = 1, 10){
        for(Q = 1, 10){
            print(I, Q)
        }
    }
   

    if(X<0.5){
        H1 = 999
        if(Use){
            H1 = 900   
        } 
    }
   


################################################## WRITING E2 CODE ###########################################################
In general, all e2 code follows the same pattern:

    Variable:function(args):function(args)...:function(args)

For this, a variable doesn't have to be a declared variable. It can simply be anything that has value. Also, it is necessary to have the brackets after
every function, whether it takes any arguments or not.
Unlike some other coding languages, it isn't necessary to end each line with a semi-colon. Just start a new line.

There are also certain functions which can simply start their own line:


################## A FEW SINGLE-LINE FUNCTIONS ###########################

########## runOn FUNCTIONS ##########

E2 has several functions which dictate when the code will run. Bear in mind when making code that using these will greatly increase the op-count of
your e2, and often can be avoided altogether with careful use of @trigger.
The basic and most-used commands are:

    interval(<num>) - Declares an interval in milliseconds, running the code each time the interval passes. For example, interval(1000) will run
                      every second.
   
    runOnTick(<num>) - Runs the code on every nth server tick (dictated by your number). This is EXTREMELY high-ops and almost never used.

    runOnChat(<num>) - Runs the code every nth time someone speaks.

Others include:

    runOnHTTP - Runs each time the E2 receives a HTTP.
   
    runOnSignal - Runs each time the E2 receives a signal, from another e2 or certain wire devices
   
There's quite a few others, but they're near never-used and therefore not worth mentioning in this tutorial.


########## FIND FUNCTIONS ##########
Finds are some of the most important and commonly-needed functions in E2. They allow any form of entity to be detected by the E2.
Starting a new find will overwrite any previous ones (unless they've been stored to a variable, which I'll explain in a second.), and they can be written
at the start of a line without any preceding variables needed:

    findInSphere(<vector>) - creates an invisible sphere around the given position vector, and returns an array of entities found within it.
    findInBox(<vector1>,<vector2>) - finds entities in an invisible box, with the first corner on the first vector's position and the other <vector2> away.
    findInCone(<vec>,<vec>,<num>,<num>) - Creates a cone using the given parameters and returns the found entities.
    findByModel(<string>) - Finds all entities on the map with the given model pathway (e.g. models/hunter/plates/plate1x1.mdl to find all 1x1 plates).
    findByName(<string>) - Finds all entities with the given name
    findByClass(<string>) - Finds all entites of the given class (e.g. spawned_shipment or money_printer)
   
    findPlayerByName(<string>) - A bit special. Like findByName, but only returns players. Used for player-specific commands.
   
   
Ok, so we've found our entites. But what if we want to refine our search. If we've found all entities in a sphere, but only want money-printers?
Well... here we use the function findClipTo... , finishing it off with any of the find-types above - findClipToClass() for example. There's also
findClipFrom... which removes any entities with that type.
What else? Ahh yes, time to sort them! (just one here)

    findSortByDistance(<vector>) - Sorts the find by the entities' distance from the given position, closest first.

Finally, we might need to store this find to an array - this allows us to re-use the information from it several times without having to repeat the
find each time, possibly with different results.

    <variable name> = findToArray()


############################### USING THE EXPRESSION 2 IDE #####################################

Say what?

Ok, if you didn't know already, the window you see when editing E2 is the IDE (Integrated Development Environment).
Naturally, the people who made wiremod wanted to make it as easy as possible for people to make things, so the window comes with a few handy tricks to
help you code better.

########## FUNCTION AUTO-DETECTOR ##########
Go to the editor and type in 'fin'. Right below where you type, there should be a list opening with a load of blue buttons. This is E2 trying to suggest
things you might be typing. To auto-type something you like the look of, simply click on it. You'll need to fill in the arguments of course, but at least
you won't have to worry about typos!
Look at the list again. In the mandatory brackets after the function name, certain auto-listed functions have a group of letters. These represent (in order)
the arguments that the function needs. An example (hooray, cause we haven't had to many of those!):

    findInSphere(VN) means that the function findInSphere() needs one vector and one number as its arguments. They must be in that order.

Some of the letters included can be a little misleading. The most common ones are:

    S - string
    N - number
    V - vector
    R - ranger
    XWL - wirelink
    A - array
    E - entity
   
There's a lot of others, but I can't list them all without making this tutorial so long. Besides, this is only meant to be the basics to help you start
coding e2.
   
If, in auto-detection, a function's brackets are empty, that simply means it has no arguments needed.
Also, user-created functions will NOT be listed in auto-detect. To find out how to create your own functions, look at the bottom of this tutorial.
########## CODE VALIDATION ##########
Got some code, but not sure if it'll work? Well, the IDE has a little something to help. If you've coded something, click the green bar at the bottom. This
tells the game to validate the code, detecting typos, syntax errors and suchlike. If it stays green after you click, all good. If it turns red, it will tell
you what the error is, as well as where in the code to find it. Line numbers are listed on the left hand side of the window.

NOTE: The validator cannot tell you if your code will actually do what it's intended. All it can tell you is if there's a grammatical bug in your code.
It can't comment on your logic, since it doesn't know what you're trying to do.

########## SOUND BROWSER ##########
Very rarely used, but if you're using functions involving sounds, then you can click on 'Sound Browser' in the top right to open a window that allows you
to find all sounds usable in your e2. However, you will likely have some custom sounds downloaded, so don't assume everyone else can hear anything you play.

########## E2 HELPER ##########
A neat little window which is really underused. E2Helper allows you to search for any function in the E2 language. Using the three search bars at the top,
you can search by function name, arguments and return types repectively. For example, to search for finds which take strings, I'd put 'find' in the left and
's' in the middle.


#####################USEFUL LINKS ########################

If you want to improve your E2 skills, the best idea is to just keep practicing. Look through other people's codes, whatever. Anyway:

    The ByB wiremod sub-forum
    Wiremod.com
    YouTube
    Google (no, seriously.)

Any questions, feel free to ask. I'll do my best to answer, and I'm sure the other ByB E2ers will be willing to help where I can't.

AutoMerge: June 27, 2013, 05:46 pm
Just thought I'd add a quick credit as well:

Many thanks to all at ByB and elsewhere who've helped me with my E2.

Specific thanks to KGwilson for putting up with my endless whining on RP1 today and Spoofzor for letting me post the bloody thing at the end of it all.
« Last Edit: June 27, 2013, 05:46 pm by Chikanman »

Offline Spoofzor

  • ByB Fanatic
  • ****
  • Posts: 902
  • What do you mean that's as loud as it can go!?!
    • View Profile
Re: [Tutorial] A BEGINNER\'S GUIDE TO E2
« Reply #2 on: June 27, 2013, 05:48 pm »
Reserved, again.
[edit]/sticky[/edit]

I like a lot of the stuff you pointed out in this mile long tutorial. It's worth the read for the most part to anyone trying/attempting to learn E2.

Specifically the detail you go into about the IDE. Which is stuff I personally never bothered explaining. It really helps a new user really understand what they're looking at.

I do have a few things I'd like to point out as suggestions for possible future edits.

The segment on switch() statements in particular. I don't find them very useful. I don't know about you. if(){}elseif(){}else{} statements would suffice a beginner don't you think?

A small note for the runOn* functions: runOnTick(1) and runOnTick(1000) do EXACTLY the same thing.
If a runOn* function is given a value of ANYTHING besides 0 it will run depending on its execution trigger.

I noticed you didn't include tables or gTables. Although as this is aimed at beginners I can see why they wouldn't be. However, I'd be willing to assemble/help assemble an 'advanced' tutorial as an addition to this one.

Also, I don't know what caused it but your formatting is really weird in your text. Just thought I'd point it out. xD
« Last Edit: June 27, 2013, 06:08 pm by Spoofzor »

Offline Ginny Weasley

  • Supporter
  • ByB Fanatic
  • *
  • Posts: 612
  • I'm not here. Sod off.
    • View Profile
Re: [Tutorial] A BEGINNER\'S GUIDE TO E2
« Reply #3 on: June 27, 2013, 06:14 pm »
However, I'd be willing to assemble/help assemble an 'advanced' tutorial as an addition to this one.
Would love to! I'm far from an expert myself, so I'd definitely like the assistance. Also, I REALLY can't be bothered to spend another 8-10 hours of my life making another one...

Also, I don't know what caused it but your formatting is really weird in your text. Just thought I'd point it out. xD
I didn't actually write it in the forum, or even on a word processor. I wrote it on the E2 chip, so I could test things out as I wrote them in. Admittedly, that did result in about half an hour of editing everything into BBCode.

Offline Hashcakes

  • ByB Newbie
  • *
  • Posts: 1
  • High as a nigga'pie.
    • View Profile
Re: [Tutorial] A BEGINNER\'S GUIDE TO E2
« Reply #4 on: July 24, 2013, 10:18 pm »
Great tutorial!
I still have some learning to do, but it helps if another member of the community is around and willing to help. Thanks for the great tut Chikan and keep it up :)
"I kill a communist for fun, but for a green card, I gonna carve him up real nice."

~ Tony Montana

Offline Ginny Weasley

  • Supporter
  • ByB Fanatic
  • *
  • Posts: 612
  • I'm not here. Sod off.
    • View Profile
Re: [Tutorial] A BEGINNER\'S GUIDE TO E2
« Reply #5 on: July 24, 2013, 10:34 pm »
Thanks! Currently working on an advanced tut with a couple of other people - sadly due to unavoidable circumstances it's taking a while - but should hopefully see something new coming up in the next few months if we can get our act together!