Lua debug script support

I’ve been watching this project since before Whales released the source code, so I thought it was about time I made a contribution. I’ve been thinking about how this would work for a while, and today I finally took a crack at adding some simple lua scripting support to DDA.

for v = 1,100,1 do get_item(v,20,false) end

The above lua script will add 20 of each of the first 100 objects in the master items list (starting after the null item) to the player’s inventory, using the rough system I have coded right now.

Now that I’ve got basic support in place, I could add any number of debug commands: mutate, spawn monsters, edit map tiles, spawn vehicles, add bionics, etc. My question for you guys is, would you like me to expand on this? I would like to have a simple script that quickly puts me in god mode or creates a certain map structure without having to open the (currently very limited) debug menu hundreds of times, but I want to know if there’s any desire for this. Hell, it doesn’t just have to be used for debug or cheaty purposes. Lua scripts could become a more permanent part of the game for modding things that can’t be expressed in json files.

What do you guys think?

Hi Gatleos,

CIB was working on something like this a month or so ago.

Best to talk to him on IRC and check his progress first before you continue.

Here are his pull requests.

Lua Support

Adds lua support for iuse’s and a lua debug command

Adds lua support for iuse’s and a lua debug commandLua ok

Welp

Looks like he was binding a large portion of the codebase to lua functions, as well as whole data structures. I was just planning on allowing access to a few dozen functions for debug purposes. Thanks for the link, I wouldn’t want to waste time on this if it’s already being done.

It looks like you’re going in a bit of a different direction with it. The think holding his stuff up is that if we do what he’s proposing we’ll have to integrate fully with LUA and make it a hard dependency, which we’re generally pretty against. If your system is an optional dependency, that’s something we could drop in immediately since we don’t have to worry about supporting it in all releases.

Depends on what you mean by “optional” dependency. What I was trying to do is make the lua functions (which have to use C syntax) work as wrappers around existing functions, so that future releases don’t completely break compatibility with the scripts later on. Right now I just have the whole lua source included with my project, but I could get it into a static library.

I really haven’t done much to the code, so it all depends on what you guys want from lua support.

Right now we have one hard dependency, the curses library. We have features that add dependencies on gettext (for translation) and SDL (for alternate text rendering, or tile support).

If it’s for debugging functions, we could make builds that don’t have any dependencies on LUA, those builds just wouldn’t have that feature. If we used LUA for modding support, it would be mandatory for all builds to depends on LUA.

Additional mandatory dependencies raise barriers to people working on the core code, since it complicates the build process. Ideally you can just grab the source and build, if you have to grab the project source and development libraries for a bunch of other stuff, some people, who would otherwise have been valuable contributors, might just not take that first step.

Bottom line, if we can make the dependency on LUA optional with a compile flag or something, there’s a very good chance we’ll want to add this, if it makes LUA mandatory for all builds we’ll have to put some more thougt into whether we want to do that or not.

Other than calls to initialize and garbage collect for lua in the main() function and an extra member function in the game class, everything related to lua is stored in separate files. I can easily add some preprocessor stuff to make lua dependency optional in compilation, but I don’t really have enough experience with makefiles and command line compilation to integrate that. If you or someone else wants to add a “LUA_SUPPORT” flag to the makefile when merging the code, I can easily make this optional.

Sure, I’m not demanding you do everything involved.

Alright, I’ve got quite a few debug functions registered to be called from lua files. It’s by no means comprehensive yet, but it should allow you to do some interesting things.
What we’ve got so far is:

[spoiler][code]int,int get_player_pos()
int get_monsterlist_size()
int,int look_around()
int menu(bool cancelable,string name,…)
int rng(int low,int high)
debugmsg(string msg)

set_tile(int index,int posx,int posy)
spawn_creature(int index,int posx,int posy)
get_item(int index,int count,bool incontainer)
get_item(string index,int count,bool incontainer)
spawn_item(int index,int posx,int posy,int count,bool incontainer)
spawn_item(string index,int posx,int posy,int count,bool incontainer)
mutate(int index)
bionic(int index)
set_skill(int level)
set_skill(int level,int index)
set_skill(int level,string index)[/code][/spoiler]

