advances_from

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

Moderator: Forum Moderators

Post Reply
User avatar
DranKof
Posts: 34
Joined: May 30th, 2013, 6:35 am
Location: Beijing, China

advances_from

Post by DranKof »

Hello, I have been searching for a couple days now for any clue if there's already existent code to do the following.

I would like to be able to get a value for what a unit advances from.

For example, I provide unit_type "Elvish Marksman" and it returns/stores in a variable or array: "Elvish Archer"

I think there might be a macro or something that already does this (because the in-game encyclopedia displays said information when you look up a unit) but I still haven't found it/any. Am I overlooking anything? Or would I have to accomplish this by scanning through every unit to check and see if it can be promoted into the unit in question?
User avatar
Dugi
Posts: 4961
Joined: July 22nd, 2010, 10:29 am
Location: Carpathian Mountains
Contact:

Re: advances_from

Post by Dugi »

There is no way to do that with WML.

However, lua has a feature named wesnoth.unit_types that is an array of all units loaded, so there might be a way to add it to wml. Maybe something like this:

Code: Select all

function wml_actions.get_advances_from(cfg)
	local var = cfg.variable or "advances_from"
	local type = cfg.type or helper.wml_error "[store_unit_type] missing required type= attribute."
	local list = {}
	for j,k in pairs(wesnoth.unit_types) do
		if string.find(k.advances_to,type) then
			table.insert(list,advances_to.id)
		end
	end
	local result = table.concat(list,",")
	wesnoth.set_variable(var, result )
end
I haven't tested it, but it should be contained in code of a [lua] tag in main, and then it should be usable like this:

Code: Select all

[get_advances_from]
  type=Elvish Marksman
  variable=advances_from #If you omit this, advances_from will be default
[/get_advances_from]
User avatar
DranKof
Posts: 34
Joined: May 30th, 2013, 6:35 am
Location: Beijing, China

Re: advances_from

Post by DranKof »

Dugi wrote:There is no way to do that with WML.

However, lua has a feature named wesnoth.unit_types that is an array of all units loaded, so there might be a way to add it to wml. Maybe something like this:

Code: Select all

function wml_actions.get_advances_from(cfg)
	local var = cfg.variable or "advances_from"
	local type = cfg.type or helper.wml_error "[store_unit_type] missing required type= attribute."
	local list = {}
	for j,k in pairs(wesnoth.unit_types) do
		if string.find(k.advances_to,type) then
			table.insert(list,advances_to.id)
		end
	end
	local result = table.concat(list,",")
	wesnoth.set_variable(var, result )
end
So, you just gave the next two or three weeks of my life new meaning: http://www.lua.org/manual/5.2/.

Since this doesn't seem to be a WML problem anymore and now a LUA project, I guess it doesn't need to be elaborated on in this forum, BUT...

My first step to make it semi-work was to put "wesnoth." in front of "wml_actions.get_advances_from"
But now it's telling me "[string '...']:7: bad argument #1 to 'find' (string expected, got nil)
So I'm guessing that means that "k.advances_to" is passing "string.find" a nil and not a string as it seems to require?

I will definitely be looking into lua a lot more in the future, thanks for the introduction.
User avatar
Dugi
Posts: 4961
Joined: July 22nd, 2010, 10:29 am
Location: Carpathian Mountains
Contact:

Re: advances_from

Post by Dugi »

It seems that the variable k contains something different than I expected. I'll investigate it tomorrow maybe. If you're in hurry, ask a moderator to move it to lua labs and maybe you'll get a reply from somebody more experienced with lua, like Elvish_Hunter, mattsc or Aralantalara.
User avatar
Elvish_Hunter
Posts: 1575
Joined: September 4th, 2009, 2:39 pm
Location: Lintanir Forest...

Re: advances_from

Post by Elvish_Hunter »

Moved to Lua Labs.
Dugi wrote:It seems that the variable k contains something different than I expected.
First of all, I'd suggest you to avoid using j and k as variable names, and instead using a line like this:

