enclave's Lua thread

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

Moderators: Forum Moderators, Developers

enclave's Lua thread

Postby enclave » March 26th, 2015, 8:35 pm

Hello everyone,
Im using wesnoth 1.10.7

I would really like to learn Lua, and it is not very easy, because it is poorly documented..
I have couple of questions to start with:

1) How do I add options (with all show_if, not, and, or) and commands into this message code using Lua:
Code: Select all
wesnoth.wml_actions.message {
image="units/human-loyalists/peasant.png",
speaker="narrator",
side_for="1",
caption="not a caption",
message="not a message at all"
}

by the way I think narrator was working without "" also.. maybe shouldn't have.. or maybe I never noticed difference.

2) The code in wesnoth.synchronize_choice example http://wiki.wesnoth.org/LuaWML:Misc#wesnoth.synchronize_choice
didnt work for me after I removed some fragments, Im trying to figure out why.
Code: Select all
[event]
  name = "start"
  [lua]
  code = <<
    wesnoth.set_variable("input1",nil)
    local result = wesnoth.synchronize_choice(
    function()
      local option1 = T.option { message = "No", T.command { T.set_variable { name = "input1", value = "No"}}}
      local option2 = T.option { message = "Yes", T.command { T.set_variable { name = "input1", value = "Yes"}}}
      wesnoth.fire(T.message{ message =  "Are you sure you want to play this game?", option1, option2})
      return { value = wesnoth.get_variable("input1") }
    end,
    function()
      return { value = math.random(30) }
    end)
    wesnoth.set_variable("input1",nil)
    wesnoth.message("Player 1 wants to play: " .. result.value)
  >>
  [/lua]
[/event]

Im trying to use it for prestart choice of options, it says something about input nil value.. works without errors if i remove "wesnoth.message("Player 1 wants to play: " .. result.value)" but doesnt give any options to me..

3) Need to use right-click options or be able to show players [message] when not your turn, like in age of high sorcery.
If anyone has ideas, please let me know how to do it. Otherwise I need to find it in 1000s of lines of EoHS code.

Thank you!
enclave
 
Posts: 533
Joined: December 15th, 2007, 8:52 am

Re: enclave's Lua thread

Postby gfgtdf » March 26th, 2015, 9:49 pm

enclave wrote:Hello everyone,
Im using wesnoth 1.10.7

I would really like to learn Lua, and it is not very easy, because it is poorly documented..
I have couple of questions to start with:

1) How do I add options (with all show_if, not, and, or) and commands into this message code using Lua:
Code: Select all
wesnoth.wml_actions.message {
image="units/human-loyalists/peasant.png",
speaker="narrator",
side_for="1",
caption="not a caption",
message="not a message at all"
}

by the way I think narrator was working without "" also.. maybe shouldn't have.. or maybe I never noticed difference.

you do teh same as in wml, assuming that you have T = helper.set_wml_tag_metatable {} somewhere it with code:
Code: Select all
[message]
  attribute1 = value1
  attribute2 = value2
  [option]
    attribute3 = value3
  [/option]
  [some_other_tag]
    attribute4 = value4
    [some_subtag]
    [/some_subtag]
  [/some_other_tag]
[/message]

becomes
Code: Select all
wesnoth.wml_actions.message {
  attribute1 = "value1",
  attribute2 = "value2",
  T.option {
    attribute3 = value3,
    T.some_subtag {
    }
  },
  T.some_other_tag {
    attribute4 = value4,
  }
}

enclave wrote:2) The code in wesnoth.synchronize_choice example http://wiki.wesnoth.org/LuaWML:Misc#wesnoth.synchronize_choice
didnt work for me after I removed some fragments, Im trying to figure out why.
Code: Select all
[event]
  name = "start"
  [lua]
  code = <<
    wesnoth.set_variable("input1",nil)
    local result = wesnoth.synchronize_choice(
    function()
      local option1 = T.option { message = "No", T.command { T.set_variable { name = "input1", value = "No"}}}
      local option2 = T.option { message = "Yes", T.command { T.set_variable { name = "input1", value = "Yes"}}}
      wesnoth.fire(T.message{ message =  "Are you sure you want to play this game?", option1, option2})
      return { value = wesnoth.get_variable("input1") }
    end,
    function()
      return { value = math.random(30) }
    end)
    wesnoth.set_variable("input1",nil)
    wesnoth.message("Player 1 wants to play: " .. result.value)
  >>
  [/lua]
