Go Back   Codemasters Forums > Action, RPG and Strategy Games > Operation Flashpoint: Dragon Rising > English > Operation Flashpoint: Dragon Rising - Mission Editing and Modding Chat Zone
Sign In
Register on CodeM

Operation Flashpoint: Dragon Rising - Mission Editing and Modding Chat Zone A little area for all you mission editors and modders to chat and discuss ideas.

Reply
 
LinkBack Thread Tools Display Modes
Old 02-11-2009, 09:52 PM   #1 (permalink)
Senior Member
 
Join Date: Oct 2009
Location: New York
Posts: 462
Default [LUA] Tutorial: Fun with tables

This article isn't quite complete, but instead of waiting until I got everything written (which may be never) I thought I would post what I have and update as needed. Enjoy.

Note: All code presented here is intended to be run with Lua For Windows (L4W) and I strongly recommend that everyone take a moment to download it now (its free).

Introduction

Tables in Lua (known in other languages as associate arrays, maps, or hashes) are data structures used to store data as a series of key/value pairs. For example, you can consider an entry in the address book on your cell phone as a "table" where the fields (name, email, phone number etc.) are the keys. Given a table t the syntax to set/read a value in a table is:
Code:
-- store a value in the table 't'
t[key] = value
-- retrieve a value from the table 't'
value = t[key]
Any datatype can be used a key in a Lua table and a Lua table can hold any datatype. So it is possible to have tables of tables. For example, each entry in your address book is a table and the address book itself is a table where the "key" is a name and the "value" is an entry table.

Tables as Arrays

An "array" is data structure that consists of a consecutive series of memory locations (variables) that are indexed by an integer value (think row/cell number). Lua tables aren't arrays, but if you use numbers as the keys the table behaves like an array. Note that in Lua arrays start at index 1 (in most programming languages arrays start at index 0).
Code:
t[1] = "first element"
t[2] = "second element"
t[3] = "third element"

-- Print the array elements in order.
print(t[1])
print(t[2])
print(t[3])
Lua also supports a shorthand method for initializing the contents of an array in one statement. We could achieve the same as above with:
Code:
t = { "first element", "second element", "third element" }

-- is shorthand for
t = { [1] = "first element", [2] = "second element", [3] = "third element" }

-- which is shorthand for
t = {}
t[1] = "first element"
t[2] = "second element"
t[3] = "third element"
In the first two methods we put the "array initializers" (the values used to initialize the array) inside curly braces. You can use commas or semi-colons to separate the items in the list.

Inserting and Deleting Array Elements


Lua provides two functions table.insert and table.remove that can be used to insert and remove items from tables.
Code:
t = {} -- an empty table.
table.insert(t, "one") -- inserts at the end of the "array"
table.insert(t, "two")
table.insert(t, "three")
-- insert into the second slot, other values are shuffled back.
table.insert(t, 2, "one and a half")

-- remove third element
table.remove(t, 3)
Getting the Size of a Table