Code: Select all

   for unit_type,fields in pairs(wesnoth.unit_types) do
Why? Because when you'll review your own code in six months from now, it's guaranteed that you'll find yourself wondering what that j meant. :P Using long variable names means that you'll have to type more, but you'll also understand what you did back then. In fact, you'll end up writing auto-documented code.
That said, k (or in my version, fields) does not contain advances_to, but only the following fields: id, name, max_moves, max_experience, max_hitpoints, level, cost. If you want to read advances_to, you'll need to access the __cfg field:

Code: Select all

local unit_type_advances_to = fields.__cfg.advances_to
I have no idea how such tag will perform against a gigantic era like Ageless... :hmm:
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: advances_from

Post by Dugi »

Okay, tried to correct it (maybe it looks too ugly):

Code: Select all

function wesnoth.wml_actions.get_advances_from(cfg)
   local var = cfg.variable or "advances_from"
   local type = cfg.type or helper.wml_error "[store_unit_type] missing required type= attribute."
   local list = {}
   local type_code = wesnoth.unit_types[type].__cfg
   local level = type_code.level - 1
   for unit_type,fields in pairs(wesnoth.unit_types) do
      if fields.level = level then
        local fields_read = fields.__cfg
        if string.find(fields_read.advances_to,type) then
           table.insert(list,unit_type)
        end
     end
   end
   local result = table.concat(list,",")
   wesnoth.set_variable(var, result )
end
Because level can be read without the slow .__cfg trick, I tried to avoid doing it with all units whose level is not 1 level lower than the level of the original unit.
User avatar
DranKof
Posts: 34
Joined: May 30th, 2013, 6:35 am
Location: Beijing, China

Re: advances_from

Post by DranKof »

Elvish_Hunter wrote:That said, k (or in my version, fields) does not contain advances_to, but only the following fields: id, name, max_moves, max_experience, max_hitpoints, level, cost. If you want to read advances_to, you'll need to access the __cfg field:
Where would I go to find out what data j, k, or fields (for instance) hold? I've found really comprehensive information about WML in the wiki but I can't even find a sticky about Wesnoth's LUA references to help me connect the language to Wesnoth a little better? [/me crosses fingers that he didn't miss an extremely obvious sticky or similar resource.]
Elvish_Hunter wrote:

Code: Select all

local unit_type_advances_to = fields.__cfg.advances_to
I have no idea how such tag will perform against a gigantic era like Ageless... :hmm:
Yeah, I was consider using said code for a MP Mod to demote default leaders at the start of the game but I am concerned that I might incidentally have to limit the mods it's "designed for" due to such concerns.

---

To all parties involved, wow, thanks. I can't wait till I have real time to take a look at these, thanks again, everyone, wish I didn't get home at midnight every night.
User avatar
DranKof
Posts: 34
Joined: May 30th, 2013, 6:35 am
Location: Beijing, China

Re: advances_from

Post by DranKof »

Dugi wrote:Okay, tried to correct it (maybe it looks too ugly):
Spoiler:
Finally got a chance to test it. The code works great :mrgreen: save a "=" / "==" situation, adjusted in the spoilered code above.
I will test this more with other eras in the future, hooray!
User avatar
Dugi
Posts: 4961
Joined: July 22nd, 2010, 10:29 am
Location: Carpathian Mountains
Contact:

Re: advances_from

Post by Dugi »

By the way, how many times do you use it? Because in the case if the tag was used ten times in a row in an event run several times in each scenario, there might be a more efficient way to do it, but it would not be more efficient if it was used only several times per scenario.
Last edited by Dugi on June 6th, 2013, 7:23 pm, edited 1 time in total.
User avatar
Elvish_Hunter
Posts: 1575
Joined: September 4th, 2009, 2:39 pm
Location: Lintanir Forest...

Re: advances_from

Post by Elvish_Hunter »

DranKof wrote:Where would I go to find out what data j, k, or fields (for instance) hold?
Usually I use the print function:

Code: Select all