[/event]

Im trying to use it for prestart choice of options, it says something about input nil value.. works without errors if i remove "wesnoth.message("Player 1 wants to play: " .. result.value)" but doesnt give any options to me..

The code you quoted is from a "version 1.13 and later" section, so it is unlikeley to work in 1.10.x. But actually you do not need a wesnoth.synconize_choice if you want to use [message][option]. The original code in the wiki uses wesnoth.synconize_choice becasue it wants to show messages with option to sides different that the currently playing side in mp which is not posible with normal [message].
Scenario with Robots SP scenario (1.11/1.12), allows you to build your units with components, PYR No preperation turn 1.12 mp-mod that allows you to select your units immideately after the game begins.
gfgtdf
Developer
 
Posts: 912
Joined: February 10th, 2013, 2:25 pm

Re: enclave's Lua thread

Postby enclave » March 26th, 2015, 10:49 pm

gfgtdf thank you very much for your quick reply!

I tried to use your code from (1) of my questions, worked flawlessly so far:

Code: Select all
[lua]
code = <<
wesnoth.wml_actions.message {
image="units/human-peasants/peasant.png",
speaker="narrator",
side_for="1",
caption="not a caption",
message="not a message at all",
T.option {
    message = "option1",
    T.command {
    }
  },
T.option {
    message = "option2",
    T.command {
    }
  },
}
>>
[/lua]


it gives exactly what i want, - some options. I have more understanding on the T.option thing now.. Is there any documentation on "T" anywhere? Why "T"?

