[solved] wml.get_child for unit

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

Moderator: Forum Moderators

User avatar
hermestrismi
Posts: 730
Joined: February 6th, 2016, 11:28 pm
Location: Tunisia
Contact:

[solved] wml.get_child for unit

Post by hermestrismi »

hi,
I am trying to iterate over the modifications of a unit to get a specific modifications (trait) but I got an error "except a lua or wml table but get unit".
how to fix that? and if someone can tell why is it wrong?

Code: Select all


			local u = wesnoth.units.find_on_map{ id = selected_unit_id_alpha }[1]
			for _, eff in ipairs(world_items_list) do
				if eff.world_item_id == item_id_to_give then
					-- added
					local modifications = u, "modifications")
					for i = 1,#modifications do
						if modifications[i][1] == "trait" then
							if modifications[i][2].id == "student" then
								print("unit: student")
							end
						end
					end
				end
Last edited by hermestrismi on August 27th, 2024, 6:39 am, edited 1 time in total.
white_haired_uncle
Posts: 1456
Joined: August 26th, 2018, 11:46 pm
Location: A country place, far outside the Wire

Re: wml.get_child for unit

Post by white_haired_uncle »

Well, there's something clearly wrong in what you've posted (pasted?):

Code: Select all

local modifications = u, "modifications")
But there's a working example starting here:

https://github.com/Dugy/Legend_of_the_I ... n.lua#L757


(Totally without testing it, I think you need to use u.__cfg, not the u you get from wesnoth.units.find_on_map() )
Speak softly, and carry Doombringer.
User avatar
hermestrismi
Posts: 730
Joined: February 6th, 2016, 11:28 pm
Location: Tunisia
Contact:

Re: wml.get_child for unit

Post by hermestrismi »

white_haired_uncle wrote: August 22nd, 2024, 1:52 am Well, there's something clearly wrong in what you've posted (pasted?):

Code: Select all

local modifications = u, "modifications")
yup, that was a typo. it is not like that in the original code.
But there's a working example starting here:

https://github.com/Dugy/Legend_of_the_I ... n.lua#L757


(Totally without testing it, I think you need to use u.__cfg, not the u you get from wesnoth.units.find_on_map() )
u.__cfg isn't supposed to get the data from the unit_type data?
white_haired_uncle
Posts: 1456
Joined: August 26th, 2018, 11:46 pm
Location: A country place, far outside the Wire

Re: wml.get_child for unit

Post by white_haired_uncle »

hermestrismi wrote: August 22nd, 2024, 4:17 am
white_haired_uncle wrote: August 22nd, 2024, 1:52 am
(Totally without testing it, I think you need to use u.__cfg, not the u you get from wesnoth.units.find_on_map() )
u.__cfg isn't supposed to get the data from the unit_type data?
I'll probably screw this up, but...

u.__cfg (where u is a unit) is a table that contains all(?) of the data about a unit, including things you can't access using tools that work on units, but stored in a table. I'm not sure if it's a perfect match, but much like in WML where you store a unit.

And this is what the error message was trying to tell you. You're passing it a unit, but it expects a table.
Speak softly, and carry Doombringer.
User avatar
hermestrismi
Posts: 730
Joined: February 6th, 2016, 11:28 pm
Location: Tunisia
Contact:

Re: wml.get_child for unit

Post by hermestrismi »

white_haired_uncle wrote: August 22nd, 2024, 6:34 am
hermestrismi wrote: August 22nd, 2024, 4:17 am
white_haired_uncle wrote: August 22nd, 2024, 1:52 am
(Totally without testing it, I think you need to use u.__cfg, not the u you get from wesnoth.units.find_on_map() )
u.__cfg isn't supposed to get the data from the unit_type data?
I'll probably screw this up, but...

u.__cfg (where u is a unit) is a table that contains all(?) of the data about a unit, including things you can't access using tools that work on units, but stored in a table. I'm not sure if it's a perfect match, but much like in WML where you store a unit.

And this is what the error message was trying to tell you. You're passing it a unit, but it expects a table.
got it. it works. you are totally alright
User avatar
Celtic_Minstrel
Developer
Posts: 2371
Joined: August 3rd, 2012, 11:26 pm
Location: Canada
Contact:

Re: wml.get_child for unit

Post by Celtic_Minstrel »

white_haired_uncle wrote: August 22nd, 2024, 6:34 am u.__cfg (where u is a unit) is a table that contains all(?) of the data about a unit, including things you can't access using tools that work on units, but stored in a table. I'm not sure if it's a perfect match, but much like in WML where you store a unit.
I believe it's everything except animations. Thus, there is no way to access the animations. And it is exactly the format of unit WML – the implementation of [store_unit] is literally just to dump it into a WML variable.
Author of The Black Cross of Aleron campaign and Default++ era.
Former maintainer of Steelhive.
white_haired_uncle
Posts: 1456
Joined: August 26th, 2018, 11:46 pm
Location: A country place, far outside the Wire

Re: wml.get_child for unit

Post by white_haired_uncle »

Celtic_Minstrel wrote: August 22nd, 2024, 12:47 pm
white_haired_uncle wrote: August 22nd, 2024, 6:34 am u.__cfg (where u is a unit) is a table that contains all(?) of the data about a unit, including things you can't access using tools that work on units, but stored in a table. I'm not sure if it's a perfect match, but much like in WML where you store a unit.
I believe it's everything except animations. Thus, there is no way to access the animations. And it is exactly the format of unit WML – the implementation of [store_unit] is literally just to dump it into a WML variable.
Any idea why not animations? Unless they came along after the fact and it's simply that no one added them into the serialization process(es), I would have to suspect there's something special about them?

