Dugi's lua questions

Discussion of Lua and LuaWML support, development, and ideas.

Moderator: Forum Moderators

mattsc
Inactive Developer
Posts: 1217
Joined: October 13th, 2010, 6:14 pm

Re: Dugi's lua questions

Post by mattsc »

Dugi wrote:I still need a reply to the question how can I add something="somethingelse" into the third variable array foo in a variable. variable.foo[3].something="somethingelse" like in WML does not seem to work
That should work assuming that variable.foo[3] exists and is a table. If not, you could do something like this (assuming variable.foo exists and is a table)

Code: Select all

if (not variable.foo[3]) then variable.foo[3] = {} end
variable.foo[3].something = "somethingelse"
or, equivalently,

Code: Select all

variable.foo[3] = { something = "somethingelse"}
Just two of a number of different possibilities.
Edit2: Actually, "equivalently" is wrong. They are only equivalent when variable.foo[3] does not exist or is empty. The first code snippet adds something = "somethingelse" to the table, while the second means that that is the entire table, deleting whatever might have previously existed in variable.foo[3] before..

Edit: if you're going to work with tables etc. a lot, I recommend downloading the Wesnoth Lua Pack add-on and getting familiar with the debug_utils.dbms() function.
User avatar
Dugi
Posts: 4961
Joined: July 22nd, 2010, 10:29 am
Location: Carpathian Mountains
Contact:

Re: Dugi's lua questions

Post by Dugi »

Thanks a million, I'll try and see.