Now I may be able to work from this code into my question (2) synchronize choice.. since originally shown in documentation didnt work. And it should have worked on 1.10.7 because I removed fragments intended for 1.13 use.. (at least I believe so, but i'm not experienced enough to say for 100% sure).

I need to try synchronized choice because the code written above works flawlessly in a local game, but as soon as I go on any type of multiplayer server, the game kicks me out back to lobby as soon as it starts. Message Options are not allowed in preload, prestart and start events.. My goal is to give host (or player1) options for starting game settings (starting gold, level of help, etc) as a prestart or start event. It may be not a problem to do it on turn 1 event.. I haven't tried yet, but I simply need to know if I can do it on prestart or not (maybe using synchronized choice can help, I need to try).

If you understand the lua well, could you please check the code of synchronized choice i wrote in question (2) for basic mistakes.. maybe something with T.option or wesnoth.fire or "nil" or anything else really basic? (and not even related to synchronize choice itself) I would really appreciate because for me it's not basic yet.. I may not see something what for you may be obvious mistake.

Thank you very much for looking into my problem again!
enclave
 
Posts: 533
Joined: December 15th, 2007, 8:52 am

Re: enclave's Lua thread

Postby gfgtdf » March 26th, 2015, 11:44 pm

enclave wrote:it gives exactly what i want, - some options. I have more understanding on the T.option thing now.. Is there any documentation on "T" anywhere? Why "T"?

most likeley becasue somehwere else is written "T = helper.set_wml_tag_metatable {}" see the documentation here http://wiki.wesnoth.org/LuaWML:Misc#hel ... _metatable

enclave wrote:I need to try synchronized choice because the code written above works flawlessly in a local game, but as soon as I go on any type of multiplayer server, the game kicks me out back to lobby as soon as it starts. Message Options are not allowed in preload, prestart and start events..

in 1.10.7 none of the functions that use mp sync work in prestart or start events. This includes [message][option], wesnoth.synchronize_choice, [unstore_unit] with advancements and [get_global_variable], using any of those in 1.10.7 in a prestart/start event in mp will end the game.

In 1.12/1.13 it is possible to use mp sync in start and prestart events but still it is reccomended not to use it in prestart events becasue it will casue the players who are not making the decision to wait with a black window. (because prestart events are fired 'before anything is shown on the screen at all').
Scenario with Robots SP scenario (1.11/1.12), allows you to build your units with components, PYR No preperation turn 1.12 mp-mod that allows you to select your units immideately after the game begins.
gfgtdf
Developer
 
Posts: 912
Joined: February 10th, 2013, 2:25 pm

Re: enclave's Lua thread

Postby iceiceice » March 27th, 2015, 12:45 am

enclave:

- If you look at the LuaWML page, who wrote it was I guess a fan of very short identifiers to save typing. So they suggested to make many of these "frequently useful" lua objects as single capital letters, like "W" = wesnoth action metatable, for simulating WML commands directly in lua, "H" the lua helper library, and also "T" this table constructor helper. If you can get used to this then use it by all means, if you get confused by the letters, just give them longer more descriptive names. Most code examples you'll see though probably use the letters, although I think I've seen "helper" instead of "H".

None of these things is strictly necessary, their source code is all written in lua and found in the data folder. The only fundamental thing is the "wesnoth" proxy table, which contains direct hooks into the engine. Anything that these things will be doing to affect the game state will ultimately boil down to some calls to "wesnoth.something".

- In 1.13, there is a lua console which lets you interact with the in-game lua through an interpreter. So you can type "wesnoth.get_unit({...})" and it will print interactively the result for you to look at. You can also use tab-completion here, so you can explore what functions and data are available, and what their children are etc. I think its a decent tool to play around with if you are trying to get used to how the game will interpret your lua code.

It is reachable from the "gamestate inspector" via the "lua console" button, or via a hotkey.
User avatar
iceiceice
Developer
 
Posts: 1056
Joined: August 23rd, 2013, 2:10 am

Re: enclave's Lua thread

Postby enclave » March 27th, 2015, 8:50 am

Huge thanks to you gfgtdf, I didn't know these things. I will put my options into turn 1 then or wherever else I can.. without much fuss around. I really wanted it on black screen, on preload, makes more sense for options.. while all other players could get message like "host is choosing settings" on same black screen.. I don't see problems with it, rather the opposite, but it doesn't matter too much.

thank you very much iceiceice for explanations on these T things and other stuff, will play around with it some day:)

Anyone knows how prestart options are organized in conquest- add-on? I tried to read it but it all seems overcomplicated to me, functions only lead to more functions there.. just like if it was all encrypted for my brain :)

PS. maybe the code with synchronized choice (2) gave me error because it was using math.random(30) there? somehwere in documentation it says it was disabled for being OOS magnet, and should use helper.rand instead.. ?
enclave
 
Posts: 533
Joined: December 15th, 2007, 8:52 am

Re: enclave's Lua thread

Postby enclave » March 27th, 2015, 9:33 am

I solved the problem below, please skip this post, please read next one first (this post will stay relevant to my next post)

Here we go, question #4 (4)

I have written the code
Code: Select all
[lua]
code = <<
wesnoth.set_variable("testing_mode","false")
wesnoth.set_variable("turn1help","ON")
wesnoth.set_variable("showtop9","ON")
wesnoth.wml_actions.message {
image="portraits/humans/transparent/peasant.png",
speaker="narrator",
side_for="1",
caption="Choose Game Settings",
message="How much resources would you like each player to start with?",
T.option {
    message = "15",
    T.command {
wesnoth.set_variable("starting_food","15"),
wesnoth.set_variable("starting_wood","15"),
wesnoth.set_variable("starting_stone","15"),
wesnoth.set_variable("starting_gold","15")
    }
  },
T.option {
    message = "45",
    T.command {
wesnoth.set_variable("starting_food","45"),
wesnoth.set_variable("starting_wood","45"),
wesnoth.set_variable("starting_stone","45"),
wesnoth.set_variable("starting_gold","45")
    }
  },
T.option {
    message = "90",
    T.command {
wesnoth.set_variable("starting_food","90"),
wesnoth.set_variable("starting_wood","90"),
wesnoth.set_variable("starting_stone","90"),
wesnoth.set_variable("starting_gold","90")
    }
  },
T.option {
    message = "TEST MODE",
    T.command {
wesnoth.set_variable("testing_mode","true")
    }
  },
}
>>
[/lua]


