Tiritto thank you for banner I <3 it ^ ^
Hai guys ^ ^
Even doe I'm not offically developer I've been getting a lot of PMs asking me where and how to learn Lua and make scripts (not a bad thing, pls keep PMimg me anytime about anything )
I promissed some answers so here I give them!
I'm going to expalin the basic Lua concepts needed for GoS and gonna reverse one of my own scripts I made for demostration/testing purposes. (Part 2)
Unfortunatly It can't get attention it deserves due to my bussy schedule of coffie drinking and swiming
And traveling.... That's my new occupation ^ ^
>>>USE THIS TO TEST YOUR CODE<<<<
>>>OFFICAL GOS API<<<
Let's get started!
Unlike all many other languages Lua doesn't have datatypes. In C-langs you have int, float, double for numbers (plus few more), strings and chars for texts and ofc custom classes and structs that allow you to create your own datatype. In Lua NOPE!
Only two type which are automaticly implied: >Numbers and Words<. Custom datatypes exist in form of Tables and MetaTables :S
Each variable has local before it. In C-langs this is implied, unless you make it global. Lua is other way around you could say. Not making variable local makes it GLOBAL and accessable from ANYWHERE including Other Scripts :S
Obviously, this can cause problems :S
Global variables you will probably never use, and they come in handy in DataBases and some configurations that apply for your scripts. In that case make sure your variable name is hard to guess by accident, so only you and ppl who want to use it know how to do so : )
So local variables also have range and conflict resolution. In C++ and C# you can see use of "this" keyword (Lua has "self"), and methods that take pointers and references as parametes in order to change the value of variable outside of the method. In Lua this is not neccesay. We will get to methods soon since it's more of methods topic...
--how to define a variable? local ThisIsNumber; -- ";" is not neccesary but I code in C-langs so it's a habit local ThisIsAWord --no ";" is fine too --Those two are not number nor a word right now. They are >NIL<! nil is not 0. It's a value that is exactly equal to NOTTING AT ALL --It's undefined value and is used for many diferent purposes. I will expalin later more so let's give some value to our variables ^ ^ ThisIsNumber = 10; ThisIsAWord = "Ahri"; --notice the "". It's a signature of a string (word) like in other langs --variables example 2-- local MyCurrentHealth; --this variable is visible only in this script MyCurrentHealthGlobal; --this one is visible outside of it to --but lets get the value here so we don't leave them empty and sad This time by a method! MyCurrentHealth = GetCurrentHP(myHero); --not nil anymore I assumed that myHero is already defined so this works fine --Gona talk about range of variables later :)
Soooo... what I did in 2. example is method (or function if you prefer) call.
What is a function?
Functions
Function is a piece of code that takes something in, process it and returns the result. Imagine if we have to solve an equasion 4 times in a program... We have to write same code 4 times
To avoid this we make a function that does it for us ^ ^ (lazyass)
Simple example: Let's say we give program 4 numbers.
Program adds first tow, substracts last two and multiplies the results. If we need to do that only once, that's fine. But, if we have to do it many times?
--so 4 numbers. local n1; local n2; local n3; local n4; local theEndResult; --Let's say they are given some values by the user (gonna show you how later) --So this is wat user said n1 = 5; n2 = 2 n3 = 9 n4 = 4 theEndResult = (5+2) * (9-4) -- this equals 35 print (theEndResult) --prints 35 in the console --Here you always have to write this theEndResult = [numebrs here] --Let's do this the smart way function Calculate(a, b, c, d) return (a+b) * (c-d); end; --Now we can do this theEndResult = Calculate(5,2,9,4) print(theEndResult); --prints 35 --or this theEndResult = Calculate (n1, n2, n3, n4); print(theEndResult); --prints 35 again --EVEN this print (Calculate (n1, n2, n3, n4)); --We can send any number we want and get right results in a single line --This looks easy but imagine if function has 50 lines. It's a life saver --##Few functions you might use a lot## print(whatToPrint) --Prints stuff in on the screen console io.read() --Gets the input from the user (console too) math.sqrt(number) --Gets square root. Used in GoS for distance calculation by vector magnitude --math. has many cool functions ------GOS------ local myHero = GetMyHero(); --Obvious right? local MyLocation = GetOrigin(myHero) --Gives your location in 3D in x,z,y coords local MyMaxHP = GetMaximumHP(myHero) --Obvious? DUUUH local MyCurrentHP = GetCurrentHP(myHero) --DUUUUUH --etc... Read API, it's all there
Two more things. Flow control!
If statment and loops
Comon concept that is SAME in every programing language. Only diference is syntax. Stll I ll explain anyways ^O^
Let's say we made 2 functions before somewhere in the code. One is GoAllIn(target) and other is GoBak()
GoAllIn() will attack the target with all you got while GoBak() will keep safe distance by running and harrasing ocasionaly. How to know which one to call?
Let's say if our HP is bigger then target's we go all in and if not we keep it safe. Legit right?
(WRONG! legit would be to use % but I'm lazyass)
Let's code!
---example functions function GoAllIn(target) --go all in deffiniton here end; function GoBak()--notice it has no params. This is toally ok --go back deffiniton here end; --- local MyHero = GetMyHero(); local target = GetTarget(); --returns target by GoS logics (quoted lol) local ourCurrHP = GetCurrentHP(MyHero); local targetCurrHP = GetCurrentHP(target); ----possible branchings----- --1st if ourCurrHP > targetCurrHP then GoAllIn(target) else GoBak() end; -- end marks the end of if braching --2nd if not ourCurrHP < targetCurr then GoAllIn(target) else GoBak() end; --wat about "=" ?? Let's do this the right way! >_< function FarmAndHarras() --Imagine we declare it here end; if outCurrHP > targetCurrHP then GoAllIn(target) elseif ourCurrHP < targetCurrHP then GoBak() else FarmAndHarras() end; --If it's not < nor > it's = right? --end marks end of if branching. Elseif is not same as 2 times if. If we put if insted if elseif like: if outCurrHP > targetCurrHP then GoAllIn(target) end; if ourCurrHP < targetCurrHP then GoBak() else FarmAndHarras() end; --and first if gives true then second if will be checked anyways. In elseif only 1 if can give ture and it will check as long as it's not true. --Once it is ture, others wont be checked. Use this for options and branching. --So double if is WRONG. elseif is rigt
Let's talk about range! (Basic concept, more info here http://www.lua.org/pil/4.2.html)
--##RANGE##-- local hue = 3 do local hue= 4 print(hue); end; print(hue); --what's the output? ^ ^ --try this local statment = "Oh I get it now!" function example() local statment = "Tricky little fox >_<"; print (statment); end; example(); print(statment); Some useful functions are: --Range of a variable goes to it's instance if there is one like loops (while, for, repeat),do block and functions. --Range of those blocks of code ends with "end;" and after that the block is closed and range of variables is extended to next block --So if you have do method inside of while and inside of for loop (blockseption!) "end;" will close inside blocks and switch to next one
Loops
Outside of tables there are 2 loops main loops: While and For
While Loop
->Does stuff as long as a condition is satisfied. Condition expresion must be true
The syntax of a while loop in Lua programming language is:
while(condition) -- checked on begining and after every "end" do --starts the loop statement(s); end; --ends the loop
Example code:
a=10 while( a < 20 ) do print("value of a:", a) a = a+1 --this is called >>INCREMENT<<, C-langs a++ or ++a. without this line we would have infinite loop :S end;
Loops are usualy used with tables to print out their members. More on this later : )
For loop
Used to do stuff given number of times rather than to meet condition. Syntax below:
for init,max/min value, increment do statement(s) end;
Example:
for i=10,1,-1 --i=10 -> start value (refered to as counter sometimes), 1 -> end value, -1 is DECREMENT. It reduces value of counter while INCREMENT increses it do --Increment can be skipped if it's obvious, Lua will check for start and end value after that decide for -1 or +1. You can use +2 or any other value too but must do so manualy :) print(i) --gonna print the value end; --ends the loop and returns to start while counter is not equal to end vaule --infinite loop example
for i=10, 1, 1
do
print (i);
end; --I didn't test this tbh :S
Obviously, condition will never be met here...
Tables
A table is godly thing in Lua. It's an single/multi dimension array, class and namespace and sometimes with use of metatables it's a object or even an abstract class or interface!
I won't go through all if it, because.....reasions (I'm tbh and don't wanna spoil the fun of learning by yourself )
I will divide this in few parts:
-->Array
-->Multi Array (2D, example purposes)
-->Table of tables (simple imitation of "class")
-->Table of methods
--Single dimension array... Easy thing, put multiple stuff in single variable :) local array1D = {}; -->This marks empty table local array1D = {2,4,6,8,10}; --array in Lua starts at index "1", not "0" as in C-langs. "0" will giv you nil, not an error print(array1D[3]) --prints 6 print(array1D[0]) --prints nill print(array1D[5]) --print 10 print(array1D[98789]) --BLUE SCREEN OF DEATH INCOMING :O :O :O :O, Kidding, overreaching index gives nil, --in C-langs this exception will crash the program, here it's juts nil :) --*sigh of relef*-- --Wat if.... We wanna print all of the members in table? To do that 100% right via simple loop we need 2 conditions: --->Number of members in table --->No nil members in table defined by us --if we meet any of these conditions we don't need to meet other one :) (if not, we need metatable but not gonna go there for now) -------Let's do dis-------- local array = {1,3,5,7,9,nil,nil,15}; --let's assume we know there are 8 numbers local i; for i=1,8,1 do print(array[i]) end; --see what we did? "i" changes every time loop hits end and increses by "1". First time it's 1, den 2, den 3 till it's 8. --What if do not know how many we have BUT there are no nils in array local array = {1,3,5,7,9,11,13,15}; local i = 1; while (array[i]~=nil)--or while (array[i]), same thing do print (array[i]) i=i+1; end; ----GoS-like example--- --Let's assume we have list of all players in a table called Players local Players = GetAllPlayersExampleFunctionWhichIwillAddLater(); --so now we want to get enemy and ally players and find Ahri among them local AllyPlayers={}; local EnemyPlayers={}; --we know there are 10 players right? --Let's assume we declared IsAlly() function, I ll show you the acctual code in part 2, this is example function now :) local counter=10 for i=10,1,-1 --Runing the loop in oposide direction. Wanted to show you it's possible :) do if IsAlly(AllPlayers[i]) then table.insert(AllyPlayers, AllPlayers[i]) else table.insert(EnemyPlayers, AllPlayers[i]) end; end; --After the loop we should have 5 ally players and 5 enemy players. Let's say we want to find Ahri in our team. Let's use while this time ^ ^ while (GetObjectName(AllyPlayers[i]~="Ahri" or nil))--checks for Ahri, if non of 5 is Ahri then 6th will be nil and that means there is no Ahri in team :( do i=i+1; -- ^ ^ end; --Let's check if we have Ahri or not now shall we? if AllyPlayers[i]==nil then print("There is no Ahri in your team") else print("You have Ahri! You can't loose =^_^="); end; --You do check for enemy players with for loop :P
Smtg extra: Repeat loop
i = 3 while i > 1 do print(i.."\n")--"\n" is newline, it like pressing enter i = i - 1 end repeat print(i.."\n") i = i + 1 until i = 3 --results: 3 2 <-- last output of the WHILE 1 <-- first output of the REPEAT 2
-->2D Arrays
For loop is most comon here. Let's create matrix(rows,columns) 3,4.
Think of it as 3 arrays of 4 members! We will create 3 rows and have them hold 4 members ^ ^
local Matrix = {}; local rows = 3; local cols = 4; for i=1,rows do Matrix[i]={}; for j=1,cols do Matrix[i][j] = i + j; --some value, in this case sum of indexes print(Matrix[i][j]); end; end; --Not going to expalin too much, if you want to know PM me since it's not very common in GoS and there are --good explanations online
-->Table Of Tables ! (Tableseption) !
I introduced you with tables on small scale. Array is lame use of tables >_<
Difference betwen Array and a Table is indexing! Array has intiger indexes in ascending order.
In tables you can use string or even variable values as indexes ^ ^
local FoxyTable {"TailNumber"=9,"IsCool"=true}; --or FoxyTable.AmIAhri=true; --same as FoxyTable["AmIAhri"=true]; --now we can do this: print(FoxyTable.TailNumber); print(FoxyTable.AmIAhri);
So this is cool, but just as in variables this values are FIXED. What if the value changes? Like cooldowns and HP in game right? Hp is not same all the time, so we would have to change the HP every frame or every 100ms or smtg :S
Same goes for cooldowns... This is possible but imagine that while game is running you are changing the value all the time... Do I need to say that this will drop FPS?
Workaround: Table of Methods
Let's say we have a value that will change every 100ms. I will call this value TrickyValue. Now we need to store that value in SmartTable so that we we call print(smartTable) it get's print at IT'S CURRENT value. Not the old one.
--let's assume this value changes all the time local trickyValue = ChangeValueInTime(); --Let's assume it's 5 now local StupidTable = {["Foxy"] = {NumberOfTails = trickyValue, ["IsAhri"] = false}}; --Number of tails is 5 if StupidTable.Foxy.NumberOfTails == 9 then StupidTable.Foxy.IsAhri=true end; --so we want to check if the fox here is Ahri by cheching --her tail numberbut :(.... It's not fixed :S --Let's assume that at the moment we run this code number is 5, 0.3 sec later it's 4 then 8 etc. --We can see that we have number 5 stored in NumberOfTails print (StupidTable.Foxy.NumberOfTails)--prints 5 print (trickyValue)--prints 8 --#Problem#-- --Let's fix local StupidTable = nil; --Cuz it's stupid >_< So long you stupid table! local SmartTable = {["Foxy"] = {NumberOfTails = function() return trickyValue end, ["IsAhri"] = false}} --Method!!! --Nnotice we did not give a name ti method. This is known as Annonymous Method in C# (I think). It's not rlly a delegate doe :S --This method will get the trickyValue when we ask for it! But how to demand? :S if FoxyTable.Foxy.NumberOfTails() == 9 then FoxyTable.Foxy.IsAhri=true end; --() is method call! Remeber? We did it before :D --GOS EXAMPLE-- function CreateSpellBook(myHeroPtr) local Data = { ["Q"]={ isReady = function() return CanUseSpell(myHeroPtr,_Q) == READY end, lvl =function() return GetCastLevel(myHeroPtr,_Q) end, range = function() return GetCastRange(myHeroPtr,_Q) end, cmana = function() return GetCastMana(myHeroPtr,_Q) end, cd = function() return GetCastCooldown(myHeroPtr,_Q) end, sname = function() return GetCastName(myHeroPtr,_Q) end}, ["W"]={ isReady = function() return CanUseSpell(myHeroPtr,_W) == READY end, lvl =function() return GetCastLevel(myHeroPtr,_W) end, range = function() return GetCastRange(myHeroPtr,_W) end, cmana = function() return GetCastMana(myHeroPtr,_W) end, cd = function() return GetCastCooldown(myHeroPtr,_W) end, sname = function() return GetCastName(myHeroPtr,_W) end}, ["E"]={ isReady = function() return CanUseSpell(myHeroPtr,_E) == READY end, lvl =function() return GetCastLevel(myHeroPtr,_E) end, range = function() return GetCastRange(myHeroPtr,_E) end, cmana = function() return GetCastMana(myHeroPtr,_E) end, cd = function() return GetCastCooldown(myHeroPtr,_E) end, sname = function() return GetCastName(myHeroPtr,_E) end}, ["R"]={ isReady = function() return CanUseSpell(myHeroPtr,_R) == READY end, lvl =function() return GetCastLevel(myHeroPtr,_R) end, range = function() return GetCastRange(myHeroPtr,_R) end, cmana = function() return GetCastMana(myHeroPtr,_Q) end, cd = function() return GetCastCooldown(myHeroPtr,_Q) end, sname = function() return GetCastName(myHeroPtr,_R) end}, } return Data; end; --Taken from my SpellBook method I created for spell database :) --I could do value updates onLoop() but that would drop the FPS so I made it on demand ^ ^ local myFox = GetMyHero(); local AhriSpellBook = CreateSpellBook(myFox); --Let's check for cooldown on Q print (AhriSpellBook.Q.cd()); --TADA! :D
Wanted to do it all in one tut but it would be so huge so decided to seperate offical API examples and analysis from Lua introduction
-->Errors are possible, example methods won't run in Lua online compiler! You need to define them! Also, API functions won't run for same reason
CHALLANGE FOR YOU!
Whenever I picked one way, you solve the problem other way AND try to code my example functions : )
I will code all of them in PART 2 which will be rlly about GoS and will alow you to code your first assembly ^ ^
I was away for a while and API changed so need to update my assembly before I can reverse it for you guys :S
Part 2 comming soon ^ ^
Usefull stuff! Ask for more if you want I will share! <3 you guys! ^ ^
http://www.tutorials...ua_for_loop.htm
http://www.tutorials...ment_in_lua.htm
http://www.tutorials.../lua_tables.htm -->Read this!
For advanced padawans:
http://www.tutorials..._metatables.htm --> I understand this hueheuheueheue ( ̄ー ̄)
http://www.tutorials...ct_oriented.htm -->For brave ones!
Have fun learning nabs! (=^-^=)
If you have questions ask me (PM) or post below <3