tinyromeo
Active Member
Intro -
First you will need a text editor, notepad++ is what I use and recommend.
Next you will need a game, Eve Online is what I use and recommend, however, I will be teaching towards usefulness for all games.
Then you will need Innerspace, it is what I use and recommend.
Optionally you can get an extension for your game (if one exists) to enhance the amount of options you have available to you, ISXEve is what I use and recommend
Finally open up your LavishScript wiki in another tab or window so you can easily follow along, but I will try to link when possible.
Start your game with innerspace and press the tilde key to open the console (The little ` next to the number 1). Type the following and press enter:
There you have it, it is almost that easy.
echo is very useful for finding out why something isn't working, or if you need to know more about a situation.
Gives the session title
If you have an extension loaded (using ext isxeve or some other extension) you generally have access to character information through the use of Me
Should return your name when an extension is loaded (however not all extensions are the same so don't *expect* it to work)
Well thats fairly simply, so what do I do with that? Well lets turn it into an actual script.
Open Notepad++ (or whatever text editor you chose) and enter the following:
save this file in the folder innerspace/scripts (normally found in C:/Program Files(x86)/Innerspace/Scripts) as hello.iss
Back in game type into the console
There you have it... your first script. You can see that in addition to the echo we are now also defining a main function. The main function is required for all scripts, it is the starting point from which everything else branches off, and it is what keeps your script running. Without you will get an error when you try to run your script. Also notice the {}, these tell the script what all the function encompasses. These are also necessary, without them you will get some really funny looking errors.
One thing I recommend to get in the habit of now is to open and close all parenthesis, brackets, quotation marks, any thing that opens, close it immediately and then fill in the inside. This will help you to keep track of where your brackets are when you start using more complex calls, i.e
Build something like this in steps - example (ignore the complexity and watch the simple process)
You can see that by completing the brackets ahead of time you will save yourself the trouble of trying to count them out at the end of the statement.
Again ignore all the stuff you don't understand, just remember to complete your brackets before hand and this will save you tons of trouble in the end.
Ok so what now? Next we need to know how to store information for later. We do this using variables. Variables can be many things, numbers, letters or words, collections of numbers, or entire objects with entire datasets all their own. In order to use a variable you have to tell the script to set aside a little bit of memory for this data. To do this we need to declare it. So in the first script change it to match this
When declaring a variable you must tell the script what type of variable it is (in this case int) and what its name is (in this case Number). You can name a variable pretty much anything you want, and they are case specific (Name is different than name).
The types of variables range widely (see Object Types for a larger listing(also your individual extensions add more)), but it boils down to a few main ones
bool - Boolean value, TRUE or FALSE only, like a light switch it is only on or off.
int - Integer, any whole number, 1, 45, -9000, its range is about -2 billion to +2 billion
float - Any rational number, 3.14, 45628.893728, great when you need decimal points(note: use int64 for a higher range on whole numbers not float)
string - a sequence of letters and/or numbers (Hello is a string, Forty2 is a string)
index - is a collection of multiple objects, such as index:int index:string index:entity, an index is useful for sifting through collections of data, like all the enemies in your view, all the items in your bag, etc
I will go through each of these in time for now lets code.
Above-
when you run this it will output the value of Number (4). You can see that we can set a variable's value on declaration. Then we access it by ${Number}. Anytime you need access to the data stored inside you use ${Number}
Then you can see I am changing the value of Number and displaying it again. I change the value by using the int "method" Set. Methods are accessed by a colon : ( i.e. Number:Set)
[HR][/HR]
If you look inside the wiki for int you will see you have access to different "members" and "methods" of the int data type.
Again members are accessed with ${Number.Member} - Methods with Number:Method
Members access stored data, methods perform a task.
One of the members an int has is Float, meaning you can display this number as a float instead, and since ${Number} is an int it too has access to the Float member - ${Number.Float}
Some methods to note are Set, Inc, and Dec.
:Set - will set the number to the new number given - Number:Set[3]
:Inc - will increase the value by 1 or the number given - Number:Inc - Number:Inc[20]
ec - Opposite of Inc, Decreases value - Number
ec - Number
ec[20]
Neat thing about this is we can put any other numbers into these methods
[HR][/HR]
Next lets look at float
Pretty much same as before, but float has access to more members than int does and I wanted to make sure you understand members and methods before really moving forward
[HR][/HR]
float has the same methods - Set, Dec, Inc
But has many more ways of interpreting its more complex data
[HR][/HR]
Finally just a dabble on bool, these will be either TRUE or FALSE values, nothing else. They are small so they don't take much memory, and easy to read when we get into control statements later on.
[HR][/HR]
This all may seem a little excessive, but think of this. Lets say you have your extension loaded and you have access to the Me data set, there are going to be many members and methods that will make more sense to you
Examples from isxeve Me(character) datatype -
[HR][/HR]
One last thing on members... They can be cast into many different forms over and over again. Basically, remember that int types have the ability to output floats? and floats can become ints?
Obviously this is less than ideal to do, but when you need different information check the wiki. Members most of time will link to what their output is so you can see how to interpret the data that you will receive. ${Int.Float} links to the float datatype, ${Float.Int} will link to the int datatype
[HR][/HR]
Another practical example in isxeve the Character datatype does not have any information on whether or not I am currently in warp, but the Entity Datatype does. So how do we get from a character to an entity?
So that is how a character becomes an entity, or a float an int, or anything the datatype allows you to cast into.
[HR][/HR]
The Next Step - Control
[HR][/HR]
Alright so we have access to shiny numbers and fancy actions, but how do we use them together?
We need control statements, things like if, do..while , for.
Allow me to demonstrate
Here you can see we are asking if the number we stored is greater than 1. At first it is, after we make it smaller, it isn't. So you can see by making a comparison between two pieces of data can wield different actions. If the first evaluation is true perform the first action inside the {}, otherwise (else) perform the latter action.
[HR][/HR]
If requires a true or false statement, if 1 > 0, if 10 == 3. Remeber the bool I talked about earlier?
This will display "True" and "Not False"
Here we really see how if works. if true, do this, if false, don't do this. And finally you can get a statements opposite with the exclamation point !${False} will evaluate to TRUE
[HR][/HR]
Here we are just making the comparison between two stored numbers instead.
[HR][/HR]
Next we can do many different outcomes in one check
Here you see we have a variety of outcomes we want based on the one value. We can mix and match values pretty much any way we want it, but this will only process the first if to evaluate to true.
[HR][/HR]
So if you want multiple things to happen do not use else if, simply create another if statement
[HR][/HR]
You can also have multiple comparisons in one statement, requiring that many things are true in order to process
Here I am asking "If NumberA is greater than 1 AND NumberB is less than 2" so in this case BOTH statements must evaluate TRUE (which they will)
This way we can make sure many things are true before doing something
[HR][/HR]
In addition to asking "if true AND true" we can ask "if true OR true"
Here obviously NumberA is not less than 1, but NumberB IS less than 2, so here we have an either or approach.
[HR][/HR]
I won't get to much into it, but you can really tangle some pretty crazy webs as I am sure you are seeing.
You are also able to combine all these AND's and OR's into parenthesis and really make a mess.
Here we are making some more complex decisions. Basically this reads
"if (NumberA is less than 1 OR is greater than 3) OR (NumberB is greater than 0 AND less than 10)" the first question is false, but the second question is true so with the or between the two parenthesis this will evaluate to true. Don't worry if this doesn't quite make sense to you yet. It is rare to do this, and when you are going to ask this kind of question you will probably be more prepared to handle the answer.
[HR][/HR]
Quickly I want to talk about Equal, I used it once above, but didn't explain. I was informed a while back that Equal is much more effective than ==
Sounds funny, but I actually prefer using Equal now.
All the datatypes I explained above have access to Equal and it is the way you should make direct comparisons to data of those types.
Here is how
[HR][/HR]
Next I want to show you how to loop. You can create loops a few different ways, but my favorite is "while". Similar to if, while checks a statement, if it is true it will perform its action over and over until the statement is false. This is great when you are monitoring for a change, but be careful to not get caught in an infinite loop, you (almost) always want a way out of the loop. I will demonstrate both and why they might be useful
First finite loops...
This code will count up from 0 to 9 and then end.
[HR][/HR]
This way will start checking at 1 rather than 0, so it is important to know where you want to start and end your loop, and to be mindful of what the values could/will do while being checked.
[HR][/HR]
One final way is do...while
So this way is similar to the first, it will start at 0, however, this is guaranteed to run at least one cycle before it evaluates false.
[HR][/HR]
So something like
[HR][/HR]
Here is a tip to help you figure out why your script just plain isn't doing what you want it to
Lets pretend this was more complex and we couldn't figure out why NumA
ec wasn't happening. By using an echo before the if or while statements you can see what is evaluating true and false and recheck your results from there. In this case we would see an output of "TRUE && FALSE" so we would know that the second expression is evaluating wrong. So you would check all cases of NumA to see if there is a discrepancy in the logic. In this case really all we can say is it should probably say ${NumA.Equal[1]} instead of 0 if we want this if statement to succeed.
[HR][/HR]
A practical example involving eve would be, say I am docked and I want the script to wait until I am undocked
Here I am using the wait command. This will pause the script for a certain time (in tenths of a second, so wait 10 is wait 1 second) and then continue on.
So here basically I am checking once a second to see if I am in space, when I finally am the rest of the script can continue.
[HR][/HR]
One last thing before we can write a real script!!
${Math.Calc[]}
Math.Calc is required to do any sort of arithmetic in lavishscript. In contrast to the methods Inc and Dec, you can do arithmetic on values without changing their values.
I can only really show by example, but just know all math needs to be done with Math.Calc
${Math.Calc} will return a float, so if you want to maintain that you need to store it in a float. But like above it is just as easy to put it back into an int when you don't care about the decimal point
[HR][/HR]
Alright, lets make a script that will work in any game supported by Innerspace. Lets make a script that will allow the mouse to "wrap" around the screen. When the mouse reaches the bottom it goes to the top, when it reaches the left it goes to the right, etc
So we will need to learn more about what properties the mouse has and what methods we can use to modify the mouse...
An easy way to find the mouse in all of the huge lavishscript wiki is to simply type mouse into the search bar on the side. It will link to 2 main things, but it is easy to find out which you will need. Otherwise lazy asses can go to Mouse
Alright, lots of useful information in there... Looks like we can get the X and Y positions, then we can move it around, click buttons... holy cow look at all this cool shit in here!!
Next, since we want this to work on any screen size we will want to know how big our screen is, so again find the display datatype through searching, or else... Display
Ok there is a ton more information here... all we need are a few values, looks like Width and Height should do it.
There we are ${Mouse.X}, ${Mouse.Y}, ${Display.Width}, ${Display.Height}. All of them are int which we know pretty well by now.
And finally Mouse:SetPosition[x,y]
All pretty straight forward right?
Well lets mash it all together and see what we can come up with...
Alright first you'll notice while 1, this creates an infinite loop making sure the script never ends, so you will need to stop this script using the endscript command.
Then all we are doing is checking if the mouse hits one side of the screen and move it to the opposite side. Go ahead try it. Its pretty neat.
Well how do you feel? You have taken your first steps into a brave new world. Made a fully functioning script. So whats next?
Well we can dive right in, but I think if you haven't taken the time yet, you should go back over everything, click through the wikis that you are starting to understand a little more.
Write your own script using what you know, I'll bet there is something you are itching to do with the mouse or keyboard. I bet you could make something, start small, perhaps an auto login script? And it is great practice, don't ever forget that you have a mouse and keyboard when you are swimming in indexes of entities and items.
Speaking of indexes....
[HR][/HR]
Indexes, Functions, and more
[HR][/HR]
I want to show you the index. An index is a great place to store large sets of data of the same type. For instance, all the items in your inventory can be indexed, all the enemies visible to you can be indexed. Once indexed you can look through them with simple loops, making sifting of large datasets simple.
If you look in the index wiki you will notice there aren't many really useful members or methods readily available to us. The only one I want you to see right now is Insert. As you can guess Insert will add the specified piece of data to the index.
Still in the wiki in the upper right there is a box labeled "Object Type Vitals" inside you will see that index "inherits" from object container. This means that an index will also have the same members and methods as object container.
Object container has some more useful stuff in it, like Used, GetIterator, or Clear
The iterator is used to represent one specific element of the index, then moved to the next element when looping through your checking routine.
This all sounds complex, but an example will clear everything up
First we declare our index, since we want a group of ints we say index:int, if you want floats it is index:float, index:string, index:entity, etc
Then we need to declare an iterator to use for later.
Then we slide a bunch of numbers into the index (this is the hard manual way, there will be easier ways in your extension)
Numbers:GetIterator[] will set the Iterator object to the correct index (an iterator doesn't care what is in the index, it only points to the value stored in the index)
if ${Iterator:First(exists)} This does 2 things, Iterator:First sets the iterator to the first value, and (exists) checks to see if it is there at all.
while ${Iterator:Next(exists)} Again like above, it switches to the next value, and checks to see if it exists. if it doesn't exists the loop is terminated.
${Iter.Value} points to the current value. It could be any of the numbers we inserted into the index at the start, and each pass through the loop will be a different value.
[HR][/HR]
Here is another example real quick
Pretty neat way to make an index right?
Otherwise you will notice I used break and continue inside the loop this time, break will terminate the loop, continue will ignore everything below it and go on to the next cycle of the loop.
[HR][/HR]
Well how does this work in game you ask? You want to see the items in your cargo hold you say? Fine, an isxeve example
EVE:Execute thing opens the cargohold, which is necessary when reading items inside of it.
MyShip:GetCargo[index:item] This stores the index of items into the index you supply it
The rest you know, well should at least.
[HR][/HR]
Arguments and Strings
Are almost completely unrelated except for being introduced SIMULTANEOUSLY in this tutorial HERE WE GO
Pretend we saved this file as stringtest.iss
First thing to change is right up top function main() now has a string declaration in it? This means that instead of run stringtest, we now need to say more. try run stringtest apple or run stringtest b
The additional information is stored in _MyString, setting it to another string isn't necessary in this example, but there that is how you declare strings... duh
echo MyString just says it back to you, upper is in all caps, length is well the length.
Since Upper just returns another string we can switch the statement to all caps and search for a capital a, or conversely switch to lower caps and check for b.
[HR][/HR]
Here the arguments have default values if none are supplied
The loop spells out VarB one letter at a time, repeated VarA times.
[HR][/HR]
This one allows any number of arguments to be passed. They are stored in an array named ${Args}
An array is similar to an index, it stores a set of data. The advantage of an index over an array is the array's size is static, meaning it can not take on more elements after declaration. An index can be dynamically resized at anytime.
You just need to loop through each item and check its value against what you are looking for.
Rarely do I use this method, when you start needing this much input it is probably time to learn some GUI stuff, but for the sake of learning there it is.
[HR][/HR]
Making your own functions...
Easy!
[HR][/HR]
However, this now leads me to variable scope
Seriously study this, and actually run this one.
Variables can only be accessed in the scope they are available in. This means if I declare a variable in function main(), it is not available for use in function MyFunction().
You can get around this by creating variables that are available in a wider scope, like the entire script. It is important, however, to be careful about what you want available and where. And for that matter naming things to similar.
Another way around is passing the variable through the function's arguments also shown above.
When we start creating our own objects this is going to become very important, but for now just practice keeping your globals limited.
[HR][/HR]
So what are functions good for anyways? Well if you find yourself performing the same action over and over again you can make life easier by putting that action into a function. So instead of the same three lines haunting you 20 times over, you can slide them into a function for easy using later.
So I am going to play pretend for a little bit to make explaining this easier. Lets pretend I want to have a bag sorting routine for my fictional game. My fictional extension allows me access to indexes of items, items have a location member, a type member, and a move method. This all sounds pretty realistic right?
This obviously will not work with any game I know of, but the principle is the same. You can see how using function MoveTo can start to save you a tremendous amount of work? Not needing to wait on every check, not needing to echo every time, not needing to call moveto everytime, just one simple line to solve all your problems.
It doesn't save tons of space in the above example, but imagine you have 10 different types of items you want to check, maybe even split stacks as well.
[HR][/HR]
Or how about a custom wait function that randomizes wait timers, and counts down as well...
[HR][/HR]
One final special type of if... the switch
The switch will examine the data provided. In this case ints are easily examined. A switch also affords fall through which can be useful in certain scenarios
If Iter.Value is 1 you will get the output "Num 1"
if Iter.Vale is 5 you get Cinco
if it is 13, 14, or 15 you will get fall through
12 you get More fall through, Still falling, and the number 12
11 you get Still falling, and the number 11
Any other number you will just get the number
[HR][/HR]
Thats all I got in me for now. 12 hours of this in one night is enough. I now expect you to spend your fair share on study! And limitless time on developing.
Surf the wikis, they make some sense now right?
Rip apart publicly available scripts and make them your own.
Build your own scripts from scratch, abuse them until they do what you want them to do.
When/if I get back we will explore how to make all of this easier through the use of user defined objects, just imagine making your own methods, members, functions. Finally understanding what the pulse method is for. We will explore time. And so much more...
But I can only show you the links, you must be the one to click on them.
So for now, go forth and obey your TOS's and your EULA's.
First you will need a text editor, notepad++ is what I use and recommend.
Next you will need a game, Eve Online is what I use and recommend, however, I will be teaching towards usefulness for all games.
Then you will need Innerspace, it is what I use and recommend.
Optionally you can get an extension for your game (if one exists) to enhance the amount of options you have available to you, ISXEve is what I use and recommend
Finally open up your LavishScript wiki in another tab or window so you can easily follow along, but I will try to link when possible.
Start your game with innerspace and press the tilde key to open the console (The little ` next to the number 1). Type the following and press enter:
Code:
echo Hello
echo is very useful for finding out why something isn't working, or if you need to know more about a situation.
Code:
echo ${Session}
If you have an extension loaded (using ext isxeve or some other extension) you generally have access to character information through the use of Me
Code:
echo ${Me.Name}
Well thats fairly simply, so what do I do with that? Well lets turn it into an actual script.
Open Notepad++ (or whatever text editor you chose) and enter the following:
Code:
function main()
{
echo Hello
}
Back in game type into the console
Code:
run hello
One thing I recommend to get in the habit of now is to open and close all parenthesis, brackets, quotation marks, any thing that opens, close it immediately and then fill in the inside. This will help you to keep track of where your brackets are when you start using more complex calls, i.e
Code:
${Math.Calc[${Me.Ship.Module[${Slot}].CurrentCharges} - ${Me.Ship.Module[${Slot}].MaxCharges}]}
Code:
${}
${Math.Calc[]}
${Math.Calc[${} - ${}]}
${Math.Calc[${Me.Ship[].CurrentCharges} - ${Me.Ship[].MaxCharges}]}
${Math.Calc[${Me.Ship[${Slot}].CurrentCharges} - ${Me.Ship[${Slot}].MaxCharges}]}
Again ignore all the stuff you don't understand, just remember to complete your brackets before hand and this will save you tons of trouble in the end.
Ok so what now? Next we need to know how to store information for later. We do this using variables. Variables can be many things, numbers, letters or words, collections of numbers, or entire objects with entire datasets all their own. In order to use a variable you have to tell the script to set aside a little bit of memory for this data. To do this we need to declare it. So in the first script change it to match this
Code:
function main()
{
variable int Number
echo Hello
}
The types of variables range widely (see Object Types for a larger listing(also your individual extensions add more)), but it boils down to a few main ones
bool - Boolean value, TRUE or FALSE only, like a light switch it is only on or off.
int - Integer, any whole number, 1, 45, -9000, its range is about -2 billion to +2 billion
float - Any rational number, 3.14, 45628.893728, great when you need decimal points(note: use int64 for a higher range on whole numbers not float)
string - a sequence of letters and/or numbers (Hello is a string, Forty2 is a string)
index - is a collection of multiple objects, such as index:int index:string index:entity, an index is useful for sifting through collections of data, like all the enemies in your view, all the items in your bag, etc
I will go through each of these in time for now lets code.
Code:
function main()
{
variable int Number = 4
echo ${Number}
Number:Set[3]
echo ${Number}
}
when you run this it will output the value of Number (4). You can see that we can set a variable's value on declaration. Then we access it by ${Number}. Anytime you need access to the data stored inside you use ${Number}
Then you can see I am changing the value of Number and displaying it again. I change the value by using the int "method" Set. Methods are accessed by a colon : ( i.e. Number:Set)
[HR][/HR]
If you look inside the wiki for int you will see you have access to different "members" and "methods" of the int data type.
Again members are accessed with ${Number.Member} - Methods with Number:Method
Members access stored data, methods perform a task.
One of the members an int has is Float, meaning you can display this number as a float instead, and since ${Number} is an int it too has access to the Float member - ${Number.Float}
Some methods to note are Set, Inc, and Dec.
:Set - will set the number to the new number given - Number:Set[3]
:Inc - will increase the value by 1 or the number given - Number:Inc - Number:Inc[20]
Neat thing about this is we can put any other numbers into these methods
Code:
function main()
{
variable int Number = 4
variable int NumberB = 2
echo ${Number}
echo ${NumberB.Float}
Number:Inc[${NumberB}]
echo ${Number}
NumberB:Set[${Number}]
echo ${NumberB}
}
Next lets look at float
Code:
function main()
{
variable float Number = 48.35
echo ${Number}
Number:Set[-0.0003]
echo ${Number}
}
[HR][/HR]
float has the same methods - Set, Dec, Inc
But has many more ways of interpreting its more complex data
Code:
function main()
{
variable float Number = 321.1234567
variable float NumberB = 123.987654
echo ${Number.Int}
echo ${NumberB.Int}
echo ${Number.Deci}
echo ${NumberB.Milli}
echo ${Number.Round}
echo ${NumberB.Precision[5]}
echo ${Number}
Number:Inc[${NumberB}]
echo ${Number}
}
Finally just a dabble on bool, these will be either TRUE or FALSE values, nothing else. They are small so they don't take much memory, and easy to read when we get into control statements later on.
[HR][/HR]
This all may seem a little excessive, but think of this. Lets say you have your extension loaded and you have access to the Me data set, there are going to be many members and methods that will make more sense to you
Examples from isxeve Me(character) datatype -
Code:
function main()
{
echo ${Me.Name}
echo ${Me.InSpace}
echo ${Me.AutoPilotOn}
Me:Undock
Me:SetVelocity[10]
}
One last thing on members... They can be cast into many different forms over and over again. Basically, remember that int types have the ability to output floats? and floats can become ints?
Code:
function main()
{
variable float Number = 4.209
variable int NumberB = 4
echo ${Number.Int}
echo ${Number.Int.Float}
echo ${NumberB.Float}
echo ${NumberB.Float.Int}
echo ${NumberB.Float.Int.Float}
if ${Number.Int.Float.Equal[${NumberB.Float.Int}]}
{
echo "Its true!"
}
}
[HR][/HR]
Another practical example in isxeve the Character datatype does not have any information on whether or not I am currently in warp, but the Entity Datatype does. So how do we get from a character to an entity?
Code:
function main()
{
echo ${Me.Name}
echo ${Me.ToEntity.Name}
echo ${Me.ToEntity.Mode}
}
[HR][/HR]
The Next Step - Control
[HR][/HR]
Alright so we have access to shiny numbers and fancy actions, but how do we use them together?
We need control statements, things like if, do..while , for.
Allow me to demonstrate
Code:
function main()
{
variable int Number = 2
echo ${Number}
if ${Number} > 1
{
echo "Number is bigger than 1"
}
else
{
echo "Number is Smaller or equal to 1"
}
Number:Dec[1]
echo ${Number}
if ${Number} > 1
{
echo "Number is bigger than 1"
}
else
{
echo "Number is Smaller or equal to 1"
}
}
[HR][/HR]
If requires a true or false statement, if 1 > 0, if 10 == 3. Remeber the bool I talked about earlier?
Code:
function main()
{
variable bool True = TRUE
variable bool False = FALSE
if ${True}
{
echo "True"
}
if ${False}
{
echo "False"
}
if !${False}
{
echo "Not False"
}
}
Here we really see how if works. if true, do this, if false, don't do this. And finally you can get a statements opposite with the exclamation point !${False} will evaluate to TRUE
[HR][/HR]
Code:
function main()
{
variable int NumberA = 2
variable int NumberB = 1
echo ${NumberA}
if ${NumberA} > ${NumberB}
{
echo "NumberA is bigger than NumberB"
}
else
{
echo "NumberA is Smaller or equal to NumberB"
}
}
[HR][/HR]
Next we can do many different outcomes in one check
Code:
function main()
{
variable int Number = 2
echo ${Number}
if ${Number} > 1
{
echo "Number is bigger than 1"
}
elseif ${Number.Equal[1]}
{
echo "Number is equal to 1"
}
elseif ${Number} < 1
{
echo "Number is smaller than 1"
}
}
[HR][/HR]
So if you want multiple things to happen do not use else if, simply create another if statement
Code:
function main()
{
variable int NumberA = 10
variable int NumberB = 1
if ${NumberA} > ${NumberB}
{
echo "NumberA is bigger than NumberB"
}
if ${NumberB} < ${NumberA}
{
echo "NumberB is smaller than NumberA"
}
}
You can also have multiple comparisons in one statement, requiring that many things are true in order to process
Code:
function main()
{
variable int NumberA = 2
variable int NumberB = 1
if ${NumberA} > 1 && ${NumberB} < 2
{
echo "Both are True"
}
}
This way we can make sure many things are true before doing something
[HR][/HR]
In addition to asking "if true AND true" we can ask "if true OR true"
Code:
function main()
{
variable int NumberA = 2
variable int NumberB = 1
if ${NumberA} < 1 || ${NumberB} < 2
{
echo "At least one of those is True"
}
}
[HR][/HR]
I won't get to much into it, but you can really tangle some pretty crazy webs as I am sure you are seeing.
You are also able to combine all these AND's and OR's into parenthesis and really make a mess.
Code:
function main()
{
variable int NumberA = 2
variable int NumberB = 1
if (${NumberA} < 1 || ${NumberA} > 3) || (${NumberB} > 0 && ${NumberB} < 10)
{
echo "Something in there is doing something right?"
}
}
"if (NumberA is less than 1 OR is greater than 3) OR (NumberB is greater than 0 AND less than 10)" the first question is false, but the second question is true so with the or between the two parenthesis this will evaluate to true. Don't worry if this doesn't quite make sense to you yet. It is rare to do this, and when you are going to ask this kind of question you will probably be more prepared to handle the answer.
[HR][/HR]
Quickly I want to talk about Equal, I used it once above, but didn't explain. I was informed a while back that Equal is much more effective than ==
Sounds funny, but I actually prefer using Equal now.
All the datatypes I explained above have access to Equal and it is the way you should make direct comparisons to data of those types.
Here is how
Code:
function main()
{
variable int NumberA = 10
variable int NumberB = 3
if ${NumberA.Equal[${NumberB}]}
{
echo "B is not equal to A so we won't see this"
}
if ${NumberB.Equal[3]}
{
echo "3 should equal 3 yes?"
}
}
Next I want to show you how to loop. You can create loops a few different ways, but my favorite is "while". Similar to if, while checks a statement, if it is true it will perform its action over and over until the statement is false. This is great when you are monitoring for a change, but be careful to not get caught in an infinite loop, you (almost) always want a way out of the loop. I will demonstrate both and why they might be useful
First finite loops...
Code:
function main()
{
variable int Counter = 0
while ${Counter} < 10
{
echo ${Counter}
Counter:Inc
}
}
[HR][/HR]
Code:
function main()
{
variable int Counter = 0
while ${Counter:Inc} < 10
{
echo ${Counter}
}
}
[HR][/HR]
One final way is do...while
Code:
function main()
{
variable int Counter = 0
do
{
echo ${Counter}
}
while ${Counter:Inc} < 10
}
[HR][/HR]
So something like
Code:
function main()
{
variable bool False = FALSE
do
{
echo "See it runs once even though it is false"
}
while ${False}
}
Here is a tip to help you figure out why your script just plain isn't doing what you want it to
Code:
function main()
{
variable int NumA = 1
variable int NumB = 1
echo "${NumA.Equal[${NumB}]} && ${NumA.Equal[0]}"
if ${NumA.Equal[${NumB}]} && ${NumA.Equal[0]}
{
echo "Why won't this Happen?"
NumA:Dec
}
}
[HR][/HR]
A practical example involving eve would be, say I am docked and I want the script to wait until I am undocked
Code:
function main()
{
while !${Me.InSpace}
{
echo "Waiting to undock"
wait 10
}
echo "Finally in Space"
}
So here basically I am checking once a second to see if I am in space, when I finally am the rest of the script can continue.
[HR][/HR]
One last thing before we can write a real script!!
${Math.Calc[]}
Math.Calc is required to do any sort of arithmetic in lavishscript. In contrast to the methods Inc and Dec, you can do arithmetic on values without changing their values.
I can only really show by example, but just know all math needs to be done with Math.Calc
Code:
function main()
{
variable int NumberA = 5
variable int NumberB = 2
if ${Math.Calc[${NumberA} - ${NumberB}]} < 4
{
echo "5 - 2 is less than 4"
}
NumberB:Set[${Math.Calc[${NumberA} + 2]}]
if ${NumberB} > ${NumberA}
{
echo "5 + 2 is greater than 5"
}
if ${Math.Calc[5 - 3].Equal[2]}
{
echo "does 5 - 3 equal 2?"
}
if ${Math.Calc[7 / 3].Int.Equal[2]}
{
echo "Math.Calc returns a float, so we can make it into an int if we want"
}
}
[HR][/HR]
Alright, lets make a script that will work in any game supported by Innerspace. Lets make a script that will allow the mouse to "wrap" around the screen. When the mouse reaches the bottom it goes to the top, when it reaches the left it goes to the right, etc
So we will need to learn more about what properties the mouse has and what methods we can use to modify the mouse...
An easy way to find the mouse in all of the huge lavishscript wiki is to simply type mouse into the search bar on the side. It will link to 2 main things, but it is easy to find out which you will need. Otherwise lazy asses can go to Mouse
Alright, lots of useful information in there... Looks like we can get the X and Y positions, then we can move it around, click buttons... holy cow look at all this cool shit in here!!
Next, since we want this to work on any screen size we will want to know how big our screen is, so again find the display datatype through searching, or else... Display
Ok there is a ton more information here... all we need are a few values, looks like Width and Height should do it.
There we are ${Mouse.X}, ${Mouse.Y}, ${Display.Width}, ${Display.Height}. All of them are int which we know pretty well by now.
And finally Mouse:SetPosition[x,y]
All pretty straight forward right?
Well lets mash it all together and see what we can come up with...
Code:
function main()
{
while 1
{
if ${Mouse.X} > ${Math.Calc[${Display.Width} - 2]}
{
Mouse:SetPosition[2, ${Mouse.Y}]
}
if ${Mouse.X} < 2
{
Mouse:SetPosition[${Math.Calc[${Display.Width} - 2]}, ${Mouse.Y}]
}
if ${Mouse.Y} > ${Math.Calc[${Display.Height} - 2]}
{
Mouse:SetPosition[${Mouse.X}, 2]
}
if ${Mouse.Y} < 2
{
Mouse:SetPosition[${Mouse.X}, ${Math.Calc[${Display.Height} - 2]}]
}
}
}
Then all we are doing is checking if the mouse hits one side of the screen and move it to the opposite side. Go ahead try it. Its pretty neat.
Well how do you feel? You have taken your first steps into a brave new world. Made a fully functioning script. So whats next?
Well we can dive right in, but I think if you haven't taken the time yet, you should go back over everything, click through the wikis that you are starting to understand a little more.
Write your own script using what you know, I'll bet there is something you are itching to do with the mouse or keyboard. I bet you could make something, start small, perhaps an auto login script? And it is great practice, don't ever forget that you have a mouse and keyboard when you are swimming in indexes of entities and items.
Speaking of indexes....
[HR][/HR]
Indexes, Functions, and more
[HR][/HR]
I want to show you the index. An index is a great place to store large sets of data of the same type. For instance, all the items in your inventory can be indexed, all the enemies visible to you can be indexed. Once indexed you can look through them with simple loops, making sifting of large datasets simple.
If you look in the index wiki you will notice there aren't many really useful members or methods readily available to us. The only one I want you to see right now is Insert. As you can guess Insert will add the specified piece of data to the index.
Still in the wiki in the upper right there is a box labeled "Object Type Vitals" inside you will see that index "inherits" from object container. This means that an index will also have the same members and methods as object container.
Object container has some more useful stuff in it, like Used, GetIterator, or Clear
The iterator is used to represent one specific element of the index, then moved to the next element when looping through your checking routine.
This all sounds complex, but an example will clear everything up
Code:
function main()
{
variable index:int Numbers
variable iterator Iterator
Numbers:Insert[1]
Numbers:Insert[6]
Numbers:Insert[78]
Numbers:Insert[-45]
Numbers:Insert[1000]
Numbers:Insert[131]
Numbers:Insert[-1]
Numbers:GetIterator[Iterator]
if ${Iterator:First(exists)}
do
{
echo ${Iter.Value}
}
while ${Iterator:Next(exists)}
}
Then we need to declare an iterator to use for later.
Then we slide a bunch of numbers into the index (this is the hard manual way, there will be easier ways in your extension)
Numbers:GetIterator[] will set the Iterator object to the correct index (an iterator doesn't care what is in the index, it only points to the value stored in the index)
if ${Iterator:First(exists)} This does 2 things, Iterator:First sets the iterator to the first value, and (exists) checks to see if it is there at all.
while ${Iterator:Next(exists)} Again like above, it switches to the next value, and checks to see if it exists. if it doesn't exists the loop is terminated.
${Iter.Value} points to the current value. It could be any of the numbers we inserted into the index at the start, and each pass through the loop will be a different value.
[HR][/HR]
Here is another example real quick
Code:
function main()
{
variable index:int Numbers
variable iterator Iter
variable int Counter = 0
while ${Counter:Inc} < 20
{
Numbers:Insert[${Counter}]
}
echo ${Numbers.Used}
Numbers:GetIterator[Iter]
if ${Iter:First(exists)}
do
{
if ${Iter.Value.Equal[10]}
{
echo "Stopping on 10"
break
}
elseif ${Iter.Value.Equal[2]}
{
echo "Number is 2... continuing"
continue
}
echo ${Iter.Value}
}
while ${Iter:Next(exists)}
}
Otherwise you will notice I used break and continue inside the loop this time, break will terminate the loop, continue will ignore everything below it and go on to the next cycle of the loop.
[HR][/HR]
Well how does this work in game you ask? You want to see the items in your cargo hold you say? Fine, an isxeve example
Code:
function main()
{
variable index:item Cargo
variable iterator Iter
EVE:Execute[OpenCargoHoldOfActiveShip]
wait 10
MyShip:GetCargo[Cargo]
Cargo:GetIterator[Iter]
if ${Iter:First(exists)}
do
{
echo ${Iter.Value.Name}
}
while ${Iter:Next(exists)}
}
MyShip:GetCargo[index:item] This stores the index of items into the index you supply it
The rest you know, well should at least.
[HR][/HR]
Arguments and Strings
Are almost completely unrelated except for being introduced SIMULTANEOUSLY in this tutorial HERE WE GO
Code:
function main(string _MyString)
{
variable string MyString = ${_MyString}
echo ${MyString}
echo ${MyString.Upper}
echo ${MyString.Length}
if ${MyString.Upper.Find[A]}
{
echo "MyString contains an a"
}
if ${MyString.Lower.Equal[b]}
{
echo "MyString is b"
}
}
First thing to change is right up top function main() now has a string declaration in it? This means that instead of run stringtest, we now need to say more. try run stringtest apple or run stringtest b
The additional information is stored in _MyString, setting it to another string isn't necessary in this example, but there that is how you declare strings... duh
echo MyString just says it back to you, upper is in all caps, length is well the length.
Since Upper just returns another string we can switch the statement to all caps and search for a capital a, or conversely switch to lower caps and check for b.
[HR][/HR]
Code:
function main(int _VarA = 4, string _VarB = "Auto")
{
variable int i
do
{
i:Set[1]
do
{
echo ${_VarB.Mid[${i},1]}
}
while ${i:Inc} <= ${_VarB.Length}
}
while ${_VarA:Dec} > 0
}
The loop spells out VarB one letter at a time, repeated VarA times.
[HR][/HR]
Code:
function main(... Args)
{
variable int i = 1
if ${Args.Size} > 0
{
do
{
if ${Args[${i}].Find[a]}
{
echo ${Args[${i}]}
}
}
while ${i:Inc} <= ${Args.Size}
}
}
An array is similar to an index, it stores a set of data. The advantage of an index over an array is the array's size is static, meaning it can not take on more elements after declaration. An index can be dynamically resized at anytime.
You just need to loop through each item and check its value against what you are looking for.
Rarely do I use this method, when you start needing this much input it is probably time to learn some GUI stuff, but for the sake of learning there it is.
[HR][/HR]
Making your own functions...
Code:
function main()
{
echo "main function"
call MyFunction
}
function MyFunction()
{
echo "MyFunction"
}
[HR][/HR]
However, this now leads me to variable scope
Code:
variable(script) int MyGlobalInt
function main(int _MyLocalInt)
{
variable int MyLocalInt = ${_MyLocalInt}
MyGlobalInt:Set[${MyLocalInt}]
call MyFunction ${MyLocalInt}
echo Main
echo ${MyGlobalInt}
echo ${_MyFunctionInt}
}
function MyFunction(int _MyFunctionInt)
{
echo ${_MyLocalInt}
echo ${MyLocalInt}
echo ${MyGlobalInt}
echo ${_MyFunctionInt}
MyGlobalInt:Set[34]
}
Variables can only be accessed in the scope they are available in. This means if I declare a variable in function main(), it is not available for use in function MyFunction().
You can get around this by creating variables that are available in a wider scope, like the entire script. It is important, however, to be careful about what you want available and where. And for that matter naming things to similar.
Another way around is passing the variable through the function's arguments also shown above.
When we start creating our own objects this is going to become very important, but for now just practice keeping your globals limited.
[HR][/HR]
So what are functions good for anyways? Well if you find yourself performing the same action over and over again you can make life easier by putting that action into a function. So instead of the same three lines haunting you 20 times over, you can slide them into a function for easy using later.
So I am going to play pretend for a little bit to make explaining this easier. Lets pretend I want to have a bag sorting routine for my fictional game. My fictional extension allows me access to indexes of items, items have a location member, a type member, and a move method. This all sounds pretty realistic right?
Code:
function main()
{
variable index:item Items
variable iterator Iter
Me:GetItemsInBag[Items]
Items:GetIterator[Iter]
if ${Iter:First(exists)}
do
{
if ${Iter.Value.Type.Equal["Ammo"]} && !${Iter.Value.Location.Equal["AmmoBag"]}
{
call MoveTo ${Iter.Value} "AmmoBag"
}
if ${Iter.Value.Type.Equal["Potion"]} && !${Iter.Value.Location.Equal["PotionBag"]}
{
call MoveTo ${Iter.Value} "PotionBag"
}
}
while ${Iter:Next(exists)}
}
function MoveTo(item _Item, string _Location)
{
echo "${_Item.Value.Type} not in ${_Location} - Moving"
Item:MoveTo[${_Location}]
wait 10
}
It doesn't save tons of space in the above example, but imagine you have 10 different types of items you want to check, maybe even split stacks as well.
[HR][/HR]
Or how about a custom wait function that randomizes wait timers, and counts down as well...
Code:
function main()
{
call RandomWait 2 4
call RandomWait 5 6
call RandomWait 3 3
}
function RandomWait(int _Range, int _MinLength)
{
variable int i = ${Math.Rand[${_Range}]:Inc[${_MinLength}]}
do
{
echo "Waiting - ${i}"
wait 10
}
while ${i:Dec} > 0
}
One final special type of if... the switch
Code:
function main()
{
variable index:int Numbers
variable iterator Iter
variable int Count = 20
while ${Count:Dec} > 0
{
Numbers:Insert[${Count}]
}
Numbers:GetIterator[Iter]
if ${Iter:First(exists)}
do
{
switch ${Iter.Value}
{
case 1
echo "Num 1"
break
case 5
echo "Cinco"
break
case 13
case 14
case 15
echo "Fall through"
break
case 12
echo "More fall through"
case 11
echo "Still falling"
case default
echo ${Iter.Value}
break
}
}
while ${Iter:Next(exists)}
}
If Iter.Value is 1 you will get the output "Num 1"
if Iter.Vale is 5 you get Cinco
if it is 13, 14, or 15 you will get fall through
12 you get More fall through, Still falling, and the number 12
11 you get Still falling, and the number 11
Any other number you will just get the number
[HR][/HR]
Thats all I got in me for now. 12 hours of this in one night is enough. I now expect you to spend your fair share on study! And limitless time on developing.
Surf the wikis, they make some sense now right?
Rip apart publicly available scripts and make them your own.
Build your own scripts from scratch, abuse them until they do what you want them to do.
When/if I get back we will explore how to make all of this easier through the use of user defined objects, just imagine making your own methods, members, functions. Finally understanding what the pulse method is for. We will explore time. And so much more...
But I can only show you the links, you must be the one to click on them.
So for now, go forth and obey your TOS's and your EULA's.