BTW, .__cfg isn't really a table is it, but a metatable that returns a table (so serialization only happens on first access)?
Speak softly, and carry Doombringer.
User avatar
Celtic_Minstrel
Developer
Posts: 2371
Joined: August 3rd, 2012, 11:26 pm
Location: Canada
Contact:

Re: wml.get_child for unit

Post by Celtic_Minstrel »

white_haired_uncle wrote: August 22nd, 2024, 1:15 pm Any idea why not animations? Unless they came along after the fact and it's simply that no one added them into the serialization process(es), I would have to suspect there's something special about them?
I believe animations were deliberately omitted because they are extremely verbose.
white_haired_uncle wrote: August 22nd, 2024, 1:15 pm BTW, .__cfg isn't really a table is it, but a metatable that returns a table (so serialization only happens on first access)?
Nope. It'll serialize every time you access it.
Author of The Black Cross of Aleron campaign and Default++ era.
Former maintainer of Steelhive.
User avatar
hermestrismi
Posts: 730
Joined: February 6th, 2016, 11:28 pm
Location: Tunisia
Contact:

Re: wml.get_child for unit

Post by hermestrismi »

Celtic_Minstrel wrote: August 22nd, 2024, 12:47 pm
white_haired_uncle wrote: August 22nd, 2024, 6:34 am u.__cfg (where u is a unit) is a table that contains all(?) of the data about a unit, including things you can't access using tools that work on units, but stored in a table. I'm not sure if it's a perfect match, but much like in WML where you store a unit.
I believe it's everything except animations. Thus, there is no way to access the animations. And it is exactly the format of unit WML – the implementation of [store_unit] is literally just to dump it into a WML variable.
by the way, I tried before something like T.attack_anime { ... T.if { ...
it didn't work. Seems to me that the Lua engine (I am not sure what it is called ) interpret the wml.tag.if as it is a regular lua if. is that correct?
edit:
to clear the context, I was trying to create a general case of an attack animations for all units so I needed to check if the unit have an attack animations for its melee or ranged attacks then use that attack animation if it exists...
User avatar
Celtic_Minstrel
Developer
Posts: 2371
Joined: August 3rd, 2012, 11:26 pm
Location: Canada
Contact:

Re: wml.get_child for unit

Post by Celtic_Minstrel »

If you want to create an "if" tag in Lua (or any other tag that happens to be a Lua keyword), then you need to write it as T["if"].
Author of The Black Cross of Aleron campaign and Default++ era.
Former maintainer of Steelhive.
User avatar
hermestrismi
Posts: 730
Joined: February 6th, 2016, 11:28 pm
Location: Tunisia
Contact:

Re: wml.get_child for unit

Post by hermestrismi »

Celtic_Minstrel wrote: August 22nd, 2024, 1:59 pm If you want to create an "if" tag in Lua (or any other tag that happens to be a Lua keyword), then you need to write it as T["if"].
Whoops! I didn't know that 😳 😕 😅
white_haired_uncle
Posts: 1456
Joined: August 26th, 2018, 11:46 pm
Location: A country place, far outside the Wire

Re: wml.get_child for unit

Post by white_haired_uncle »

Celtic_Minstrel wrote: August 22nd, 2024, 1:40 pm
white_haired_uncle wrote: August 22nd, 2024, 1:15 pm BTW, .__cfg isn't really a table is it, but a metatable that returns a table (so serialization only happens on first access)?
Nope. It'll serialize every time you access it.
So does that mean any changes I make are "stored" immediately? I thought I had to "unstore" the unit (e.g to_map).

The more I think about this the less I think I understand it.

I've always thought of .__cfg as being akin to storing the unit. But in WML, I store a unit to a variable, which is then just a WML variable and I can do whatever I want with it (or not). And I suppose I could store it to multiple variables, each independent of the others. Short of doing a by-value copy, I don't think I can do this in lua (this is a rather silly example that can help me understand, not something I can see myself doing).

My immediate confusion likes with "It'll serialize every time you access it". Seems like that would mean if I made a change the next time I accessed .__cfg my change would be overwritten by the serialized data from the unit. Unless behind the scenes there are actually two copies of the unit, the "real" one and the ".__cfg" one and I'm getting a serialized version of the latter. Then "unstoring" would be syncing the real one from the "working copy".

I know I'm not explaining this well. I am confused.
Speak softly, and carry Doombringer.
User avatar
Ravana
Forum Moderator
Posts: 3313
Joined: January 29th, 2012, 12:49 am
Location: Estonia
Contact:

Re: wml.get_child for unit

Post by Ravana »

It means if you call .__cfg multiple times its linear time cost.
white_haired_uncle
Posts: 1456
Joined: August 26th, 2018, 11:46 pm
Location: A country place, far outside the Wire

Re: wml.get_child for unit

Post by white_haired_uncle »

Are you saying there is a difference in serialization cost between:

Code: Select all

local unit = wesnoth.units.find_on_map(cfg)[1]
unit.__cfg.hitpoints=23
unit.__cfg.language_name=_"Uncle Bob"
unit.__cfg.experience=100
and

Code: Select all

local unit = wesnoth.units.find_on_map(cfg)[1].__cfg
unit.hitpoints=23
unit.language_name=_"Uncle Bob"
unit.experience=100
Speak softly, and carry Doombringer.
User avatar
Ravana
Forum Moderator
Posts: 3313
Joined: January 29th, 2012, 12:49 am
Location: Estonia
Contact:

Re: wml.get_child for unit

Post by Ravana »

Yes. Different behaviour too if you wanted to do anything with the wml table.

Code: Select all

$ unit.__cfg == unit.__cfg
false
Post Reply