Anonymissimus' lua thread
Moderator: Forum Moderators
-
- Inactive Developer
- Posts: 2461
- Joined: August 15th, 2008, 8:46 pm
- Location: Germany
Anonymissimus' lua thread
The wesnoth core macro MODIFY_UNIT does not allow changing more than one key per unit per call. This results in the need to repeatedly store and unstore the unit (performance ?!) to change more than one key, or to not use the macro at all.
First I wrote a wml version of this functionality using [split]:
This sets hitpoints=30 and max_moves=20 for all units on side=1.
Then I wanted to know whether this would've been easier with the help of "silene's darling" lua; to solve the question whether lua is worth being learned I need to learn it. There is a function modify_unit in helper.lua, which indeed allows modifying more than one variable per unit, which is probably the reason why silene has written it.
For editing reasons, I want to keep lua code and wml code completely separated in different files:
file setup.lua:
file modify_unit.lua:
Is there a way to make the transfer of the arguments to the lua code easier ?
What is a good development environment for this language ? (e.g. live syntax check ?)
I'd like to see "proxy" and "table" to be documented better on the wiki.
Although lua doesn't seem to be hard to learn if one has already programming experience, I doubt that there'll be many wml authors who'll try it. There are problems:
-It requires learning a new language for little benefit.
-Mixing 2 languages - although I've solved that in a bit complicated way, so that I can use the appropriate language settings in my editor for each of the files.
-What additional stuff does lua allow - other than calculating sin(x) more easily in wml via access to the C math library now ?
After all, the complexity of both solutions for modifying several unit variables seems equal, since the function modify_unit in helper.lua must be added to the lua approach.
How is lua handled by the engine ? Is it parsed in the same way like wml ? The preprocessor at least seems to make no difference.
How is lua in terms of performance compared to wml ?
There's of course a ton of other questions but I'm finished for now.
First I wrote a wml version of this functionality using [split]:
Spoiler:
Then I wanted to know whether this would've been easier with the help of "silene's darling" lua; to solve the question whether lua is worth being learned I need to learn it. There is a function modify_unit in helper.lua, which indeed allows modifying more than one variable per unit, which is probably the reason why silene has written it.
For editing reasons, I want to keep lua code and wml code completely separated in different files:
file setup.lua:
Code: Select all
<<
helper = wesnoth.require "lua/helper.lua"
--proxy = helper.set_wml_action_metatable {}
--_ = wesnoth.textdomain "my-campaign"
-- Define your global constants here.
-- ...
--helper.set_wml_var_metatable(_G)
-- Define your global functions here.
-- ...
>>
Code: Select all
<<
-- helper.modify_unit({side=1},{hitpoints=100,max_moves=2})
local args = ...
--Accessing the text below works:
--wesnoth.message(tostring(args.text))
local filter=helper.get_child(args.__parsed,"filter")
local variables=helper.get_child(args.__parsed,"variables")
helper.modify_unit(filter,variables)
>>
Code: Select all
#define LUA FILE ARGS
[lua]
code = {~add-ons/Testcampaign/utils/lua/{FILE}.lua}
[args]
{ARGS}
[/args]
[/lua]
#enddef
#define SETUP_LUA
[event]
name=preload
first_time_only=no
{LUA setup ()}
[/event]
#enddef
{SETUP_LUA}
[event]
...
{LUA modify_unit (
[filter]
side=1
id=Hamel
[/filter]
[variables]
hitpoints=100
max_moves=10
[/variables]
)}
[/event]
What is a good development environment for this language ? (e.g. live syntax check ?)
I'd like to see "proxy" and "table" to be documented better on the wiki.
Although lua doesn't seem to be hard to learn if one has already programming experience, I doubt that there'll be many wml authors who'll try it. There are problems:
-It requires learning a new language for little benefit.
-Mixing 2 languages - although I've solved that in a bit complicated way, so that I can use the appropriate language settings in my editor for each of the files.
-What additional stuff does lua allow - other than calculating sin(x) more easily in wml via access to the C math library now ?
After all, the complexity of both solutions for modifying several unit variables seems equal, since the function modify_unit in helper.lua must be added to the lua approach.
How is lua handled by the engine ? Is it parsed in the same way like wml ? The preprocessor at least seems to make no difference.
How is lua in terms of performance compared to wml ?
There's of course a ton of other questions but I'm finished for now.
Last edited by Anonymissimus on July 19th, 2010, 1:51 pm, edited 1 time in total.
projects (BfW 1.12):
A Simple Campaign: campaign draft for wml starters • Plan Your Advancements: mp mod
The Earth's Gut: sp campaign • Settlers of Wesnoth: mp scenario • Wesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
A Simple Campaign: campaign draft for wml starters • Plan Your Advancements: mp mod
The Earth's Gut: sp campaign • Settlers of Wesnoth: mp scenario • Wesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
Re: some first steps in lua, questions and discussion
This may not be directly related to your question, but I just wanted to point out that there is a much cleaner way to create this macro in WML than the way you attempted. Since you obviously know how [set_variables] mode=merge works, I am surprised you aren't using that to merge a "diff" WML into each unit.
e.g. to make all the Spearmen turn to side 2 and go to 1 hitpoint:
{MODIFY_UNITS type=Spearman hitpoints,side=1,2}
or to poison them:
{MODIFY_UNITS type=Spearman (
[status]
posioned=yes
[/status]
)}
it's quite possible...
however, to answer your question, one of the main benefits of learning lua is you don't *need* a macro. Instead, you should register an action handler, and invoke it like [just_like_any_other_tag] ... then pass in arguments to the tag...
A final note, as a WML author you really shouldn't be worrying about performance. If anything, you should be concerned with "WML bloat," which can be determined by the final line count of all your code after preprocessing (turn on uncompressed saves and save your game to get an idea). WML bloat has been shown to cause laggy responsiveness, especially during autosaves which occur at the beginning of every turn.
e.g. to make all the Spearmen turn to side 2 and go to 1 hitpoint:
{MODIFY_UNITS type=Spearman hitpoints,side=1,2}
or to poison them:
{MODIFY_UNITS type=Spearman (
[status]
posioned=yes
[/status]
)}
it's quite possible...
however, to answer your question, one of the main benefits of learning lua is you don't *need* a macro. Instead, you should register an action handler, and invoke it like [just_like_any_other_tag] ... then pass in arguments to the tag...
A final note, as a WML author you really shouldn't be worrying about performance. If anything, you should be concerned with "WML bloat," which can be determined by the final line count of all your code after preprocessing (turn on uncompressed saves and save your game to get an idea). WML bloat has been shown to cause laggy responsiveness, especially during autosaves which occur at the beginning of every turn.
http://www.wesnoth.org/wiki/User:Sapient... "Looks like your skills saved us again. Uh, well at least, they saved Soarin's apple pie."
Re: some first steps in lua, questions and discussion
Actually, it was more to test that the very first version of the Lua interface was usable. The fact that it handles several variables at once is just a side effect: the code for handling only one variable would be exactly the same (or worse, it would be more complicated if it had to error out in presence of several variables).Anonymissimus wrote:Then I wanted to know whether this would've been easier with the help of "silene's darling" lua; to solve the question whether lua is worth being learned I need to learn it. There is a function modify_unit in helper.lua, which indeed allows modifying more than one variable per unit, which is probably the reason why silene has written it.
That's a good decision, but one can do a bit better.Anonymissimus wrote:For editing reasons, I want to keep lua code and wml code completely separated in different files:
First, don't use strong quotes <<>> inside your Lua files. That way, the files will be pure Lua files, which means that you can ask you text editor to use syntactic coloration and you can directly send your Lua files to the Lua compiler/interpreter to test your files without having to launch Wesnoth. In other words, you get your "live syntax check".
Second, I wouldn't use several files, but one file with several functions:
Code: Select all
local helper = wesnoth.require "lua/helper.lua"
function modify_unit(args)
args = args.__parsed
local filter = helper.get_child(args, "filter")
local variables = helper.get_child(args, "variables")
helper.modify_unit(filter,variables)
end
-- other functions below
Code: Select all
[event]
name=preload
first_time_only=no
[lua]
code = "wesnoth.dofile 'Testcampaign/utils/lua/functions.lua'"
[/lua]
[/event]
#define LUA FUNCTION ARGS
[lua]
code = "{FUNCTION}(...)"
[args]
{ARGS}
[/args]
[/lua]
#enddef
As Sapient already mentioned, define new WML tags. The Lua code and the preload event are not modified; just add a registration point at the end of your Lua file:Anonymissimus wrote:Is there a way to make the transfer of the arguments to the lua code easier ?
Code: Select all
wesnoth.register_wml_action("modify_unit", modify_unit)
Code: Select all
[modify_unit]
[filter]
side=1
id=Hamel
[/filter]
[variables]
hitpoints=100
max_moves=10
[/variables]
[/modify_unit]
Any particular thing you want me to explain better in wiki?Anonymissimus wrote:I'd like to see "proxy" and "table" to be documented better on the wiki.
It depends on your point of view. Lua is structured like a modern language, and anybody that knows Lua would have no difficulty to understand/switch to another programming language.Anonymissimus wrote:Although lua doesn't seem to be hard to learn if one has already programming experience, I doubt that there'll be many wml authors who'll try it. There are problems:
-It requires learning a new language for little benefit.
That would not be the first time in Wesnoth' history. Think FormulaWML for instance.Anonymissimus wrote:-Mixing 2 languages - although I've solved that in a bit complicated way, so that I can use the appropriate language settings in my editor for each of the files.
There isn't much more it can do; perhaps the only thing really lacking in plain WML with respect to Lua is access to the pathfinder. Anyway, the Lua interface wasn't written to give more control over the engine to scenarios, it was written to provide higher-level programming structures. You get floating-point arithmetic, string manipulation, array manipulation, dictionaries, generators, higher-order functions, and so on.Anonymissimus wrote:-What additional stuff does lua allow - other than calculating sin(x) more easily in wml via access to the C math library now ?
For instance, consider this file from LoW: replace_map.lua. It adds x= and y= attributes to the [replace_map] tag so that it no longer loads an entire new map but only a subset of it. I'm sure that the same loading functionality could be implemented in plain WML, but I'm also sure that I wouldn't be able to implement it in only 15 minutes and 30 lines.
The embedded Lua code is preprocessed and parsed the same way than other WML (technically, it is just the value of an attribute from a tag). It is compiled on the fly, whenever the [lua] tag is executed. Lua files are compiled (they are never preprocessed nor parsed though since they are not embedded) whenever the "dofile" command is executed or the first time the "require" command is executed. So, to summarize, if you are using "dofile" and "register_wml_action" in a preload event, you will have no preprocessing nor parsing at all and a single compilation at scenario load time.Anonymissimus wrote:How is lua handled by the engine ? Is it parsed in the same way like wml ? The preprocessor at least seems to make no difference.
It depends. The rule of thumb is that it is much faster. (As surprising as it may seems, there are even a few things for which a Lua script would be faster than even the corresponding C++ code added to Wesnoth, since it internalizes strings and hashes tables.) If you care about performance, just avoid accessing the __special fields (__cfg, __parsed, and so on) several times in the row; just do it once and for all, as in the modify_unit example above.Anonymissimus wrote:How is lua in terms of performance compared to wml ?
-
- Inactive Developer
- Posts: 2461
- Joined: August 15th, 2008, 8:46 pm
- Location: Germany
Re: some first steps in lua, questions and discussion
It was the first time for me using [set_variables] mode=merge, and I'm unsure whether I know how it works. What would that part of the macro where a single unit variable (the container variable containing the unit) is modified about look like then ? I can't get a clear imagination of the code yet.Sapient wrote:Since you obviously know how [set_variables] mode=merge works, I am surprised you aren't using that to merge a "diff" WML into each unit.
e.g. to make all the Spearmen turn to side 2 and go to 1 hitpoint:
{MODIFY_UNITS type=Spearman hitpoints,side=1,2}
or to poison them:
{MODIFY_UNITS type=Spearman (
[status]
posioned=yes
[/status]
)}
I have one or two cases in my campaign with a serious slowdown...Sapient wrote:If anything, you should be concerned with "WML bloat," which can be determined by the final line count of all your code after preprocessing (turn on uncompressed saves and save your game to get an idea). WML bloat has been shown to cause laggy responsiveness, especially during autosaves which occur at the beginning of every turn.
So wml bloat, if I get it right, is caused by the way wml is made: The preprocessor inserts the code from macros at the positions where these macros are called, with parameters inserted (I used to think of this like an "inline" function in C++...), causing the code to get large. A way around this, while keeping the functionality, are true functions now provided by lua, which are kept separate: The same lua code is referenced from various positions where code from a macro would have been inserted all the time. But only if used in the way suggested by silene (loading the lua code with dofile or require) - doing it the way I wanted to do it the preprocessor inserts the lua code ?! 1:0 for lua...
This features the problem that emacs+wesnoth mode (about the most "comfortable" editing environment for wml) won't know that new tag, disabling autocompletion and spamming "Tag not available in this context" messages on syntax check, making it hard to sort out that tags that really aren't available in their given context...silene wrote:Then you don't need the LUA macro anymore, you can directly type:Code: Select all
[modify_unit] [filter] side=1 id=Hamel [/filter] [variables] hitpoints=100 max_moves=10 [/variables] [/modify_unit]
Probably nothing particular. The way I understood it from about 2 days of reading and playing around is that in lua "table" is about the same like a container variable in wml / struct in C++, but it can also contain functions, since e.g. "helper" in my code seems to be a table, too.Any particular thing you want me to explain better in wiki?
Lua features true functions, an implicit type system (I suppose) and variable/function modifiers (e.g. local). Stuff people who've only learned wml don't know about...It depends on your point of view. Lua is structured like a modern language, and anybody that knows Lua would have no difficulty to understand/switch to another programming language.
Eclipse+java is still the easiest way to learn programming I can think of. It features the live syntax check I mean (in case you misunderstood that) - display of errors as soon as one has just typed the code. Getting them after compiling without needing to launch wesnoth is still an improvement - 2:0 for lua...
projects (BfW 1.12):
A Simple Campaign: campaign draft for wml starters • Plan Your Advancements: mp mod
The Earth's Gut: sp campaign • Settlers of Wesnoth: mp scenario • Wesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
A Simple Campaign: campaign draft for wml starters • Plan Your Advancements: mp mod
The Earth's Gut: sp campaign • Settlers of Wesnoth: mp scenario • Wesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
-
- Inactive Developer
- Posts: 2461
- Joined: August 15th, 2008, 8:46 pm
- Location: Germany
Re: some first steps in lua, questions and discussion
Is it right that functionalities from the global table wesnoth aren't accessible without starting wesnoth ?
Most of the functionalities from the files in /data/lua/ also aren't usable since they're using that table themselves ?
Most of the functionalities from the files in /data/lua/ also aren't usable since they're using that table themselves ?
projects (BfW 1.12):
A Simple Campaign: campaign draft for wml starters • Plan Your Advancements: mp mod
The Earth's Gut: sp campaign • Settlers of Wesnoth: mp scenario • Wesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
A Simple Campaign: campaign draft for wml starters • Plan Your Advancements: mp mod
The Earth's Gut: sp campaign • Settlers of Wesnoth: mp scenario • Wesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
Re: some first steps in lua, questions and discussion
That is right. Is there a reason for wanting to use the wesnoth table outside Wesnoth? I have considered several times providing a dummy implementation that would allow people to run LuaWML scripts outside Wesnoth, but in the end it was never worth it. Perhaps you have a need for it?Anonymissimus wrote:Is it right that functionalities from the global table wesnoth aren't accessible without starting wesnoth ?
Most of the functionalities from the files in /data/lua/ also aren't usable since they're using that table themselves ?
-
- Inactive Developer
- Posts: 2461
- Joined: August 15th, 2008, 8:46 pm
- Location: Germany
Re: some first steps in lua, questions and discussion
One of my main motivations to cope with lua is the lacking need to launch the wesnoth engine to test the code since it's a lot faster. Writing functionalities for wesnoth in lua without using the table wesnoth seems rather pointless so that's currently the only reason for me.silene wrote:That is right. Is there a reason for wanting to use the wesnoth table outside Wesnoth? I have considered several times providing a dummy implementation that would allow people to run LuaWML scripts outside Wesnoth, but in the end it was never worth it. Perhaps you have a need for it?Anonymissimus wrote:Is it right that functionalities from the global table wesnoth aren't accessible without starting wesnoth ?
Most of the functionalities from the files in /data/lua/ also aren't usable since they're using that table themselves ?
How much work would that be and what's the benefit ? Would the functions return initialized values then, but not calculate or do anything ?
projects (BfW 1.12):
A Simple Campaign: campaign draft for wml starters • Plan Your Advancements: mp mod
The Earth's Gut: sp campaign • Settlers of Wesnoth: mp scenario • Wesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
A Simple Campaign: campaign draft for wml starters • Plan Your Advancements: mp mod
The Earth's Gut: sp campaign • Settlers of Wesnoth: mp scenario • Wesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
Re: some first steps in lua, questions and discussion
Sorry, don't understand. The "wesnoth" table contains C++ function exported by the engine, and they are the only way for a LuaWML script to interact with the external world in general and with Wesnoth in particular. So a Lua script that wouldn't use them would indeed be pointless from a WML point of view. But on the other hand, there is no point in executing a LuaWML script outside Wesnoth, since there would be nothing for it to interact with.Anonymissimus wrote:One of my main motivations to cope with lua is the lacking need to launch the wesnoth engine to test the code since it's a lot faster. Writing functionalities for wesnoth in lua without using the table wesnoth seems rather pointless so that's currently the only reason for me.
So, I'm still not sure why you would execute scripts outside Wesnoth. However, what makes sense to me is not to execute them but just to compile them. That way, you can detect beforehand if there are syntax errors. In practice, you just try to execute the scripts, and if the error you get is "attempt to index global 'wesnoth' (a nil value)", then it means your script doesn't contain any syntax error (since lua tried to executed it).
By the way, when I write LuaWML scripts, I always have Wesnoth running. Contrarily to plain WML, you don't need to restart the game or even the scenario to test Lua scripts. For instance, let's assume you have written or modified a function "foo" in a file "bar.lua" and you want to know how the the function behaves. Then you can just type from inside the game:
Code: Select all
:lua wesnoth.dofile "bar.lua"
:lua foo(some, args)
The amount of work depends on the realism you expect from the functions. For instance, writing trivial functions that don't do anything is a few minutes job. For instance,Anonymissimus wrote:How much work would that be and what's the benefit ? Would the functions return initialized values then, but not calculate or do anything ?
Code: Select all
wesnoth = {}
function wesnoth.register_wml_action(name, fun) print("Registering function for action " .. name) end
function wesnoth.fire(name, cfg) print("Executing WML action " .. name) end
-- and so on
-
- Inactive Developer
- Posts: 2461
- Joined: August 15th, 2008, 8:46 pm
- Location: Germany
Re: some first steps in lua, questions and discussion
I've just installed lua mode for emacs and a lua interpreter and I'm not yet sure about where the difference is at this thing between compiling and execution - other than e.g. VS C++.
But this
The rest of your post makes somehow sense to me, too.
But this
is probably even better than the benefit which I was exspecting from the dummy table+compiling lua with an external interpreter.silene wrote:Contrarily to plain WML, you don't need to restart the game or even the scenario to test Lua scripts. For instance, let's assume you have written or modified a function "foo" in a file "bar.lua" and you want to know how the the function behaves. Then you can just type from inside the game:Code: Select all
:lua wesnoth.dofile "bar.lua" :lua foo(some, args)
The rest of your post makes somehow sense to me, too.
projects (BfW 1.12):
A Simple Campaign: campaign draft for wml starters • Plan Your Advancements: mp mod
The Earth's Gut: sp campaign • Settlers of Wesnoth: mp scenario • Wesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
A Simple Campaign: campaign draft for wml starters • Plan Your Advancements: mp mod
The Earth's Gut: sp campaign • Settlers of Wesnoth: mp scenario • Wesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
Re: some first steps in lua, questions and discussion
It isn't needed for using Lua, but I will try to clarify a few details.Anonymissimus wrote:I've just installed lua mode for emacs and a lua interpreter and I'm not yet sure about where the difference is at this thing between compiling and execution - other than e.g. VS C++.
Lua is not really an interpreted language. When you try to execute a Lua script, it is first compiled to a binary program containing elementary instructions. This first phase will fail if there are syntax errors in the script. This binary program is then executed by the Lua virtual machine. This second phase will fail if there are logic errors in the script.
The important point is that the compilation phase does not depend on the environment that will later run the script: there is only one Lua language. In particular, whether the global variable "wesnoth" contains a table does not matter at compile time. So you don't have to use Wesnoth to check that your file doesn't contain any syntax error, you can directly use Emacs.
I'm not a user of Emacs and I have never seen what the lua mode is like. But if it does behaves like other Emacs modes and if everything is properly installed, you should get a "lua" entry in your menubar when you load a lua file. Then you can select "send buffer" in this menu and your file will be sent to the Lua interpreter. For instance, you can try typing "print(2 + 2)" and hopefully a new buffer should open with the answer "4".
Obviously, you will get execution errors if you send a LuaWML script to the interpreter, since the "wesnoth" table doesn't exist in its environment. But if the interpreter actually complains about your trying to access wesnoth as nil, it means that the compilation was successful since it is trying to execute the script. Therefore the script didn't contain syntax error (e.g. parentheses and brackets are properly balanced, operators are properly used, and so on). So, before saving your file and trying to load it in Wesnoth, just try to send it to the interpreter from Emacs and it will detect a first batch of errors.
Re: some first steps in lua, questions and discussion
Could someone clarify exactly how to reference files with wesnoth.dofile and wesnoth.require? The wiki says that they "Load the given filename (relative to the content directory)", but what exactly does that mean? What's the content directory?
It seems like the content directory would be equivalent to the ~ (or lack thereof) in preprocessor includes. This makes sense compared to silene's suggestion on how to include files. However, when I tried to follow silene's instructions to use an external lua file, it didn't work.
Here's the error message:
It seems like the content directory would be equivalent to the ~ (or lack thereof) in preprocessor includes. This makes sense compared to silene's suggestion on how to include files. However, when I tried to follow silene's instructions to use an external lua file, it didn't work.
Here's my code:silene wrote:Code: Select all
[event] name=preload first_time_only=no [lua] code = "wesnoth.dofile 'Testcampaign/utils/lua/functions.lua'" [/lua] [/event]
Code: Select all
[event]
name=preload
first_time_only=no
[lua]
code = "wesnoth.dofile 'Brent/utils/brent_utils.lua'"
[/lua]
[/event]
Code: Select all
20091228 18:49:15 error scripting/lua: [string "wesnoth.dofile 'Brent/utils/brent_utils.lua..."]:1: bad argument #1 to 'dofile' (file not found)
stack traceback:
[C]: in function 'dofile'
[string "wesnoth.dofile 'Brent/utils/brent_utils.lua..."]:1: in main chunk
-
- Inactive Developer
- Posts: 2461
- Joined: August 15th, 2008, 8:46 pm
- Location: Germany
Re: some first steps in lua, questions and discussion
bad argument #1 to me, "content directory" is meaningless!melinath wrote:Could someone clarify exactly how to reference files with wesnoth.dofile and wesnoth.require? The wiki says that they "Load the given filename (relative to the content directory)", but what exactly does that mean? What's the content directory?
Try about this, that works for me:
Code: Select all
code= <<
--...
functions = wesnoth.require "~add-ons/Testcampaign/utils/lua/functions.lua"
--...
>>
return functions
at the end to make it work that way.
projects (BfW 1.12):
A Simple Campaign: campaign draft for wml starters • Plan Your Advancements: mp mod
The Earth's Gut: sp campaign • Settlers of Wesnoth: mp scenario • Wesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
A Simple Campaign: campaign draft for wml starters • Plan Your Advancements: mp mod
The Earth's Gut: sp campaign • Settlers of Wesnoth: mp scenario • Wesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
Re: some first steps in lua, questions and discussion
Oh, so it just follows the same rules as the WML directory tools... thanks!
I'm experimenting with putting the lua file in _main.cfg, since that's how LOW does it. Seems more efficient.
I'm experimenting with putting the lua file in _main.cfg, since that's how LOW does it. Seems more efficient.
Re: some first steps in lua, questions and discussion
Almost. The main difference is that you are not allowed to use relative locations "./something" since WML doesn't know about directories (only the preprocessor does).melinath wrote:Oh, so it just follows the same rules as the WML directory tools... thanks!
It's equivalent to having a preload event. If you indeed use the same Lua code for all your scenarios (e.g. definition of new tags), the _main.cfg file (or any equivalent file) is indeed the best place to put a Lua script loader.melinath wrote:I'm experimenting with putting the lua file in _main.cfg, since that's how LOW does it. Seems more efficient.
From the point of view of locating files, "dofile" and "require" behave the same way; this path would have worked for both. Both of them also return the result of the script (that is, if last line of the script is "return something"). The main difference is that, "require" puts the result of the script in a cache and returns it for subsequent calls to the same script. (By the way, that means you can't use "require" to force Wesnoth to reload a file with ":lua".)Anonymissimus wrote:In file functions.lua needs to be aCode: Select all
code= << --... functions = wesnoth.require "~add-ons/Testcampaign/utils/lua/functions.lua" --... >>
return functions
at the end to make it work that way.
So, if your script is mainly registering WML actions and defining global functions, "dofile" is the way to go.
But, if your script is in fact a library, then "require" should be used. We could imagine that, at a point, someone ships a LuaTricks add-on that is meant to be used by several other add-ons. For instance, this is already the case with the "lua/helper.lua" script from mainline: it is used by several independent places so it would be hard to choose a single place where to put "dofile". For the same reason, "require" is also useful for an era with [unit_type] events, since you don't have control over a "preload" event. Each event will use "require" to load the needed functions, but the actual load will happen only once.
By the way, the structure of a file to be loaded by "require" is:
Code: Select all
local library = {} -- the actual name doesn't matter since it is local to the file
function library.do_something(a) ... end
function library.go_somewhere(x, y) ... end
return library
Re: some first steps in lua, questions and discussion
It might be useful to also include something on how to access the information in raw WML dumps like stored_unit.__cfg.
Comparison of a save file to a partial dump of a unit cfg (see script below) has shown that __cfg has a structure as follows:
This setup fits somewhat with how WML is supposed to be stored by Lua. But I can't seem to access actual values...
I haven't figured out yet how to access things like unit.id from the __cfg...
P.S. Even after I get this reading thing done, I'd like to polish this script to be more useful, so if anyone has suggestions/corrections/tricks, it'd be great!
EDIT:: Found a better script on the internet using for...in, which I hadn't found yet. If anyone's interested, here's the modified version I'm using now:
Still working on how this will help me actually access things...
EDIT EDIT::
Um. Okay, feel silly now. Just had to do team.__cfg.shroud_data to get the shroud data. Which now seems really obvious.
Comparison of a save file to a partial dump of a unit cfg (see script below) has shown that __cfg has a structure as follows:
Code: Select all
cfg = the [unit] tag. This is a table.
cfg[1] = the first child tag of the [unit] tag: say, the [portrait] tag. This is also a table. Let's call it v.
v[1] = the first child tag's tag name. String. Say, "advancement".
v[2] = the first child tag's contents. We'll call it q.
q[1] = a table. There are as many qs as there are WML containers inside the tag that v represents. I suspect that if we call this table r, we would find that:
r[1] = the first child container's name. Say, "effect"
r[2] = the first child containter's contents.
etc.
I haven't figured out yet how to access things like unit.id from the __cfg...
Script!:
EDIT:: Found a better script on the internet using for...in, which I hadn't found yet. If anyone's interested, here's the modified version I'm using now:
Spoiler:
EDIT EDIT::
Um. Okay, feel silly now. Just had to do team.__cfg.shroud_data to get the shroud data. Which now seems really obvious.
Last edited by melinath on December 29th, 2009, 10:17 am, edited 2 times in total.