Use the '#' (size) operator to get the number of elements in a table that is being used as an array.
Code:
t = {"one", "two", "three"}
n = #t  -- n == 3
Note that this only works for tables used as arrays, it will not return the correct size if the table is used as a dictionary.
Code:
t = {"one", "two", "three"}
print(#t)   -- prints 3
t.one = 1
t.two = 2
t.three = 3
print(#t)    -- prints 3 again!
Tables as Dictionaries

When a table uses a string value as the key it is commonly referred to as a "Dictionary" (i.e. you use a word to look up a value). For example, we may use tables to keep track of statistics for each player in a match and we want to use meaningful names to keep track of what is in each field (slot):
Code:
player = {}
player["name"] = "Haywood Slap"
player["score"] = 0
player["kills"] = 0
player["deaths"] = 0

-- We can also use variables that contain strings for either 
-- the key or value:
key = "name"
value = "Haywood Slap"
player[key] = value

-- Lua also provides shortcuts for setting table values 
-- that use strings as the key.
player.name = "Haywood Slap"

-- is shorthand for
player["name"] = "Haywood Slap"

-- Lua also has a shorthand method that allows us to initialize all the
-- fields at one.  This is equivalent to the first method.
player = {
    name = "Haywood Slap",
    score = 0,
    kills = 0,
    points = 0
}
The above uses a similar approach we used when initializing a table as an array, that is we put the initializers in curly braces and separate the values with commas. We could write the above as follows and achieve exactly the same effect.
Code:
player = {
    ["name"] = "Haywood Slap",
    ["score"] = 0,
    ["kills"] = 0,
    ["points"] = 0
}
None of the methods of initializing a table are any more efficient that any of the others. The various methods of initializing a table are referred to as "syntactic sugar" (or syntactic candy) or just "sugar", and this is what is meant when the Lua documentation refers to "the sugar in Lua". The Lua compiler does some arm waving and lets us write the same thing using the notation we find most comfortable, but in all instances the compiler will generate exactly the same bytecode. It is sweet and it "tastes" good, but it doesn't really do anything.

Note
Take care when mixing the methods of setting table values:
Code:
player.1 = "One"

-- is equivalent to
player["1"] = "One"

-- it is NOT equivalent to
player[1] = "One"
The last assignment treats the player table as an array and inserts the string "One" into the first slot (field). The first two assignments use the string "1" as the key. I don't know where it will go in the table, but it won't be the first slot.

Iterating Over Tables

Very often you will have a table and you don't know they keys or how many elements are in the table. If the table is being used as an array you can use the size operator in a for loop to iterate over the array:
Code:
t = {"one", "two", "three"}
for i=1,#t do
    print(i, t[i])
end
--[[ prints
1    one
2    two 
3    three
]]
However Lua has two functions pairs and ipairs that can be used to iterate over all the fields in a table. Each time through a loop the pair functions return one of the key/value pairs from the table. Use the ipairs function if the table is an array (think of the i in ipairs as the i in the for loop); ipairs will iterate over all the values in the table in order.
Code:
t = {"one", "two", "three"}
for index,value in ipairs(t) do
    print(index, value)
end
--[[ prints
1    one
2    two 
3    three
]]
Use the pairs function for tables that are used as dictionaries or arrays (or a mix)
Code:
player = {
    name = "Haywood Slap",
    score = 0,
    kills = 0,
    points = 0
}
for key,value in pairs(player) do
    print(key, value)
end
-- [[ prints
points    0
kills    0
name    Haywood Slap
score    0
]]
Note that the pairs function does not return the elements in the table in any particular order.

Using Tables as Classes
To be written.

Conclusions

Tables are the only user datatype Lua supports but they are a very (very) powerful feature. If you need to keep track of lots of information in your mission you need tables. The Lua Users Wiki is a great source of information. This is basically a rehash of their Tables tutorial with a OFP slant.

I also can't recommend downloading and experimenting with L4W enough. I use L4W constantly to test fragments of code before plugging it into OFP. I can't imaging writing Lua code without it.
__________________
In theory there is no difference between theory and practice. But in practice there is.
Intro to LUA, Fun with tables, Undocumented Functions, Saving Game State
Timer library, Sector Control Framework
Finite State Machines (part 1)
Haywood Slap is offline   Reply With Quote
Old 02-11-2009, 10:25 PM   #2 (permalink)
Senior Member
 
Join Date: Oct 2009
Posts: 239
Default

Thanks for taking the time to post this, I think I'll be printing your post to read properly off-line. Much appreciated.
__________________
Code:
function onFinishedTyping(userName, messageName)
    talking_sh*te=OFP:isUserName("private_pile")
    if talking_sh*te==true then
    OFP:clickButton("submit", "OVERRIDE")
    end
end
private pile is offline   Reply With Quote
Old 02-11-2009, 10:49 PM   #3 (permalink)
Senior Member
 
Talisa1811's Avatar
 
Join Date: Nov 2005
Location: Small Dole, UK
Posts: 639
Default

I have downloaded this also and will be reading it as soon as I have finished my current mission.

Thanks
__________________
Talisa

If in doubt, C-4 !

My SkyDrive OFP-DR Files
http://cid-c59474ce7ff81dd7.skydrive...sing%20Related
Talisa1811 is offline   Reply With Quote
Old 03-11-2009, 07:04 AM   #4 (permalink)
Senior Member
 
Join Date: Oct 2009
Posts: 127
Default

I have linked this in the [INFO] LUA in OFPR thread. Thanks a lot for your effort!
gannebamm is offline   Reply With Quote
Old 03-11-2009, 08:48 AM   #5 (permalink)
Senior Member
 
Dru1d's Avatar
 
Join Date: Sep 2009
Posts: 224
Default

Nice post Haywood. I agree, tables are very powerful and reduce and simplify the amount of coding necessary along with providing soluitions to otherwise almost impossible tasks.

Insert and delete are particularly useful. I use them to keep a table of the player and multiplayer names in a fireteam, as occasionally I want triggers to activate on them and not some dumb AI who also happens to be a member of the same fireteam.
Dru1d is offline   Reply With Quote
Reply

Bookmarks

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



All times are GMT. The time now is 08:45 PM.


Powered by vBulletin®
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.