[solved] where I can use [lua] and it's return value, what I can do in modify_unit

The place to post your WML questions and answers.

Moderator: Forum Moderators

Forum rules
  • Please use [code] BBCode tags in your posts for embedding WML snippets.
  • To keep your code readable so that others can easily help you, make sure to indent it following our conventions.
Post Reply
white_haired_uncle
Posts: 1231
Joined: August 26th, 2018, 11:46 pm
Location: A country place, far outside the Wire

[solved] where I can use [lua] and it's return value, what I can do in modify_unit

Post by white_haired_uncle »

This is similar to another thread where I was pointed to [insert_tag], which may be an alternative here, but I'd like to understand some things. I want to create an object in lua and feed that to [modify_unit]. I can create an object, and I can use [modify_unit] to add an object to a unit, but I can't seem to glue them together.

There's probably multiple things wrong here, but I've reduced it as simply as I can.

Here's what I'm trying:

Code: Select all

    [event]
        name=prerecruit
        id=fire wraith
        first_time_only=no
        [filter]
            side=3
            type=Fire Wraith
        [/filter]
            [lua]
                code=<<
                local unit = wml.variables["unit"]
                local tmp = loti.item.type[1] -- ensure list is loaded
                local craftables = {}
                for i,item in pairs(loti.item.type) do
                    if item.sort == "weaponword" then 
                        table.insert(craftables,i)
                    end
                end
                local index = mathx.random(#craftables)
                local item = loti.item.type[craftables[index]]
                wesnoth.interface.add_chat_message(string.format("Outside modify_unit:  %s will hold %s",unit.id,item.name))
                print(wml.tostring({wml.tag.object(item)}))
                gui.show_lua_console()
                --return  {wml.tag.object(item)}
            >>
            [/lua]
        [modify_unit]
            [filter]
                id=$unit.id
            [/filter]

            [lua]
                code=<<
                local unit = wml.variables["unit"]
                local tmp = loti.item.type[1] -- ensure list is loaded
                local craftables = {}
                for i,item in pairs(loti.item.type) do
                    if item.sort == "weaponword" then 
                        table.insert(craftables,i)
                    end
                end
                local index = mathx.random(#craftables)
                local item = loti.item.type[craftables[index]]
                wesnoth.interface.add_chat_message(string.format("%s will hold %s",unit.id,item.name))
                print(wml.tostring({wml.tag.object(item)}))
                gui.show_lua_console()

                return  {wml.tag.object(item)}
            >>
            [/lua]
        [/modify_unit]
    [/event]
I can see that the [lua] creates the object that I want, or at least something very close. But when I run the above, I get only one chat/print (from outside the [modify_unit] as shown below), and my unit has no [object].

I've noticed that it seems I can't do much inside [modify_unit]. For example, I have tried an failed to print/save the value of $this_unit in various ways, but whatever I try seems to be silently ignored. Can I use [lua] there? Is there a list of places where [lua] is acceptable? Is there a list of what I can/can't do inside [modify_unit] (I suppose "anything it doesn't say explicitly")?

I'm not convinced using 'return [object] ... [/object]' is valid. I'd hope so. I know I can do something like [if] [lua] return true|false[/lua] [/if]

I realize that because I'm using random I won't necessarily get the same object from the two [lua] blocks, but I believe this shows that the block returns roughly the data I want it to. Nothing follow this:

Code: Select all

20240420 11:48:18 info scripting/lua: Script says: "Outside modify_unit:  Fire Wraith-9524 will hold Gloombringer"
20240420 11:48:18 debug scripting/lua: intf_print called:
20240420 11:48:18 debug scripting/lua: '[object]
	amethysts=1
	attacks=30
	black_pearls=0
	damage=20
	description="<span color='green'>Damage increased by 20%</span>
<span color='green'>30% more attacks </span>
<span color='#60A0FF'>Resistance to pierce increased by 10%</span>
<span color='#C0C000'>New weapon special: poison</span>
<span color='#60A0FF'>Chance to get hit decreased by 10%</span>
<span color='#808080'><i>One side wins, the other side loses. Both sides' widows weep.</i></span>"
	diamonds=0
	dodge=10
	emeralds=4
#textdomain wesnoth-loti
	flavour=_"One side wins, the other side loses. Both sides' widows weep."
	image="items/leather-pack.png"
	name=_"Gloombringer"
	number=583
	obsidians=2
	opals=0
	pearls=0
	pierce_resist=10
	rubies=1
	sapphires=0
	sort="weaponword"
	topazes=1
	[specials]
		[poison]
#textdomain wesnoth-help
			description=_"This attack poisons living targets. Poisoned units lose 8 HP every turn until they are cured or are reduced to 1 HP. Poison cannot, of itself, kill a unit."
			id="poison"
			name=_"poison"
			special_note=_"The victims of this unit’s poison will continually take damage until they can be cured in town or by a unit which cures."
		[/poison]
	[/specials]
[/object]
'
Last edited by white_haired_uncle on April 21st, 2024, 3:12 pm, edited 1 time in total.
Speak softly, and carry Doombringer.
white_haired_uncle
Posts: 1231
Joined: August 26th, 2018, 11:46 pm
Location: A country place, far outside the Wire

Re: where I can use [lua] and it's return value, what I can do in modify_unit

Post by white_haired_uncle »

P.S. while I'd still like to understand the above, keeping the [lua] outside [modify_unit], passing the return through a wml variable, and using [insert_tag] does work.

Code: Select all

... 
               wml.variables["my_item"] = item
            >>
            [/lua]
        [modify_unit]
            [filter]
                id=$unit.id
            [/filter]
        [insert_tag]
            name=object
            variable=my_item
        [/insert_tag]
[/modify_unit]
Speak softly, and carry Doombringer.
gnombat
Posts: 710
Joined: June 10th, 2010, 8:49 pm

Re: where I can use [lua] and it's return value, what I can do in modify_unit

Post by gnombat »

white_haired_uncle wrote: April 20th, 2024, 5:24 pm I've noticed that it seems I can't do much inside [modify_unit]. For example, I have tried an failed to print/save the value of $this_unit in various ways, but whatever I try seems to be silently ignored. Can I use [lua] there? Is there a list of places where [lua] is acceptable? Is there a list of what I can/can't do inside [modify_unit] (I suppose "anything it doesn't say explicitly")?
I don't think your example makes sense because [lua] is ActionWML, so it is supposed to be used in locations where ActionWML is allowed.

Of course, [modify_unit] is also ActionWML, but it can't contain ActionWML. It can contain only the child tags described in its documentation (which is pretty complex, but I don't think it allows [lua]).
white_haired_uncle wrote: April 20th, 2024, 5:24 pm I know I can do something like [if] [lua] return true|false[/lua] [/if]
That one is kind of a special case because [lua] is also allowed as ConditionalWML (as described in the LuaWML documentation).
User avatar
Ravana
Forum Moderator
Posts: 3024
Joined: January 29th, 2012, 12:49 am
Location: Estonia
Contact:

Re: where I can use [lua] and it's return value, what I can do in modify_unit

Post by Ravana »

[lua] as actionWML is wesnoth.wml_actions.lua, while [lua] in [if] is wesnoth.wml_conditionals.lua. From wml point of view both are [lua], but behaviour is different. There are similar examples for example [object] as actionWML is different from [object] in tags such as [modify_unit].
User avatar
Celtic_Minstrel
Developer
Posts: 2249
Joined: August 3rd, 2012, 11:26 pm
Location: Canada
Contact:

Re: where I can use [lua] and it's return value, what I can do in modify_unit

Post by Celtic_Minstrel »

white_haired_uncle wrote: April 20th, 2024, 5:24 pmI've noticed that it seems I can't do much inside [modify_unit]. For example, I have tried an failed to print/save the value of $this_unit in various ways, but whatever I try seems to be silently ignored.
I don't think there's any way to debug the value of $this_unit in [modify_unit]. You could use debug_print in [modify_unit][filter] but that debugs the variable in the filter, not the unit being modified. (They have the same name but are technically different variables.)
white_haired_uncle wrote: April 20th, 2024, 5:24 pmCan I use [lua] there?
No. [lua] is not supported in [modify_unit].
white_haired_uncle wrote: April 20th, 2024, 5:24 pmIs there a list of places where [lua] is acceptable?
The LuaWML page documents them near the top – [event], other places taking ActionWML (which off the top of my head only adds [command]), [era], [modification], [campaign], and [resource]. ([campaign] was missing until just now, but I've added it.) It also mentions it can be used as ConditionalWML, which means it's valid in such places as [if], [while], [show_if], and [filter_condition]. Though it's not mentioned anywhere (intentionally), it's also valid as a toplevel tag.
white_haired_uncle wrote: April 20th, 2024, 5:24 pmIs there a list of what I can/can't do inside [modify_unit] (I suppose "anything it doesn't say explicitly")?
Correct. Anything not explicitly mentioned as valid in [modify_unit] is not valid in [modify_unit]. In other words, the only things allowed are [filter], [object], [advancement], [trait], [effect], [set_variable], [clear_variable], and most of the stuff listed in SingleUnitWML (but not the creation options).
white_haired_uncle wrote: April 20th, 2024, 5:24 pmI'm not convinced using 'return [object] ... [/object]' is valid. I'd hope so. I know I can do something like [if] [lua] return true|false[/lua] [/if]
It really depends on what you mean by valid, but… it won't do what you want. You can return literally anything you want from a [lua] tag, but only the ConditionalWML version of [lua] does anything with the return value. So whatever you return, it'll just be ignored. But it is valid in the sense that it won't give an error message.

Perhaps an option to do something with the return value of a non-conditional [lua] is worthwhile. It does not exist at this time however.
white_haired_uncle wrote: April 20th, 2024, 5:24 pm This is similar to another thread where I was pointed to [insert_tag], which may be an alternative here, but I'd like to understand some things. I want to create an object in lua and feed that to [modify_unit]. I can create an object, and I can use [modify_unit] to add an object to a unit, but I can't seem to glue them together.
You should do either what you said in your second post (use a WML variable to pass the object through) or what Ravana described (add the modification from Lua).
Author of The Black Cross of Aleron campaign and Default++ era.
Former maintainer of Steelhive.
white_haired_uncle
Posts: 1231
Joined: August 26th, 2018, 11:46 pm
Location: A country place, far outside the Wire

Re: where I can use [lua] and it's return value, what I can do in modify_unit

Post by white_haired_uncle »

Thank you. That clears up most, probably all of my confusion. For now, at least.
Celtic_Minstrel wrote: April 21st, 2024, 2:36 pm Perhaps an option to do something with the return value of a non-conditional [lua] is worthwhile. It does not exist at this time however.
It seems quite logical to me. If a [lua] block returns a valid WML tag, I would expect that to have the same result as if I had typed in said tag at that location. Clearly, I'm wrong, but it's what I would expect.

I'm probably(?) biased by my hatred of global variables. Every time I have to set a variable I have to worry that someone, somewhere, might have set that variable with the expectation that I won't come along and just happen to use it for myself. A collision like that is probably quite rare, unless you're me. If I have to pass a value, I'd much rather do it via return.

Thanks again.
Speak softly, and carry Doombringer.
User avatar
Celtic_Minstrel
Developer
Posts: 2249
Joined: August 3rd, 2012, 11:26 pm
Location: Canada
Contact:

Re: where I can use [lua] and it's return value, what I can do in modify_unit

Post by Celtic_Minstrel »

white_haired_uncle wrote: April 21st, 2024, 3:12 pm It seems quite logical to me. If a [lua] block returns a valid WML tag, I would expect that to have the same result as if I had typed in said tag at that location. Clearly, I'm wrong, but it's what I would expect.
I'm not sure how viable that interpretation is. It would be equivalent to allowing [lua] inside [insert_tag] (and, if implemented, would probably be done that way rather than the way you assumed), which implies executing Lua code during variable interpolation (ie wml.interpolate can call arbitrary code), and I'm not sure if allowing that would create issues.
Author of The Black Cross of Aleron campaign and Default++ era.
Former maintainer of Steelhive.
white_haired_uncle
Posts: 1231
Joined: August 26th, 2018, 11:46 pm
Location: A country place, far outside the Wire

Re: [solved] where I can use [lua] and it's return value, what I can do in modify_unit

Post by white_haired_uncle »

So it looks like you can't do this either, which is unfortunate as I have multiple objects I'd like to insert.

Code: Select all

#ifdef NONONO 
        [modify_unit] 
            [filter] 
                id=$unit.id 
            [/filter] 
            [foreach] 
                array=my_items 
                [do] 
                    [insert_tag] 
                        name=object 
                        variable=this_item 
                    [/insert_tag] 
                [/do] 
            [/foreach] 
        [/modify_unit] 
#endif 
Had to move the [modify_unit] inside the [foreach] of course.

Actually, I wonder if I was really careful crafting my array maybe I could get away with just one [modify_unit]:

Code: Select all

        [modify_unit] 
            [filter] 
                id=$unit.id 
            [/filter] 
            [insert_tag] 
                name=insert_tag
                variable=surely_youre_not_serious
...
I don't think I'll try that.
Speak softly, and carry Doombringer.
User avatar
Celtic_Minstrel
Developer
Posts: 2249
Joined: August 3rd, 2012, 11:26 pm
Location: Canada
Contact:

Re: [solved] where I can use [lua] and it's return value, what I can do in modify_unit

Post by Celtic_Minstrel »

white_haired_uncle wrote: April 22nd, 2024, 5:00 am So it looks like you can't do this either, which is unfortunate as I have multiple objects I'd like to insert.
Why would you need to? You can dump multiple objects into [modify_unit anyway, so just put the [insert_tag] directly in there (like in your second example, but with name=object).

That makes me wonder whether nested insert_tag will actually work…
Author of The Black Cross of Aleron campaign and Default++ era.
Former maintainer of Steelhive.
white_haired_uncle
Posts: 1231
Joined: August 26th, 2018, 11:46 pm
Location: A country place, far outside the Wire

Re: [solved] where I can use [lua] and it's return value, what I can do in modify_unit

Post by white_haired_uncle »

Celtic_Minstrel wrote: April 22nd, 2024, 12:59 pm
white_haired_uncle wrote: April 22nd, 2024, 5:00 am So it looks like you can't do this either, which is unfortunate as I have multiple objects I'd like to insert.
Why would you need to? You can dump multiple objects into [modify_unit anyway, so just put the [insert_tag] directly in there (like in your second example, but with name=object).
Using [insert_tag] would be straightforward for any fixed number of objects. But I have an array of items (in this case, one for every weapon the unit has for which a corresponding item of that type exists) which is not of fixed length. Maybe there's a simple answer, I'm just not seeing it.

Hence the nested [insert_tag] idea (though I hesitate to even call it an "idea"). The upper [insert_tag] (fixed length=1) goes in [modify_unit], and its contents are a variable length list(array) of [insert_tag]s which contain the actual objects.

Even if it worked, I hope I'd never actually do it. Better to be slightly less efficient and use something much easier to read.
Speak softly, and carry Doombringer.
white_haired_uncle
Posts: 1231
Joined: August 26th, 2018, 11:46 pm
Location: A country place, far outside the Wire

Re: [solved] where I can use [lua] and it's return value, what I can do in modify_unit

Post by white_haired_uncle »

Brilliant. Thanks.
Speak softly, and carry Doombringer.
Post Reply