for key, value in pairs( my_table ) do print( key, value ) end
However, the print function, when value is a table, instead of printing its content prints its memory address. In that case, one can create a recursive function to print it as well.
DranKof wrote:I can't even find a sticky about Wesnoth's LUA references to help me connect the language to Wesnoth a little better? [/me crosses fingers that he didn't miss an extremely obvious sticky or similar resource.]
Well, searching in Google for lua tutorial gives this result: http://lua-users.org/wiki/TutorialDirectory . That's possibly the staple resource for every Lua coder. 8)
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
DranKof
Posts: 34
Joined: May 30th, 2013, 6:35 am
Location: Beijing, China

Re: advances_from

Post by DranKof »

Dugi wrote:By the way, how many times do you use it? Because in the case if the tag was used ten times in a row in an event run several times in each scenario, there might be a more efficient way to do it, but it would not be more efficient if it was used only several times per scenario.
Just once in the beginning of the scenario. I have a screenshot of it doing what it's supposed to do on my mod's forum topic. Because the leader can be revived in the mod, to keep him from necessarily being too overpowered at the start, I wanted to add an option to replace the leader-heroes with a 1-level-lower variety. I just downloaded the Ageless Era and my fairly wooden computer seemed to load everything just fine with various eras with negligible, 1-time lag, so I wouldn't be too concerned about optimization.
Elvish_Hunter wrote:Usually I use the print function:

Code: Select all

for key, value in pairs( my_table ) do print( key, value ) end
However, the print function, when value is a table, instead of printing its content prints its memory address. In that case, one can create a recursive function to print it as well.
Well, searching in Google for lua tutorial gives this result: http://lua-users.org/wiki/TutorialDirectory . That's possibly the staple resource for every Lua coder. 8)
Bookmarked. Yeah, I guess I was wondering if there was a lua wiki just for Wesnoth that I totally overlooked, but between all the sample code I've been seeing in the forums and other peoples' mods lately, and now this resource also, I'm just gonna go back to quiet research as I work on a little bit of artwork. Thanks a bunch both of you, the code works perfect.
User avatar
Dugi
Posts: 4961
Joined: July 22nd, 2010, 10:29 am
Location: Carpathian Mountains
Contact:

Re: advances_from

Post by Dugi »

Just once in the beginning of the scenario.
If it is used only once, this is even more effective. The optimalisation I mentioned would be worth it only in the case when it was used a lot of times, and it isn't, so it would just slow it down.
User avatar
8680
Moderator Emeritus
Posts: 742
Joined: March 20th, 2011, 11:45 pm
Location: The past

Re: advances_from

Post by 8680 »

DranKof wrote:Yeah, I guess I was wondering if there was a lua wiki just for Wesnoth that I totally overlooked, […]
There is.
User avatar
DranKof
Posts: 34
Joined: May 30th, 2013, 6:35 am
Location: Beijing, China

Re: advances_from

Post by DranKof »

Oh wow, I totally missed the section on interface to the engine and helper functions, which is the missing piece I was looking for (before, I thought that page only listed WML-related tags).

So, between the Lua 5.2 Reference Manual, the LuaWML page with interface and helper functions, and the Lua-user's tutorial directory, it's starting to look a lot like Christmas in Wesnoth land. :mrgreen:
User avatar
Elvish_Hunter
Posts: 1575
Joined: September 4th, 2009, 2:39 pm
Location: Lintanir Forest...

Re: advances_from

Post by Elvish_Hunter »

DranKof wrote:So, between the Lua 5.2 Reference Manual, the LuaWML page with interface and helper functions, and the Lua-user's tutorial directory, it's starting to look a lot like Christmas in Wesnoth land. :mrgreen:
Well then, since it's Christmas have another gift 8) .
At this page: http://thomaslauer.com/comp/Lua_Short_Reference you can find a Lua cheat sheet in PDF, with almost all the functions briefly explained. Unfortunately it lacks something (like the string.reverse function, or tabke.pack/unpack from Lua 5.2), but it's still a useful resource.
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)
Post Reply