I’ve got functions for changing terrain, spawning items, spawning monsters, creating menus, setting skills, etc. and it can all be edited on the fly through .lua files. Does anybody have any other functions they would like included?

I’ve not made a PR with my lua stuff since I can’t really think of a use of it right now(other than simple debug and testing). Adding a few #ifdef’s and cleaning up my files would be trivial if people wanted optional lua compilation for debug functionality, but so far I didn’t think that was desired.

For my part the main thing I’d use it for (I think anyway) would be poking at LUA and figuring out how LUA/C++ interaction works in practice, but I assume Gatleos finds it useful, and as long as it’s fairly non-invasive and optional, I don’t see a problem with including it. Same for the LUA integration CIB proposed, but that struck me as requiring a hard dependency, which is why I never suggested it being optional.

But… LUA modding support would be so coooooool

That aside, I think that sooner or later we are going to end up with a “code-like” system in the modding JSON files (see, e.g. any paradox grand strategy game, or Mount & Blade; FWIW the modding buffs in my martial arts branch already constitute a regular language in the formal sense). While I don’t strictly disagree with anything Kevin says re: dependencies, I think it might be nice to jump the gun here and implement some kind of real scripting language because eventually we are all going to be hand-writing ASTs or DFA graphs in JSON anyways.

I think assuming that there WILL be a scripting language is a bit of a stretch. I can certainly see there are some major benefits, and also some major issues with it, but we certainly could continue with JSON just being data and all the logic being implemented in the main code.

If there’s going to be a scripting language, it’s pretty much going to be LUA, there’s definitely no reason to implement our own scripting language. There’s a bit of a chicken-and-egg problem though, in that it’s a big additional dependency, and of course you can’t see any benefits until you actually do it. The traditional way to overcome this hump is to either make a very detailed proposal of how everything is going to work, or go ahead and implement it with enough features to demonstrate that it will work and integrate well. Unit testing has the same problem, I integrated with libtap and wrote some prototypical tests, but they don’t really accomplish anything, so no one (including myself) has written any significant tests.

I think the optional debug functionality is a good middle-ground, where we can integrate with the LUA build dependencies and protype some approaches for further use without making it a hard dependency.

No, the framework is pretty separate, I’m actually done implementing the #ifdef switch. There’s hardly any intrusion into the other files, except the iuse wrapper(which can be made to just wrap C++ if no lua is present), some init calls and the lua debug command(which for the time being I just put at the end of the list with an #ifdef, until someone finally codes a non-hardcoded debug menu).

EDIT: PR is up Optional lua for debugging by CIB · Pull Request #2862 · CleverRaven/Cataclysm-DDA · GitHub

I’ve written up some documentation: https://github.com/CIB/Cataclysm-DDA/blob/7fdb2ee733ddb312063bd2c29c202283309e557a/code_doc/LUA_SUPPORT.md

This might help others understand what my framework is about, how it can be used and extended, and how one could benefit from it.

What happens if an item tries to use an iuse defined in LUA and LUA isn’t supported? I assume at the least the item doesn’t work, that’s a hard dependency, since parts of the game break if it’s disabled.

Or am I misunderstanding, and it’s wrapping iuse so it can call the iuse functions, instead of being able to call LUA iuse functions?

The iuse’s are defined from the lua script. If some item makes use of a lua iuse and lua isn’t loaded, the same thing will happen as if the iuse isn’t defined. It would be a hard dependency if someone actually moved iuse.cpp to lua, but that’s obvious, isn’t it? As it is, it’s more like you can prototype iuse’s in lua, but if you wanted to commit them, you’d have to rewrite them in C++.

Aah, that makes sense, prototyping in LUA hadn’t occured to me since I’m much more fluent in C++ than LUA.

When I started working on this, it was just to become more familiar with lua and get some practice with it (as well as familiarizing myself with the dda code). I’ve made plenty of progress, but don’t feel obligated in any way to use what I’ve made here. CIB’s implementation is far more useful, as it looks like he’s allowing prototyping of item code in addition to a lua debug api.

Ideally, if you have some good ideas/working code for things one could do with lua, I could incorporate them into my PR. I haven’t really used lua very actively, since it’s that much easier to just work with the C++ code if you already know it, so some fresh perspective would help.