And of course it does not do what I want it to do.. because it is quite WML(ish).. and I guess Lua should work different way?
Basically I need to give choice of options.. and if the choice was "15" to set variables with "15"... but what my code does, it performs all of the "wesnoth.set_variable" that are in my code.. or only the last one, I'm not too sure.. could it be so?

I guess I should put some locals like "input", give them values, and then only in the end use "wesnoth.set_variable"? Or what am I doing wrong? Sorry I guess it looks too stupid, my code.. but I'm still trying to figure out how to use this "mutant" WML-Lua language.. :) nice experience from the other hand..
enclave
 
Posts: 533
Joined: December 15th, 2007, 8:52 am

Re: enclave's Lua thread

Postby enclave » March 27th, 2015, 11:32 am

Regarding my question number (4) in my previous post..

Was the code below best way to solve my problem in a previous post?
Code: Select all
[lua]
code = <<
wesnoth.set_variable("turn1help","ON")
wesnoth.set_variable("showtop9","ON")
wesnoth.wml_actions.message {
image="portraits/humans/transparent/peasant.png",
speaker="narrator",
side_for="1",
caption="Choose Game Settings",
message="How much resources would you like each player to start with?",
T.option {
    message = "15",
    T.command {
T.set_variable { name = "input1", value="15" },
T.set_variable { name = "input2", value="15" },
T.set_variable { name = "input3", value="15" },
T.set_variable { name = "input4", value="15" },
T.set_variable { name = "input5", value="false" }
    }
  },
T.option {
    message = "45",
    T.command {
T.set_variable { name = "input1", value="45" },
T.set_variable { name = "input2", value="45" },
T.set_variable { name = "input3", value="45" },
T.set_variable { name = "input4", value="45" },
T.set_variable { name = "input5", value="false" }
    }
  },
T.option {
    message = "90",
    T.command {
T.set_variable { name = "input1", value="90" },
T.set_variable { name = "input2", value="90" },
T.set_variable { name = "input3", value="90" },
T.set_variable { name = "input4", value="90" },
T.set_variable { name = "input5", value="false" }
    }
  },
T.option {
    message = "TEST MODE",
    T.command {
T.set_variable { name = "input5", value="true" }
    }
  }
}
wesnoth.set_variable("starting_food",wesnoth.get_variable("input1"))
wesnoth.set_variable("starting_wood",wesnoth.get_variable("input2"))
wesnoth.set_variable("starting_stone",wesnoth.get_variable("input3"))
wesnoth.set_variable("starting_gold",wesnoth.get_variable("input4"))
wesnoth.set_variable("testing_mode",wesnoth.get_variable("input5"))
>>
[/lua]


Thank you all very much, all help is very much appreciated!

PS. regarding my question (2) synchronised choice.. In this case I did not need it.. why? Is it because there was no variables like wesnoth.game_config.version involved? I dont understand when and why choice of options would need synchronised choice.. and when doesnt... I just want to make sure it wont cause any OOS.. Is it if each player would have to chose different option? No I still completely don't understand :)
enclave
 
Posts: 533
Joined: December 15th, 2007, 8:52 am

Re: enclave's Lua thread

Postby Ravana » March 27th, 2015, 12:41 pm

It would be better solution to just use http://wiki.wesnoth.org/OptionWML so that other players do not need to wait.
User avatar
Ravana
Moderator
 
Posts: 1482
Joined: January 29th, 2012, 12:49 am
Location: Estonia

Re: enclave's Lua thread

Postby enclave » March 27th, 2015, 2:22 pm

