Lua newbie custom tag query

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

Moderator: Forum Moderators

Post Reply
User avatar
Spannerbag
Posts: 86
Joined: December 18th, 2016, 6:14 pm

Lua newbie custom tag query

Post by Spannerbag »

Hi,

I'm trying to learn some basic lua by creating a custom tag but am finding clear information regarding very basic language elements difficult to find (but then my google-fu is terrible) and after perusing the web I now have more questions than ever, hence this post.

Lua syntax
  • Can someone please clarify the difference (if any) between assigning var ::== something vs. var = something as the manual seems to swap between them without explanantion (to be fair I have not read the entire manual as it's huge).
  • How do you structure conditional logic? Again, I found the documentation regarding or and () consufing.
    Is if ((var == value1) or (var == value2)) a valid syntax?

... OK, on to my problem ...


What I am trying to do
Define a custom WML tag, mainly to learn lua basics but also to slightly reduce bloat as I presently use this logic a lot as a macro.

This tag, arbitrarily called [set_gold], is the same as [gold] except it has another optional key: set.

If set is absent or false then [set_gold] should behave identically to [gold] - ideally I would like to call [gold] from my lua code rather than replicate [gold]'s logic, but have not got that far yet.

If set is true (specifically at present ==true or ==yes but will eventually test for is_false rather than not_true maybe)
then the value of the amount key is the minimum gold the side(s) specified can have.

Whenever I run the script I get the on screen error:

Code: Select all

<Lua error>   [string " function wesnoth.wml_actions.set_gold(cfg)..."]:4: variable 'yes' must be assigned before being used
stack traceback:
	[C]: in function '.error'
	lua/ilua.lua:131: in metamethod '__index'
	[string " function wesnoth.wml_actions.set_gold(cfg)..."]:4: in local 'cmd'
	lua/wml-utils.lua:145: in field 'handle_event_commands'
	lua/wml-flow.lua:6: in function <lua/wml-flow.lua:5>
I have embedded the actual code in the scenario for now rater than using [load_resource] in [campaign].
I asume the :4: in [string " function wesnoth.wml_actions.set_gold(cfg)..."]:4: variable 'yes' must be assigned before being used refers to a line number?

Here's (one version of) the actual lua in the scenario with the WML below (I have used nested if... thens... to try and avoid conditional syntax errors):

Code: Select all

  [lua]
    code = << function wesnoth.wml_actions.set_gold(cfg)
    local set_amount = tonumber(cfg.amount) or wml.error "[set_gold] missing required amount= attribute."
    local action_set = 0			-- Should include set omitted (=nil)
    if cfg.set == yes or cfg.set == true then action_set = 1 end
    for index, set_sides in ipairs(set_sides) do
      set_sides[index].gold = set_sides[index].gold + set_amount
      if action_set == 1 then			-- Avoid conditional statements for now while debugging
        if set_sides[index].gold < set_amount then set_sides[index].gold = set_amount end
      end
    end
    end >>
  [/lua]



# Turn 1
  [event]
    name=turn 1
{MSG ("-1- About to [set_gold] side=1, amount=33 set=no, so side 1 should have 133 gold on NORMAL")}
    [set_gold]
      side=1
      amount=33
    [/set_gold]
{MSG ("Done")}
  [/event]

Line 4 would seem to be if cfg.set == yes or cfg.set == true then action_set = 1 end so the equality test would seem to be the issue?


Weirdly (to me at least) if I change the equality test to:
if ((cfg.set == "yes") or (cfg.set == "true")) then action_set = 1 end or if (cfg.set == "yes" or cfg.set == "true") then action_set = 1 end
then the error is on line 5? (for index, set_sides in ipairs(set_sides) do)

Reverting back to if (cfg.set == yes or cfg.set == true) then action_set = 1 end or if ((cfg.set == yes) or (cfg.set == true)) then action_set = 1 end moves the error back to line 4, so quotes make a difference (so I guess the yes ain't working right).

I get the same error whether set is absent or present and =yes or =no.
I have spent a fair bit of time on this and would like to ask what I am doing wrong? (and there's probably more than one answer!) as I seem to be going round in circles...

Aside
Oh, and an exampe of how to code a numbered list in this forum using the list=a ... /list format would help as I can do "a" but not "b"...



Note: posted regarding this some time ago on development-ideas.

Any thoughts/comments greatly appreciated!

Cheers!
-- Spannerbag
UMC Campaign: After EI
I suspect the universe is simpler than we think and stranger than we can know.
User avatar
Pentarctagon
Project Manager
Posts: 4784
Joined: March 22nd, 2009, 10:50 pm
Location: Earth (occasionally)

Re: Lua newbie custom tag query

Post by Pentarctagon »

yes or no is allowed without quotes in WML as equivalent to true and false, but that is not the case in lua, where putting just yes or no without quotes means you're trying to use a variable that's named yes or no.
99 little bugs in the code, 99 little bugs
take one down, patch it around
-2,147,483,648 little bugs in the code
User avatar
Spannerbag
Posts: 86
Joined: December 18th, 2016, 6:14 pm

Re: Lua newbie custom tag query

Post by Spannerbag »

Pentarctagon wrote: May 24th, 2021, 2:30 pm yes or no is allowed without quotes in WML as equivalent to true and false, but that is not the case in lua, where putting just yes or no without quotes means you're trying to use a variable that's named yes or no.
Hi,

Thanks for the reply - I did try with and without (double) quotes and the error message didn't change except that the "4" became a "5"?
Spannerbag wrote: May 24th, 2021, 1:42 pm ...
Line 4 would seem to be if cfg.set == yes or cfg.set == true then action_set = 1 end so the equality test would seem to be the issue?


Weirdly (to me at least) if I change the equality test to:
if ((cfg.set == "yes") or (cfg.set == "true")) then action_set = 1 end or if (cfg.set == "yes" or cfg.set == "true") then action_set = 1 end
then the error is on line 5? (for index, set_sides in ipairs(set_sides) do)

Reverting back to if (cfg.set == yes or cfg.set == true) then action_set = 1 end or if ((cfg.set == yes) or (cfg.set == true)) then action_set = 1 end moves the error back to line 4, so quotes make a difference (so I guess the yes ain't working right).
...
I'd got as far as realising that part of the problem at least is with the "yes" but am stuck. Maybe I should try a different delimiter?

Again, thanks for taking the trouble to reply.

Cheers,
-- Spannerbag
UMC Campaign: After EI
I suspect the universe is simpler than we think and stranger than we can know.
User avatar
Pentarctagon
Project Manager
Posts: 4784
Joined: March 22nd, 2009, 10:50 pm
Location: Earth (occasionally)

Re: Lua newbie custom tag query

Post by Pentarctagon »

I don't understand what you mean by "delimiter", but using yes is simply incorrect because there is no variable by that name declared here and "yes" won't actually do anything because when going from WML -> lua it will get changed to true.
99 little bugs in the code, 99 little bugs
take one down, patch it around
-2,147,483,648 little bugs in the code
vghetto
Posts: 463
Joined: November 2nd, 2019, 5:12 pm

Re: Lua newbie custom tag query

Post by vghetto »

Here's a rule of thumb to avoid headaches.
In WML only use yes/no for bools, never true/false.
In Lua only use true/false for bools, never yes/no
They will auto-magically translate between the two languages.
If the key is missing in WML, then its value will be nil in lua.

You don't have to test cfg.variable against yes or true, only the true/false/nil test is needed.
So if (cfg.set == yes or cfg.set == true) then action_set = 1 end should be if (cfg.set == true) then action_set = 1 end

I'm looking at your original post and it said

Code: Select all

[gold]
    side=1
    amount=100
    set_amount=true
[/gold]

set_amount in WML should have been set_amount=yes instead.

I didn't test it, but didn't what I write in the other post do exactly what you asked for and what you're trying to do here?
Luther
Posts: 126
Joined: July 28th, 2007, 5:19 pm
Location: USA

Re: Lua newbie custom tag query

Post by Luther »

Spannerbag wrote: May 24th, 2021, 1:42 pm Lua syntax
  • Can someone please clarify the difference (if any) between assigning var ::== something vs. var = something as the manual seems to swap between them without explanantion (to be fair I have not read the entire manual as it's huge).
::= is not Lua syntax. It's a notation for defining technical terms in Lua's grammar.
  • How do you structure conditional logic? Again, I found the documentation regarding or and () consufing.
    Is if ((var == value1) or (var == value2)) a valid syntax?
That's correct. or is an operator, similar to + or -. () is for grouping which operators to evaluate first.
If set is true (specifically at present ==true or ==yes but will eventually test for is_false rather than not_true maybe)
then the value of the amount key is the minimum gold the side(s) specified can have.
The WML strings "yes", "no", "true", and "false" get translated to Lua as booleans, which is its own data type whose values can be either true or false.

An if condition can be any expression. It usually doesn't make sense to compare two booleans, because that just gives you another boolean. Just use cfg.set by itself.
I asume the :4: in [string " function wesnoth.wml_actions.set_gold(cfg)..."]:4: variable 'yes' must be assigned before being used refers to a line number?
Yes.
Weirdly (to me at least) if I change the equality test to:
if ((cfg.set == "yes") or (cfg.set == "true")) then action_set = 1 end or if (cfg.set == "yes" or cfg.set == "true") then action_set = 1 end
then the error is on line 5? (for index, set_sides in ipairs(set_sides) do)
When an error happens, there's no way for Lua to continue executing to find more errors. Fixing one error reveals the next one.

In this case, you're using set_sides as both a looping variable and the array to iterate through. I don't see it defined anywhere before that loop.
User avatar
Elvish_Hunter
Forum Moderator
Posts: 1473
Joined: September 4th, 2009, 2:39 pm
Location: Lintanir Forest...

Re: Lua newbie custom tag query

Post by Elvish_Hunter »

Spannerbag wrote: May 24th, 2021, 1:42 pm Can someone please clarify the difference (if any) between assigning var ::== something vs. var = something as the manual seems to swap between them without explanantion (to be fair I have not read the entire manual as it's huge).
var = something is the assignment operator, whilst var == something is the equality test operator. This is one of the basics, not just with Lua but with every programming language, so I'd highly advise you to follow the Lua tutorials at http://lua-users.org/wiki/TutorialDirectory.
Spannerbag wrote: May 24th, 2021, 1:42 pm How do you structure conditional logic? Again, I found the documentation regarding or and () consufing.
Is if ((var == value1) or (var == value2)) a valid syntax?
It is valid, and you can even remove the outermost set of braces.
vghetto wrote: May 24th, 2021, 3:34 pm You don't have to test cfg.variable against yes or true, only the true/false/nil test is needed.
So if (cfg.set == yes or cfg.set == true) then action_set = 1 end should be if (cfg.set == true) then action_set = 1 end
That action_set variable is just confusing and useless; get rid of it and just use if cfg.set then.
In Lua, every value that isn't false or nil casts as true, so a missing or =no WML key won't pass this test; the downside is that the key will be true with any other value (not just with a WML =yes!), but this can be fixed later if you really want to.
Spannerbag wrote: May 24th, 2021, 3:10 pm I did try with and without (double) quotes and the error message didn't change except that the "4" became a "5"?
for index, set_sides in ipairs(set_sides) do: you never defined set_sides anywhere, and even if you did you're going to mask it in the for loop, so there are two bugs in a single line (well, the masking isn't a bug, but it's confusing, so avoid that).
Current maintainer of these add-ons:
1.14: The Sojournings of Grog, A Rough Life, The White Troll (co-author), Wesnoth Lua Pack
1.12: Children of Dragons
User avatar
Spannerbag
Posts: 86
Joined: December 18th, 2016, 6:14 pm

Re: Lua newbie custom tag query

Post by Spannerbag »

vghetto wrote: May 24th, 2021, 3:34 pm Here's a rule of thumb to avoid headaches...

You don't have to test cfg.variable against yes or true, only the true/false/nil test is needed...

I didn't test it, but didn't what I write in the other post do exactly what you asked for and what you're trying to do here?
Hi again,

Thanks for the reply, very helpful. Yes, your original post was very close and I used it as a starting point (and managed to move further away from where I wanted to get to...) because I wanted to learn how to do this stuff myself.
Had a lot of replies to my post so will keep this short, but thanks again for your help, much appreciated!

Cheers,
-- Spannerbag.
UMC Campaign: After EI
I suspect the universe is simpler than we think and stranger than we can know.
User avatar
Spannerbag
Posts: 86
Joined: December 18th, 2016, 6:14 pm

Re: Lua newbie custom tag query

Post by Spannerbag »

Luther wrote: May 24th, 2021, 3:58 pm
Spannerbag wrote: May 24th, 2021, 1:42 pm Lua syntax
...

I asume the :4: in [string " function wesnoth.wml_actions.set_gold(cfg)..."]:4: variable 'yes' must be assigned before being used refers to a line number?

...

In this case, you're using set_sides as both a looping variable and the array to iterate through. I don't see it defined anywhere before that loop.
Brilliant! That helped a lot! You've given me plenty to work on, thank you for taking the time and trouble to reply, really appreciated!

Cheers!
-- Spannerbag
UMC Campaign: After EI
I suspect the universe is simpler than we think and stranger than we can know.
User avatar
Spannerbag
Posts: 86
Joined: December 18th, 2016, 6:14 pm

Re: Lua newbie custom tag query

Post by Spannerbag »

Elvish_Hunter wrote: May 24th, 2021, 4:18 pm ... I'd highly advise you to follow the Lua tutorials at http://lua-users.org/wiki/TutorialDirectory.

... you never defined set_sides anywhere...
Ah, yet another helpful resource I somehow managed to miss!
Thanks, will have a look.

Also thanks for taking the time and trouble to reply, much appreciated!

Cheers!
-- Spannerbag
UMC Campaign: After EI
I suspect the universe is simpler than we think and stranger than we can know.
User avatar
Spannerbag
Posts: 86
Joined: December 18th, 2016, 6:14 pm

Re: Lua newbie custom tag query *working*

Post by Spannerbag »

Hi everyone,
It's finally working!
Many thanks to all who took the time and trouble to help me, it's really appreciated.

File lua/set_gold.lua is loaded in _main.cfg and in scenario 1 [set_gold] works.
I now (kinda) understand the basics of doing lua in Wesnoth.
Thanks again!

Cheers,
-- Spannerbag
UMC Campaign: After EI
I suspect the universe is simpler than we think and stranger than we can know.
User avatar
Celtic_Minstrel
Developer
Posts: 1816
Joined: August 3rd, 2012, 11:26 pm
Location: Canada
Contact:

Re: Lua newbie custom tag query

Post by Celtic_Minstrel »

I see your problem is solved, but one minor query never got an answer.
Spannerbag wrote: May 24th, 2021, 1:42 pm Aside
Oh, and an exampe of how to code a numbered list in this forum using the list=a ... /list format would help as I can do "a" but not "b"...
Here's an example of coding a list on this forum:

Code: Select all

[list=1]
[*]One
[*]Two
[*]Three
[/list]
That produces the following list:
  1. One
  2. Two
  3. Three
If you open it with [list] instead of [list=1], it'll give you a bulleted list; in all other respects, the code for a bulleted list is the same. There's no way that I know of to specify the starting number for the list, though. If you want to intersperse stuff between the list items, I'd suggest putting the between stuff inside the preceding list item.
Elvish_Hunter wrote: May 24th, 2021, 4:18 pm var = something is the assignment operator, whilst var == something is the equality test operator. This is one of the basics, not just with Lua but with every programming language,
Not every language. Some languages use = for equality and either don't have assignment (like WFL or SQL) or use := for assignment.
Author of The Black Cross of Aleron campaign and Default++ era.
Maintainer of Steelhive.
User avatar
Spannerbag
Posts: 86
Joined: December 18th, 2016, 6:14 pm

Re: Lua newbie custom tag query

Post by Spannerbag »

Aha!

Thanks for taking the trouble to clarify, much appreciated!
Celtic_Minstrel wrote: June 6th, 2021, 3:39 pm I see your problem is solved, but one minor query never got an answer.

Here's an example of coding a list on this forum:

Code: Select all

[list=1]
[*]One
[*]Two
[*]Three
[/list]
That produces the following list:
  1. One
  2. Two
  3. Three
If you open it with [list] instead of [list=1], it'll give you a bulleted list; in all other respects, the code for a bulleted list is the same. There's no way that I know of to specify the starting number for the list, though. If you want to intersperse stuff between the list items, I'd suggest putting the between stuff inside the preceding list item.
Cheers,
-- Spannerbag
UMC Campaign: After EI
I suspect the universe is simpler than we think and stranger than we can know.
Post Reply