Still not working. I think that I am wrong somewhere. I exported the variable array into wml, and it created an array that looks like this:
Spoiler:
Then I wanted to add a tooltip using the code to the list_definition.
I tried this (also some other variations, that didn't seem to help):

Code: Select all

dialog.grid.row[2].column.grid.row.column.grid.row[2].listbox.tooltip = "blablabla"
But it is telling that 'attempt to index field 'grid' (a nil value)'.
What am I doing wrongly? Any ideas?
mattsc
Inactive Developer
Posts: 1217
Joined: October 13th, 2010, 6:14 pm

Re: Dugi's lua questions

Post by mattsc »

Dugi wrote:Then I wanted to add a tooltip using the code to the list_definition.
I tried this (also some other variations, that didn't seem to help):

Code: Select all
dialog.grid.row[2].column.grid.row.column.grid.row[2].listbox.tooltip = "blablabla"


But it is telling that 'attempt to index field 'grid' (a nil value)'.
What am I doing wrongly? Any ideas?
That error message means that the 'grid' field (one of the 3 grid fields) in that table doesn't exist yet (it has value 'nil'). So you need to create it (and potentially its subfields, depending on how you do it), for example by one of the methods in my earlier post.

If you use "debug_utils.dbms(dialog)" from the WLP, it should tell you the structure of the table and you can see where things need to be added. (I don't have time to go through the WML table you posted right now, sorry.)
Luther
Posts: 128
Joined: July 28th, 2007, 5:19 pm
Location: USA

Re: Dugi's lua questions

Post by Luther »

Dugi wrote: Then I wanted to add a tooltip using the code to the list_definition.
I tried this (also some other variations, that didn't seem to help):

Code: Select all

dialog.grid.row[2].column.grid.row.column.grid.row[2].listbox.tooltip = "blablabla"
But it is telling that 'attempt to index field 'grid' (a nil value)'.
What am I doing wrongly? Any ideas?
Unless you're referring directly to a WML variable, you can't use the same syntax to look into a WML table that you would use in WML. 'grid' is nil because multiple subtags can have the same name and are therefore indexed by number. Take the following example of a valid WML table:

Code: Select all

dialog = {
  -- Must be a string, number, boolean, or nil
  grid = 42,

  -- This is a subtag. Its index is 1.
  T.grid{
    -- Other attributes and subtags
  }
}
When you say 'dialog.grid', Lua always assumes you're referring to the attribute, not the tag. That's because Lua tables are much more freeform than WML objects. I think you would need special functions to access containers within WML tables. I'm currently working on some functions that do that in some modified Wesband code. I'm trying to keep them compatible with the existing Wesband code, but ideally they would correspond with the WML tags [set_variable] (for attributes), [set_variables] (for containers), and [clear_variable] (for deleting containers). I should be able to post some code in a few days.
User avatar
Dugi
Posts: 4961
Joined: July 22nd, 2010, 10:29 am
Location: Carpathian Mountains
Contact:

Re: Dugi's lua questions

Post by Dugi »

Unless you're referring directly to a WML variable, you can't use the same syntax to look into a WML table that you would use in WML.
I have learned it recently. Thanks to mattsc's hint about that debug thing. I think I can live also with the usual way it is done.

EDIT: I have a suspicion that wesnoth.set_dialog_canvas crashes the game. If I changed the canvas to a table I used to open the dialog before (therefore, I replaced it with the same thing), and it crashed, this was the Terminal output:

Code: Select all

20121207 19:58:47 error gui/event: Invalid scrollbar mode 'no' falling back to 'initial_auto'.
20121207 19:58:47 error gui/parse: Canvas: found a shape of an invalid type tooltip.
wesnoth-1.10: /build/buildd/wesnoth-1.10-1.10.4/src/gui/auxiliary/canvas.cpp:1493: void gui2::tcanvas::parse_cfg(const config&): Assertion `false' failed.
Aborted (core dumped)
EDIT #2: Got the GUI working as intended, but the scroll_label seems to change size any time the text changes, reshaping the whole window. Is there a way to fix its size?

EDIT #3: Why is it impossible to set callbacks to sliders?
User avatar
Dugi
Posts: 4961
Joined: July 22nd, 2010, 10:29 am
Location: Carpathian Mountains
Contact:

Re: Dugi's lua questions

Post by Dugi »

Sorry for replying to myself, but nobody would notice this otherwise.

New question. If I use a lua-based wml tag containing a GUI and retrieval from persistent varriables in a synchronised event, shall it cause OoS errors?
User avatar
Dugi
Posts: 4961
Joined: July 22nd, 2010, 10:29 am
Location: Carpathian Mountains
Contact:

Re: Dugi's lua questions

Post by Dugi »

Now seriously, could someone help me? I helped a lot of people with WML, so somebody could help me with lua till I learn it.

I am trying to store a unit type into a variable array, but this:

Code: Select all

local unit_type=wesnoth.unit_types["name of the desired unit"]
does not seem to work, although according to the wiki, it should be a variable array indexed by unit type ids. debug_utils.dbms tells that it contains only the unit's ID, nothing else, and it behaves like that. How can that thing in wml_tags.lua work, that is a mystery for me.

Any ideas how to store a unit type into a lua array?

This is what for example what wesnoth.unit_types["Necromancer"] contains:

Code: Select all

{
  id="Necromancer"
}
with a metatable that cannot be read normally.
Anonymissimus
Inactive Developer
Posts: 2461
Joined: August 15th, 2008, 8:46 pm
Location: Germany

Re: Dugi's lua questions

Post by Anonymissimus »

Dugi wrote:Now seriously, could someone help me? I helped a lot of people with WML, so somebody could help me with lua till I learn it.
There are pretty few people in the forums who can answer lua questions. Developing is hard, and you are very well able to answer questions yourself. Many of the wml questions are just asked because people are being lazy, and there are many people who know enough wml, have enough time and are nice to help.

try like this (untested):

Code: Select all

local unit_type=wesnoth.unit_types.Troll.__cfg)
You already know dbms; did you also discover what I still consider the best thing about wesnoth lua, namely the fact that you can test changed code within a second, without the need to go to the mainscreen and press F5 ? Especially useful for testing MP addons in networked multiplayer, when you don't need to disconnect from the server with the host.
Then you can do quick trial & error and learn fast.
projects (BfW 1.12):
A Simple Campaign: campaign draft for wml startersPlan Your Advancements: mp mod
The Earth's Gut: sp campaignSettlers of Wesnoth: mp scenarioWesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
User avatar
8680
Moderator Emeritus
Posts: 742
Joined: March 20th, 2011, 11:45 pm
Location: The past

Re: Dugi's lua questions

Post by 8680 »

The Lua representations of unit types, units, and other things are proxy tables — rather than all the engine’s data on the Necromancer unit type being copied to a Lua table when you access wesnoth.unit_types.Necromancer, a proxy table is returned, which retrieves each attribute from the engine when you request it:

Code: Select all

necro = wesnoth.unit_types.Necromancer -- necro is a proxy table.
necrohp = necro.hitpoints -- Retrieves the Necromancer’s hitpoints from the engine; necrohp is a normal number.
necrocfg = necro.__cfg    -- Retrieves all the data immediately; necrocfg is a normal table.
User avatar
Elvish_Hunter
Posts: 1576
Joined: September 4th, 2009, 2:39 pm
Location: Lintanir Forest...

Re: Dugi's lua questions

Post by Elvish_Hunter »

Dugi wrote:Now seriously, could someone help me? I helped a lot of people with WML, so somebody could help me with lua till I learn it.
Sorry for the delay in answering, but real life got in the way. After all, we don't refuse to answer because we are (meant as people with Lua knowledge, and in my case also as developer) so heartless and like to see new coders suffering :twisted: ; if we don't answer, usually it's simply because we don't have the time to do so. :wink:
Dugi wrote:

Code: Select all

dialog.grid.row[2].column.grid.row.column.grid.row[2].listbox.tooltip = "blablabla"
You can't access other arrays inside a WML array in this way; you need to use the helper.child_range() function. It becomes a bit more clear if you think how the Lua table structure will be:

Code: Select all

dialog = { { "grid", { "row", { "column", {}}, { "column" {}} } } }
If you see it in this way, you'll notice that WML table can't directly be accessed with its index, so we use the helper function.
About your tooltip and scroll_label issue: please note that GUI2/Lua almost certainly still contains some bugs, and if you find one of them you should at least inform mordante.
Dugi wrote:New question. If I use a lua-based wml tag containing a GUI and retrieval from persistent varriables in a synchronised event, shall it cause OoS errors?
Does the GUI ask the user to input values in some way? If yes, then also the answer is yes, and you must use wesnoth.synchronize_choice() to return a WML table containing the selected values and avoid OOS.
Dugi wrote:Any ideas how to store a unit type into a lua array?
Anonymissimus and 8680 pretty much answered to this; I want only to point two things:
1) the documentation of wesnoth.unit_types is at http://wiki.wesnoth.org/LuaWML:Units#wesnoth.unit_types . You can notice the __cfg field, but you can see it also in other functions (wesnoth.get_units, for example). What's its purpose? It returns a read_only WML table, containing all the same data that you can see in the inspect window. This means that, if you want to read a WML table inside of it, you'll have to use helper.child_range.
2) Lua does not have such thing as "array". Lua has tables, that are different from WML arrays as they can contain also unindexed values and functions. Example:

Code: Select all

local t = { "spam", "eggs", "bacon", 42 }
is a perfectly valid Lua table, but doesn't work as a WML array, because it will more or less become:

Code: Select all

[t]
    spam
[/t]
[t]
    eggs
[/t]
[t]
    bacon
[/t]
[t]
    42
[/t]
Current maintainer of these add-ons, all on 1.16:
The Sojournings of Grog, Children of Dragons, A Rough Life, Wesnoth Lua Pack, The White Troll (co-author)
User avatar
Dugi
Posts: 4961
Joined: July 22nd, 2010, 10:29 am
Location: Carpathian Mountains
Contact:

Re: Dugi's lua questions

Post by Dugi »

So, thank you Anonymissimus and 8680, thanks to you I should be able to continue with the thing I was doing.

@Elvish_Hunter I have learned the way to work with lua tables already, but you made it clearer to me anyway.
Who is mordante? Never seen a post from him.
How do I use wesnoth.synchronize_choice? According to wiki, it should wrap the GUI, will that cause that all variables created by its callbacks and post_show functions will be synchronised?
The following advice was also useful, thanks.

I would have written more, but my neck is too tired from a metal concert to keep my head in the position I need :D
User avatar
Dugi
Posts: 4961
Joined: July 22nd, 2010, 10:29 am
Location: Carpathian Mountains
Contact:

Re: Dugi's lua questions

Post by Dugi »

Another issue. When I create a unit, with some tables/variable arrays inside its [variables] (this works), I somehow cannot get these variables from there.

This is the table describing the unit (nothing strange with it; unimportant parts were removed):
Spoiler:
I am trying to make something read the ids of the tables named 'a', I mean those 10301, 112, 218, 305, etc, but even unit[4] is said to be nil.
User avatar
Elvish_Hunter
Posts: 1576
Joined: September 4th, 2009, 2:39 pm
Location: Lintanir Forest...

Re: Dugi's lua questions

Post by Elvish_Hunter »

Dugi wrote:Who is mordante? Never seen a post from him.
How do I use wesnoth.synchronize_choice? According to wiki, it should wrap the GUI, will that cause that all variables created by its callbacks and post_show functions will be synchronised?
mordante is our GUI expert. You can contact him on IRC, channel #wesnoth-dev.
Some examples on how to use wesnoth.sychronize_choice are available in the WLP, file gui_tags.lua. Here there is one that I made some time ago:

Code: Select all

	local function sync()
		local function item_postshow()
			-- here get all widget values
		end
	
		local return_value = wesnoth.show_dialog( item_dialog, item_preshow, item_postshow )
		
		return { return_value = return_value }
	end
	
	local return_table = wesnoth.synchronize_choice(sync)
	if return_table.return_value == 1 or return_table.return_value == -1 then
		wesnoth.set_variable ( cfg.variable or "item_picked", "yes" )
	else wesnoth.set_variable ( cfg.variable or "item_picked", "no" )
	end
Basically, only the postshow and show_dialog function need to be wrapped inside the sync function. Said function will be passed to synchronize_choice and must return a WML table.
Dugi wrote:When I create a unit, with some tables/variable arrays inside its [variables] (this works), I somehow cannot get these variables from there.
That's right, you can't. Only first level variables are proxied, this means that you can't directly access arrays inside [variables].
To do this, you can use again the .__cfg field. Let's assume that you already stored the unit with wesnoth.get_units(), and it's inside the u variable:

Code: Select all

local vars = helper.get_child( u.__cfg, "variables" )
Now vars contains the [variable] field, and you can retrieve your values with helper.child_range:

Code: Select all

for item in helper.child_range( vars, "a" ) do
Current maintainer of these add-ons, all on 1.16:
The Sojournings of Grog, Children of Dragons, A Rough Life, Wesnoth Lua Pack, The White Troll (co-author)
User avatar
Dugi
Posts: 4961
Joined: July 22nd, 2010, 10:29 am
Location: Carpathian Mountains
Contact:

Re: Dugi's lua questions

Post by Dugi »

Damn, I should have remembered that. Thanks a lot.

:(
It wasn't what I needed, it was not a metatable, it was a regular lua table.
User avatar
8680
Moderator Emeritus
Posts: 742
Joined: March 20th, 2011, 11:45 pm
Location: The past

Re: Dugi's lua questions

Post by 8680 »

I believe helper.get_child(u.__cfg, "variables") can be replaced by u.variables.__cfg, eliding the subtag search and minimizing the (slow) cfg dump.
Dugi wrote:It wasn't what I needed, it was not a metatable, it was a regular lua table.
What wasn’t what you needed, and why did you need a metatable?
Post Reply