Thank you very much Ravana, but as far as I understand checkbox is only working starting from 1.11

My question (4) was more like "how could I optimise my lua code to make it any shorter? Or have I already done it best/short way possible?"
enclave
 
Posts: 533
Joined: December 15th, 2007, 8:52 am

Re: enclave's Lua thread

Postby gfgtdf » March 27th, 2015, 7:06 pm

hm then why dont you use 1.12 ?
PS. regarding my question (2) synchronised choice.. In this case I did not need it.. why? Is it because there was no variables like wesnoth.game_config.version involved? I dont understand when and why choice of options would need synchronised choice.. and when doesnt... I just want to make sure it wont cause any OOS.. Is it if each player would have to chose different option?

[message][option] is has an automatic sync mechanism that works the same way as wesnoth.syncronized_choice (but with less configuration posibilities) if you put [message][option] in a wesnoth.syncronized_choice you will basicly use that sync mechanism twice, In 1.10 this causes OOS.

wesnoth 1.12 and later will notice that you use mp sync twice and simply ignore the second use of mp sync (that is [message][option]s sync meachnism if you put that inside a wesnoth.sync_choice).
In 1.13 wesnoth.sync_choice allows you to query multiple other players than the currently active player, which [message][option]s sync mechanism does not allow. The code from the wiki works around that 'drawback' by puting it insode a wesnoth.sync_hoice to that sync_hoices sync meanism is used instead of [mesage][options] sync mechanism.

There are some other non mp save functions most importantly wesnoith.show_dialog, they do not have a mp sync mechamism if you want to use them then in most cases you have to use wesnoth.sync_choice (in 1.10 and in 1.12)
Scenario with Robots SP scenario (1.11/1.12), allows you to build your units with components, PYR No preperation turn 1.12 mp-mod that allows you to select your units immideately after the game begins.
gfgtdf
Developer
 
Posts: 912
Joined: February 10th, 2013, 2:25 pm

Re: enclave's Lua thread

Postby enclave » March 27th, 2015, 7:51 pm

Thank you very much for information gfgtdf! Was very useful to know.

I still use 1.10 because I started my project there, I plan to change it to 1.12 soon, after I polish it a little bit more, so I could leave it with 1.10 in more or less complete state (while there are still a lot of players there).

For 1.12 I will have to change some things.. i noticed some picture pathes became different, i noticed that [ability] will have to work some other way.. and for some reason a random map generator also has different way of functioning (at the moment simply doesnt work the way i have it in my project).. So of course I will switch to 1.12, I already see a tendency of more players playing there in 1.12, so people started to switch.
Spoiler:
enclave
 
Posts: 533
Joined: December 15th, 2007, 8:52 am

Re: enclave's Lua thread

Postby Elvish_Hunter » March 28th, 2015, 11:45 am

