Spectre's Expression 2 Tutorial
A Beginners Guide to the Expression 2
In this tutorial I will be explaining the basics of E2 for all of you confused people out there. I will try to write this as simply as I can, to avoid confusion. If you find something difficult to understand, Please post.
The purpose of this tutorial is not to explain every single command used by the Expression 2 but give you enough knowledge to learn from yourself and others.
This tutorial includes:
The First 5 Lines
Basic Math
If Statements
Vectors
Entities
Arrays
Strings
Find Commands
Applyforce
Chat Commands
Concmd (Console Commands)
Rangers
Console Screens
Holograms
Wirelink
I will start off by explaining what the first 5 lines of code in the Expression are used for
Code:
@name
@inputs
@outputs
@persist
@trigger All
"@name" is used to input what you want the expression will be called when others are viewing it.
"@inputs" this is where you write any inputs you would like to have on your expression. You may not have 2 of the same inputs, and they all must start with a capital letter. These will then appear as options to wire up later. For multiple inputs you would separate by a space.
"@outputs" is where you write any outputs that you would like to have on your expression. This is what you wire other things to. You may not have 2 of the same outputs, and they all must start with a capital letter. For multiple outputs you would separate by a space.
"@persist" is a unique line that is only in the Expression 2. This is where you will put any thing you would like to retain. With personal experience, you will be using this the most when you get one to more advanced wiring. You may not have 2 of the same inputs, and they all must start with a capital letter. For multiple inputs you would separate by a space.
"@trigger" you should not bother with this until you are more experienced with Expression 2. Basically for Console Screens trigger is your best friend. In a nutshell, trigger tells the expression what inputs or outputs update the chip. This is kind of hard to explain, so I may develop the explanation later.
Basic Math
A basic code would be
e2 Code:
@name Add Expression
@inputs A B
@outputs Out
@persist
@trigger All
Out = A + B
In this simple Add expression you are taking input "A" and adding it to input "B". Anything you would wire to the expression will receive the sum of the two.
You can do a lot of math with all most the same equation such as.
Out = A – B
Out = A / B
Out = A * B
Out = A ^ B
If statements
If statements are the most simple things to do in expression, but they will have the biggest impact on your code. The if statement could be viewed upon like a flood control valve. When the valve is open, all the data will come through, if it is closed, nothing will come through.
If statements are written as
if (A) {Out = B} else {Out = C}
this is to say, if "A" is 1, the output would be "B". However, if "A" is not 1, the output would be "C". Here is an example
e2 Code:
@name Control
@inputs Button
@outputs Out
@persist
@trigger All
if(Button) {Out = 30} else {Out = 5}
In this example a Button would be wired to the expression. If the button was on, the expression would output 30, and if it was off the expression would output 5. This could be used for a door of some sort.
By taking out the "else" you would end up with the expression
if(Button) {Out = 30}
When you spawn this chip, out would be 0. When you press the button, it will output 30. However even if you turn the button off, the output would still be 30. This is because you are not telling it what to do if the button is off, so it retains its value. This would be used for a Toggle of some sort, and you can use another if statement to turn it back to 0.
In an If statement, you do not have to have a stable value. A good example for a statement with a changing value would be.
e2 Code:
@name Speed
@inputs Speedometer Button
@outputs Out
@persist
@trigger All
if(Button) {Out = Speedometer} else {Out = 0}
This expression would output the Speedometer only if the button was pressed.
Now for a function called "Interval", this function will update the chip at a given number, 1000 being 1second. Many functions need this to work, usually the ones involving getting information from the world. These can also be used in Timers, and counting. However in some cases you will have to use logic, but that comes later. He is an example of a timer, when the timer hits 10 explode would equal one. When the timer Equals 0, Explode will be 1. We will use persists in this line, because we do not want to output the actual timer, just the explode variable.
First however, there is some math that you will have to learn for the If statement, but not much.
"==" - Is Equal to
"!=" - Is not Equal to
This will be used in the following code
e2 Code:
@name Timer
@inputs
@outputs Explode
@persist Time Count
@trigger All
interval(1000)
Time = Time + 1
if(Time == 10) {Explode = 1} else {Explode = 0}
By doing "Time = Time + 1" A loop has been created that will update with the interval. This can also be written as
"Time += 1" or "Time++"
You can also reset your timer by doing this.
e2 Code:
@name Timer
@inputs
@outputs Explode
@persist Time Count
@trigger All
interval(1000)
Time = Time + 1
if(Time == 10) {Explode = 1, Time = 0} else {Explode = 0}
By adding a comma, I am telling the IF statement to do two things at one, First is to explode, second is to restart the timer. You can have as many as these as you want. There is also the option to use "|" this basically means "or". A good example would be
e2 Code:
@name Or Test
@inputs Button Button2
@outputs Out
@persist
@trigger All
if(Button | Button2) {Out = 5} else {Out = 0}
This can be translated into, If button is equal to one "or" Button2 is equal to one, Out will be 5.
For the last bit in information about If statements, you can have an If statement, in an If statement. In this example I will make the timer only work if a button is on.
e2 Code:
@name Timer
@inputs Button
@outputs Explode
@persist Time Count
@trigger All
interval(1000)
if(Button) {
Time = Time + 1
if(Time == 10) {Explode = 1} else {Explode = 0}
} else {Time = 0}
With If statements, if you choose you are capable of taking up more then one line. It can go as far as you would like. However you should label them as the code gets more complicated.
Vectors
Vectors are generally used in the Coordinate situations. They are written as (X,Y,Z). Vectors have some rules though.
In the Inputs, or Outputs or Persists you would have to write it such as V:vector, this is declaring V a vector so you may no longer use V for single numbers, angles, or entities. To use a vector you will be using what is called a function. To use a function you write : (functionname) immediately after the variable.
You are not able to add or subtract a single number to a vector, for this you would have to make that single number a vector and subtract that.
An example would be
(500,153,120) + 8
This would not work; instead you would have to use a function to make the 8 a vector such as
(500,153,120) + vec(8,8,8) = (508,161,128).
It does not have to be a single number, you can use any number you like.
(500,153,120) + vec(100,120,180) = (600,273,300)
When you are using a vector, you always have to define it in the first 5 lines. It will be written as V:vector. A good example for this would be
e2 Code:
@name GPS
@inputs GPS:vector Button
@outputs Out:vector
@persist
@trigger All
if(Button) {Out = GPS} else {Out = vec()}
I really cannot see a good use for this except an on or off switch. Vectors are used tremendously in cases where Entities are involved. You can also edit vectors using commands such as
e2 Code:
V:setX(#)
V:setY(#)
V:setZ(#)
if you would like to only use a single number from a vector the commands would be.
Here is an example for using a GPS to find how high it is.
e2 Code:
@name Height
@inputs GPS:vector
@outputs Height
@persist
@trigger All
Height = GPS:z()
Rotating vectors is another function in the expression 2. Although it is not commonly used, it is worth knowing how to do. This is kind of hard to explain... when you rotate an angle, you are rotating it relative to 0,0,0; for example
vec(100,0,0):rotate(ang(180,0,0)) = vec(-100,0,0)
vec(100,0,0):rotate(ang(90,0,0)) = vec(0,0,0)
This is generally used for HUD's and navigation. I do not think I explained this very well; so like always, I think the best example would be... an example.
** This code contains content that you have not learned yet, but you will learn this later in the tutorial. All you should pay attention to is Rotate. **
Do not worry about this yet but
Ang = your heads angle
Vec = your position
e2 Code:
@name
@inputs
@outputs Rotate:vector
@persist Vec:vector Ang:angle
@trigger
runOnTick(1)
#Ignore ---
if(first()) {
holoCreate(1)
}
Ang = owner():eye():toAngle()
Vec = owner():shootPos()
holoPos(1,Rotate)
#Ignore ---
#Roate
Rotate = Vec+ (vec(100,0,0):rotate(Ang))
In this example vec(100,0,0) is how far away it is from you. Notice how I am only rotating vec(100,0,0). If i were to rotate Vec+vec(100,0,0) it would rotate the whole thing relative to the center of the world; This is not what you want.
Please Comment if you are confused about this section
Entities
Entities are used a lot in the expression 2 chip. They are used for players, robots, and other such things. There is a lot you can do with an entity, and a lot of information you can get from them. An entity can be A person, a prop, a Vehicle, an NPC or world values. In the first 5 lines entities will be declared an entity by E:entity. Commands for entities include, E:pos, E:height, E:shootPos, E:owner(), and much more. Until you learn entity discovery, you will probably use a target finder.
A nice command that I use a lot is
entity():isWeldedTo()
This command gives you the entity of the prop that you spawned it on.
There is also
E:aimEntity() - this will give you the entity of what you are looking at
Here is an expression using a target finder to grab the vector of where it is.
e2 Code:
@name Vector
@inputs Player:entity
@outputs X Y Z
@persist
@trigger All
Location = Player:pos()
X = Location:x()
Y = Location:y()
Z = Location:z()
To wire this up, you would wire the Player input to the target finder. Usually the target finder will tell you what It is outputting. It will look something like 1 [ENTITY].
I would recommend going to the Expression 2 Wiki to read all the functions that can be used with an entity.
Wire Expression2 - GMod Wiki
Arrays
Arrays are like tables that are filled with information, such as Entities, Strings, Numbers, and other stuff. An Array would be written on the first 5 lines as R:array. You can use it to store information for later use. Using the commands
e2 Code:
R:setString(#,String)
R:setEntity(#,Entity)
R:setNumber(#,Number)
R:setVector(#,Vector)
The # stands for the index, basically what slot of the Array you want this information to be stored in.
An example of this would be
e2 Code:
@name
@inputs
@outputs Out
@persist R:array
@trigger all
R:setNumber(5,500)
Out = R:number(5)
What I am doing in this expression is putting the information "500" in slot 5 of the array. Then I am calling the information out with R:number(5)
In the most recent update of wiremod, you have been given the option to create an array like this:
e2 Code:
@persists Ary:array Blah:array Yargle:array
Ary[1,number]= 100
Blah[56,vector]= vec(100,100,100)
Yargle[1337,string]= "Roflsocks"
Strings
Strings are used mainly for console screens, chat bots, and find commands. Strings are written on the first 5 lines as S:string. You can write a string in the game by using quotes.
Here is an expression making me say an entities name using the target finder and S:print()
e2 Code:
@name Test
@inputs Player:entity
@outputs
@persist Name:string
@trigger all
Name = Player:name()
if(Player:isAlive()) {
print("Where is "+Name)
}
If you spawned this chip without the if statement, it would work, but you would not have time to wire it up. Adding if(Player:isAlive()) means that the chip will only do this command, if the entity is alive.
When you spawn this chip it should say in blue letters on your chat box
"Where is Bob"
Assuming your target finder is targeting bob.
You can cut pats of a string off with the commands left() and right()
Take this phrase for example
"THISISATEST"
If you did
"THISISATEST":left(4) = "THIS"
"THISISATEST":right(4) = "TEST"
You can also use a helpful function called Explode, where you break up a string into an array.
Using S:explode(***)
*** = This is where you put the character you want to divide the string by.
For example
Array = "This , Is , A , Test":explode(",")
Would break this into
e2 Code:
Array:string(1) = "This "
Array:string(2) = " Is "
Array:string(3) = " A "
Array:string(4) = " Test"
Find Commands
Find commands are used to find Players, Props, NPC's, Vehicles, and World things. They are actually very simple to use when you know what to do. For these, you must use an interval() otherwise you will only get the data at the time the chip is spawned.
The most basic find commands are
findByModel("String") – When in Q menu right click on an Icon and click "Copy to clipboard"- paste it over "String"
findByPlayerName(String)
findByClass(String) – This includes "Player" "Npc_" "Prop" "Vehicle"
After your find command you need to get the entity using the commands find() or findResult()
findResult(#) - # is the number of entity you wish to get, such as players. If there were 3 players, findResult(2) would grab the second player
find() - Is exactly like findResult(1)
An example to get an entity would be
e2 Code:
@name
@inputs
@outputs
@persist Player:entity
@trigger All
interval(10)
findByClass("Player")
Player = findResult(2)
This expression get the second player that joined the servers entity. You can now find out his position with Player:pos() or height with Player:height()
ApplyForce
ApplyForce is used a lot. Its the equivalent to a vector thruster, however it uses the whole prop. You can only use this on props you own however. They are fairly simple to make, however there is a forumla.
V = (Where you want it to go) – (Where it is now)
P:applyForce((V*25 – P:vel()) * P:mass())
P being the prop and V being the vector.
Here is an expression that will fly over your head.
Code:
@name E2 Hat
@inputs
@outputs
@persist V:vector
@trigger All
interval(10)
V = owner():shootPos() + vec(0,0,50) - entity():pos()
entity():applyForce((V*25 - entity():vel()) * entity():mass())
entity() is the Expression 2 Chip and ShootPos is the height at which you fire your gun.
There is also applyAngForce() which will let you rotate your prop, however this is cursed so I will explain it later.
Chat Commands
Chat commands are basically the text receiver. These commands involve the use of strings, usually not too many. Since there are not that many commands, I will list a few.
runOnChat(1) - This is exactly like interval, however it only updates when something is said in chat.
lastSaid() - This will give you the string of what was said last in chat. Can also be written as
Entity:lastSaid() - This will give you the last thing a certain player said.
lastSpoke() - This will give you the entity of who said something last.
lastTimeSaid() - This will give you the time the last thing was said, usually used in cases with intervals.
I will demonstrate a simple expression that will output a 1 if the word "boom" is used.
e2 Code:
@name Explode
@inputs
@outputs Explode
@persist
@trigger All
runOnChat(1)
if(owner():lastSaid() == "boom") {Explode = 1} else {Explode = 0}
In this expression, if the owner of the chip said "Boom", Explode will equal one until something new is said in chat.
Concmd (Console Commands)
"Concmd", short for Console Commands are very self explanatory. This function allows you to input a string into your console. This can be used for all kinds of things, such as chatbots and aimbots. These commands can only be used on the owner. However you can make someone copy your expression and it will work as well. This is client side, so it may be turned off using wire_expression2_concmd 0 and many admins have this turned off.
If you have an interval, you must apply some logic to the expression. If not done correctly, the interval will constantly use the concmd and spam your console. This can be avoided by using "~" which looks for a change. Here is a simple expression that will make you say "Hi" when a button is pressed.
e2 Code:
@name Concmd HI
@inputs Button
@outputs
@persist
@trigger All
if(Button & ~Button) {concmd("say Hi")}
I am assuming that you noticed the (Button & ~ Button), this is the logic I was speaking about earlier. Basically it says
If button is one, and there has been a change in the button = concmd.
This is how you avoid console spam, with a regular button, the expression will constantly update as long as the button is equal to one. However the button can only change twice, and that Is when you turn it on and off.
Because the concmd is using strings, the same principle applies, you can add to the string, cut the string, and what not. Here is an example
e2 Code:
@name Concmd HI
@inputs Button
@outputs
@persist
@trigger All
if(Button & ~Button) {concmd("say Hi, I am "+owner():name())}
Remember to put a space after your last word, to avoid having yourself say
Hi, I amBob
Rangers
The internal ranger is much better then the wire ranger, only because you can do a lot more things with it. This is where the commands get a little more complicated however. First you will need to define it on the first 5 lines as R:ranger. Also, you will require an interval for rangers to function. Because it is a little more complicated, I think rangers deserve a basic command index.
ranger(range) - This will create a ranger that starts from the expression and goes directly up compared to the expression (For example, if the expression was tilted, the ranger will be tilted to).
ranger(range,x,y) - This will create a ranger that starts from the expression and goes to the local X, Y coordinate. This is to say, if you put ranger(500,50,0), the ranger will be on the right, because the X value is 50.
rangerOffset(Vector,Vector) - This is my favorite ranger function. It creates a ranger between two vectors.
Here are some options that you can add to the ranger, these should be put after the ranger.
rangerHitWater(N) - 1 / 0
rangerIgnoreWorld(N) - 1 / 0
rangerDefaultZero(N) - 1 / 0
These are the commands that you use to retrieve data from the ranger.
R:distance() - This will output the rangers distance.
R:position() - This will output where the ranger is hitting.
R:entity() - This will output the entity the ranger is hitting.
R:hit() - This outputs a 1 if the ranger is hitting something, or a 0 if it is not.
Although this may seem like a lot to remember, you will rarely be using them all at the same time. Here is a simple expression that will be like a trip mine, just spawn it on a wall.
e2 Code:
@name Trip mine
@inputs
@outputs Explode
@persist R:ranger
@trigger All
interval(10)
R = ranger(500)
rangerIgnoreWorld(1)
rangerDefaultZero(1)
Explode = R:hit()
Console Screens
Console screens are pretty easy to learn and a lot of fun to use from time to time. Usually once a person learns this, they go off and start making a giant expression using it. This will require you to make a new variable in the first five lines, S:wirelink. *** Important: Please Please PLEASE, do not use an interval unless you actually NEED to when using this function. This could cause massive lag ***
First is setup, Create a Console Screen any size will do. Now take out a new tool called "Expression 2 - Wirelink" above your gate tool. Now click on your screen.
Make an expression, on the back is always good for me. For inputs, write S:wirelink. Close out of the expression screen and wire S:wirelink from the expression, to the wirelink of the screen. Remember to wire Clk from the screen to a button or something. Also, you should wire the screens reset to another button. Now we are all set up.
There are many commands for the Console Screen, some more advanced then others, however this is a beginners tutorial so I will stick with the basics.
S:writeString("String",Xpos,Ypos,Color,BGColor,Fla shing(1/0)
You do not have to fill out all this information, you can simply have S:writeString("String",Xpos,Ypos) and the text would be white with not background.
S:writeCell(2041,1) -- Resets your screen
S:writeCell(2042,Color) -- Adds a background color
Please be careful with blue commands, they could mess up your expression if you do not use them properly.
Ok before I begin to tell you about some of the commands, I would like to show you how the color system works. It’s actually very easy, but you would have to figure it out first. The color system is like
(255,255,255), except think that the max is 9 and you can have no commas. So for example red would be 900 (9,0,0) and green would be 90 (0,9,0) and blue would be 9 (0,0,9).
Here is a basic example of writing to the screen
e2 Code:
@name
@inputs S:wirelink
@outputs
@persist
@trigger all
S:writeString("Hello World",1,1,9,90,0)
As basic as it can get, right? This expression will write "Hello World" in blue letters on a green background.
I will use a writeCell in this example to make the screens background white.
e2 Code:
@name
@inputs S:wirelink
@outputs
@persist
@trigger all
S:writeCell(2042,999)
S:writeString("Hello World",1,1,9,90,0)
Now before you start playing with these commands, remember to use the screens reset after each update. Otherwise you will get copies of what you wrote. However you can also use the S:writeCell(2041,1) command to reset your screen. Here is an example of using this command.
For this expression it is not required for you to press the reset button yourself.
e2 Code:
@name
@inputs S:wirelink Button
@outputs
@persist
@trigger all
S:writeCell(2042,999)
if(!Button) {
S:writeCell(2041,1)
S:writeString("Hello World",1,1,9,90,0)
} else {
S:writeCell(2041,1)
S:writeString("Goodby World",1,1,9,90,0)
}
Basically, when button = 0, the screen will say "Hello world", but when the button = 1, the screen will say "Goodby World." For this to work, you would have to reset the screen each time the text changes. This is because when you tell the screen to write a string, it stays there, until you reset it. Now if we didn't add the S:writeCell(2041,1) the two strings will overlap.
Obviously you can have more then one write string on the screen at one time. They have to be in different places however. Here is an example of a screen that will print your name.
e2 Code:
@name
@inputs S:wirelink Button
@outputs
@persist
@trigger all
S:writeCell(2041,1)
S:writeCell(2042,999)
S:writeString("Hello,",1,1,9,90,0)
S:writeString(entity():owner():name(),1,2,9,90,0)
This expression will make the screen say, "Hello," and then your name under it. So for me it would say:
"Hello,
<{BT}> Spectre {Cat}"
Now many people like to integrate keyboards with the console screen. Now this is a bit more advanced to do, but I don't think my tutorial would be complete without telling you how. For this expression, you will need an interval (Remember the lower you make it, the more laggy the screen will be).
Now the keyboard doesn't work how I wish it did, by outputting the letter you pressed. Instead it outputs a number, and each number represents a letter. I know there is a place that tells you what each number represents, and if anyone would be kind enough to post it, I will add it to tutorial.
Fortunately you do not have to worry about decoding it, because wiremod was kind enough to give us the command toChar() which decodes it for us. So to do this, add a "Wire keyboard" to the screen, I like to put it under the screen, because it looks nice. In the next expression wire the keyboard input into the memory of the keyboard.
e2 Code:
@name
@inputs S:wirelink Keyboard
@outputs
@persist String:string
@trigger all
if(first()) {
S:writeCell(2041,1)
S:writeCell(2042,999)
}
if(Keyboard & ~Keyboard) {String += toChar(Keyboard)}
S:writeString(String,2,2,9,90,0)
You should notice that I have if(first()) this means that if the chip is spawned then it will run the if statement. I have this because since we have an interval, we do not want the screen resetting every 100 milliseconds. Also you might notice that we added logic again from before, this is to prevent the spamming of the letter you pressed. The reason this works is because when you press a letter, it does
String = String + Letter. {String += toChar(Keyboard)}
Most likely, you will start to make an expression, that is waaay over complicated using these commands... Like me :D
CatOS Beta
Holograms
I have come to know Holograms as one of the best parts about E2, and we have my buddy Mclovin to thank for that =) .
Holograms are basically props that are striped of all physics, so you see them, but you really can’t do anything to them. They also have the unique feature to scale the holograms to anything you want (However there is a max). The commands to control there are actually pretty simple, so I've included them in this tutorial.
First off you need to know the basic functions:
Code:
holoCreate(Index,Vector,Scale,Angle,Color) - this is to create a hologram.
holoCreate(Index,Vector,Scale,Angle)
holoCreate(Index,Vector,Scale)
holoCreate(Index,Vector)
holoCreate(Index
holoPos(Index,Vector) - Sets the vector of a hologram
holoColor(Index,Color,Alpha) - Sets the color of a hologram
holoScale(Index,Vector) - Sets the scale of a hologram
holoAngle(Index,Angle) - Sets the angle of a hologram
holoModel(Index,String) - Sets the model of a hologram (Continue reading for help)
holoParent(Index,Index) - This is basically like weld with the holograms. Once you do this, wherever you move one hologram, the other one will go as well. You can also parent holograms to entities.
holoDelete(Index)
These are the basic commands you will be using. Notice the Index, this is how you tell the command which hologram to control. So logically, you should set each hologram to have a different index.
HoloModel is a bit different then what you might think, there are only 14 models you can use. These are
Code:
"cone"
"cube"
"cylinder"
"icosphere"
"icosphere2"
"icosphere3"
"prism"
"pyramid"
"sphere"
"sphere2"
"sphere3"
"torus"
"torus2"
"torus3"
So say you wanted to make a holo Sphere, you would write holoModel(1,"sphere"). Simple as that.
How to scale it is pretty self explanatory, you put in the vector of how large you want it to be, for example:
holoScale(1,vec(2,2,1))
Would make a rectangle, 2 units length, 2 units width, and 1 unit high.
Now you would think to make a hologram you would just do, holoCreate(1), and you would be correct, IF you did not have an interval. To do holoCreate(1) and have an interval would create massive lag, because you are creating a brand new hologram every interval. So we will have to approach this a different way.
Before we get too far, you will notice that I only create holos with holoCreate(Index) and not holoCreate(Index,Vector,Scale,Angle,Color). This is because I find it easier to understand later. You do not need to do it my way however.
I hope you all remember the if(first()) thing I mentioned earlier, this is what we use. Here is a quick example of how to make a hologram circle hover above your expression.
e2 Code:
@name Holo Example
@inputs
@outputs
@persist
@trigger
interval(10)
if(first()) {
holoCreate(1)
holoModel(1,"sphere")
}
holoPos(1,entity():pos()+vec(0,0,50))
Now the reason I put holoModel() in the first() statement is because we really don't need to update the model every 10milliseconds
You can create more then one holo at a time too. Like:
e2 Code:
@name Holo Example
@inputs
@outputs
@persist
@trigger
if(first()) {
holoCreate(1)
holoCreate(2)
}
holoPos(1,entity():pos()+vec(0,0,10))
holoPos(2,entity():pos()+vec(0,0,20))
I said I would not talk about while() loops but I might just mention that it’s out there. While I highly recommend that you do not use these loops until you are a bit more experienced with wiremod. Ill show you how to use one here.
e2 Code:
@name Holo Example
@inputs
@outputs
@persist
@trigger
if(first()) {
while(I < 20) {I++
holoCreate(I)
}
}
To me, the best way to explain while() loops are that they are if statements, that have intervals built in.
In this statement I'm saying:
While I is less the 20, I++, holoCreate(I). This will create 20 holograms. If you don't understand this, don't worry, just stick with the basics.
Basically, anything you can do with applyForce or applyAngForce you can do with Holograms, without the formulas. For example, making a Triangle rotate over your head.
e2 Code:
@name Holo Example
@inputs
@outputs
@persist
@trigger
interval(10)
if(first()) {
holoCreate(1)
holoModel(1,"pyramid")
}
holoPos(1,owner():shootPos()+vec(0,0,20))
if(I < 180) {I++}
if(I == 180) {I = -180}
holoAng(1,ang(0,I,0))
Here is something I made with holograms :D
Cat's Hologram Chess
Wirelink
Wirelink is a very useful tool if you know how to use it. Previously in the Console Screen part of this tutorial, you used wirelink to get text to your screen. This is not all the wire link does however. The best way to explain this, is that you can wire up more then 30 different things with one wirelink. This is commonly used in Advanced Pod controllers, but it can also be used in almost anything that has a wiremod output (Except other Expression).
Here is a short list of the basic functions that you can use.
XWL:number(S) - You can link this to anything that outputs a number, ex: 1 , 0
XWL:vector(S) - You can link this to anything that outputs a vector
XWL:string(S) - You can link this to anything that outputs a string
XWL:entity(S) - Same with entity...
The pod controller is really the best way to explain how to use this tool, basically because of its massive amount of outputs. First comes set up, spawn an Advanced Pod Controller and hook it up to a chair (If you do not know how to use an Advanced Pod Controller, then this is not the right tutorial for you). Now for the inputs on your expression, put P:wirelink. Take out the wirelink tool (Located in the tools section of your wiremod menu) and simply click on the Advanced Pod Controller. Now wire the input from the expression, to the newly created wirelink output on your advanced pod controller (Go slow when looking for the wirelink, or you will miss it and get angry).
In this code you will make the game display if you are hitting W, S, A, or D. Using the function hint("String",How long it will appear)
When setting up the function P:number(S) please remember that it is case sensitive.
e2 Code:
@name Wirelink Example
@inputs P:wirelink
@outputs
@persist W A S D
@trigger all
runOnTick(1)
W = P:number("W")
A = P:number("A")
S = P:number("S")
D = P:number("D")
if(W & $W) {hint("W",2)}
if(A & $A) {hint("A",2)}
if(S & $S) {hint("S",2)}
if(D & $D) {hint("D",2)}
The reason we are using P:number is because W A S D on the advanced pod controllers output numbers (1/0). This is why we would use P:number for buttons as well.
Pretty simple right =D
Now to make this a little more complicated I'm going to make the expression tell you WHO is pressing the button.
e2 Code:
@name Wirelink Example
@inputs P:wirelink
@outputs
@persist W A S D
@trigger all
runOnTick(1)
W = P:number("W")
A = P:number("A")
S = P:number("S")
D = P:number("D")
Name = P:entity("Entity"):driver():name()
if(W & $W) {hint(Name+" Has Pressed W",2)}
if(A & $A) {hint(Name+" Has Pressed A",2)}
if(S & $S) {hint(Name+" Has Presses S",2)}
if(D & $D) {hint(Name+" Has Pressed D",2)}
For this I'm using P:entity() and getting the Entity that the Advanced pod controller is outputting (Which is outputting the vehicle it is linked to). Then I am using Driver, to get who is driving the vehicle, and then using Name to get the name of the driver. So now it will say
"<{BT}> Spectre {Cat} Has Pressed A"
That is all for today, maybe I will make more later.
Please post for any suggestions or errors
A Beginners Guide To Expression 2 Thread
Bookmarks