enclave wrote:1) How do I add options (with all show_if, not, and, or) and commands into this message code using Lua:
There are two ways to do it. The one that you're currently using is called a metatable, and to use it you must first assign said metatable to the T variable:
Code: Select all
local T = helper.set_wml_tag_metatable()
In this case, it allows you to write shorter code, but there are two problems: first, it partially hides how WML tags are handled in Lua; second metatables are one of the most complex paradigms in Lua (they're used to implement object-oriented programming), so usually one learns them later, not in the beginning.
The second way to implement sub-tags require the use of WML tables. At the time, I had serious troubles understanding them, because the wiki explanation wasn't that good. Now, however, the situation is much clearer: a WML table is just a regular table, where the first element is the tag name, and the second element is another table containing all the key/value pairs. Should one member of this second table be another sub-tag, it must be implemented as a WML table again.
In your case the code becomes:
Code: Select all
wesnoth.wml_actions.message {
    image="units/human-loyalists/peasant.png",
    speaker="narrator",
    side_for="1",
    caption="not a caption",
    message="not a message at all",
    { "show_if",
        { "have_unit", {
            id = "Elyssa"
            }
        }
    }
}

enclave wrote:by the way I think narrator was working without "" also.. maybe shouldn't have.. or maybe I never noticed difference.
Tip: uninitialized variable are automatically handled by Lua as if they contained the nil value. This has the tendency to create obscure bugs, and for this reason in the upcoming 1.13 series we implemented a strict mode, where using not initialized variables throws an error. So, in your case the speaker key was handled in this way:
Code: Select all
speaker = nil

enclave wrote:maybe something with T.option or wesnoth.fire or "nil" or anything else really basic?
wesnoth.fire is here for two reasons: backwards compatibility (it was the only way to call a WML tag in 1.8 ) and WML variable substitution (which isn't performed by the usual wesnoth.wml_actions, unless you access a special field called .__parsed - but that's a more advanced topic).
Except from these two cases, you usually call WML tags directly from wesnoth.wml_actions.
iceiceice wrote:If you look at the LuaWML page, who wrote it was I guess a fan of very short identifiers to save typing.
Yep, that was silene's style.
iceiceice wrote:Most code examples you'll see though probably use the letters, although I think I've seen "helper" instead of "H".
For sure you'll find it in every piece of documentation that I write: I always preferred to write long variable names, because the short ones confuse me. So, if somewhere you find helper, tag, unit, location, index, key, value instead of H, T, u, loc, i, k, v, you can be pretty sure who the culprit was :P Although some other devs may have followed my example, as it's true that one types more, but one needs to type less comments as well (the variable name itself counts as a form of comment) and it's more likely to catch mistakes.
enclave wrote:Regarding my question number (4) in my previous post..
Here you pretty much ended up writing Lua as if it was WML. The best solution, in this case, is to avoid Lua, and instead use directly WML code.
Personally, I use Lua mainly to implement new WML tags, which is done by creating new functions in the wesnoth.wml_actions table, and said functions should accept a cfg argument. Inside the function, you'll be able to access the WML content of the tag by reading the cfg table.
Current maintainer of The Sojournings of Grog, Children of Dragons, A Rough Life and Wesnoth Lua Pack
Co-author of The White Troll
On Wesbreak until the 21th of December
User avatar
Elvish_Hunter
Developer
 
Posts: 1359
Joined: September 4th, 2009, 2:39 pm
Location: Lintanir Forest...

Re: enclave's Lua thread

Postby gfgtdf » March 28th, 2015, 1:28 pm

I really reccomend to use T.tagname when creating wml tables, i think the error in elvish's code
Code: Select all
wesnoth.wml_actions.message {
    image="units/human-loyalists/peasant.png",
    speaker="narrator",
    side_for="1",
    caption="not a caption",
    message="not a message at all",
    { "show_if", {
        { "have_unit", {
            id = "Elyssa"
            }
        }
    }
}


makes it clear why.
Scenario with Robots SP scenario (1.11/1.12), allows you to build your units with components, PYR No preperation turn 1.12 mp-mod that allows you to select your units immideately after the game begins.
gfgtdf
Developer
 
Posts: 912
Joined: February 10th, 2013, 2:25 pm

Re: enclave's Lua thread

Postby Elvish_Hunter » March 28th, 2015, 1:56 pm

gfgtdf wrote:I really reccomend to use T.tagname when creating wml tables, i think the error in elvish's code
In that case, I accidentally added one more bracket after the "show_if". That's the downside of handling WML tables directly: it's quite easy to do add, miss or misplace some brackets - even more when one isn't using an exitor with syntax highlighting (I typed it directly in the forum's editor...). :(
Anyway, I edited my code to remove the issue.
Current maintainer of The Sojournings of Grog, Children of Dragons, A Rough Life and Wesnoth Lua Pack
Co-author of The White Troll
On Wesbreak until the 21th of December
User avatar
Elvish_Hunter
Developer
 
Posts: 1359
Joined: September 4th, 2009, 2:39 pm
Location: Lintanir Forest...

Next

Return to Lua Labs

Who is online

Users browsing this forum: No registered users and 1 guest