Jump to content
  • 1

Modding request: move and keep more things in mod-accessible places in the .lua files


Nyrin

Suggestion

Now, I know that making it work is the first priority--but given how awesome the modding potential is, the better we can make it... well, the better. None of this is intended as a whine; you've invested a lot into making Avorion nicely moddable (thank you!) and as a player and a modder I'd just like to see that investment maximized.

The problem

A lot of state and behavior is embedded inside of functions in ways that can't be easily augmented or changed via mods--replacing entire, often very large functions is necessary if you want to change the thing in the middle, and that's enormously fragile and problematic for maintenance and compatibility.

Three examples I've hit recently that are only representative:

1. mapcommands.lua -- I want to add logic to secure/restore the button state for "show these ships," and *that* part of it is easy enough to do since the shipList variable is file-global. But for updating the button overlays in the UI, there's no way--the buttons are created as temporary, local variables in the 320-line initUI function and, since the callback functions take the button table as a parameter, there's no way to modify these without replacing the entirety of that function -- which would be a very bad idea!

2. tradecommand.lua (this is common across commands) -- similar pattern, except this time I want to add UI. The almost 400-line buildUI function does almost everything UI-related as temporary variables, meaning there's again no way of changing or modifying existing state without replacing the entire function and signing up for all but guaranteed future compatibility headaches. I was able to add UI by retracting the steps of the top-level rects and then drawing where it "should be," but although this is less likely to break it's just as likely to end up drawing over the top of something it shouldn't in the future.

3. Also tradecommand.lua, just wanted to give a non-UI example: the generateAssessmentFromPrediction function adds lines in that are pulled from function-local variables rather than a global table or atomic helper functions, meaning that replacement or augmentation of a category requires either replacing the whole function (fragile, loses out on interoperability and future changes) or blind manipulation of table entries (potential very weird compatibility breaks, though less likely to all-out break). 

Fixes

First and foremost, and I mentioned this on another feedback: please consider open-sourcing the public part of the .lua files! By that, I mean put it on GitHub or somewhere that can accept public pull requests that you can take a look at and summarily approve or reject. We already have the files thanks to the modding strategy, so this just lets you get potential free fixes and work from the community.

Beyond that, though, I know nobody's going to go redo everything (I hope not, anyway), but just principles to keep in mind for mod-friendliness:

- Whenever possible, keep UI elements in distinct, global(/file scope) variables and/or have atomic helper functions that build each piece of a bigger part. Every something important goes off to die in a local variable, our ability to interact with it is diminished. 

- Likewise for constants, string tables, etc., disprefer putting them as local variables in big functions -- I had to completely replace ScoutCommand:revealSectors to add new lines, whereas ideally you'd just be adding to to a table! Even if it's normally a weird practice, keeping more at a higher scope than immediately necessarily keeps a lot more options open. 

- In general, try to keep functions smaller. That's a good practice in general, but if TradeCommand had a "buildHeader," "buildSliderRect," "buildAssessmentBlock," etc. instead of everything being flat inside of buildUI, it's be possible for mods to change things with much less collateral damage.

 

You read this? Well, thanks! I really do appreciate the work that's gone in.

Link to comment
Share on other sites

2 answers to this suggestion

Recommended Posts

  • 0

For sure don't want too much performance-sensitive stuff in the lua layer -- what I mean by all this is for what is in the lua layer to be more modding-friendly.

Concrete example I'm hitting right now: I want to experiment with making Trade available to non-merchants. That's all in the lua layer: tradecommand.lua. Should be easy, right? It's just a couple of "if not captain:hasClass(CaptainClass.Merchant) then return end" checks.

But oh. Oh. That call's an early abort right at the beginning of the 200-line onAreaAnalysisFinished, and it's done with a ShipDatabaseEntry computed from the metadata used for everything else. Hmm, there are normally some tricks...

Tricky approach 1: temporarily replace the "has" function to always return true, or at least for Merchant -- but unfortunately, that's not at the lua layer and not writable. So no can do with replacing it.

Tricky approach 2: make a fake captain, swap things out, run the needed steps, then swap back. ...Except, despite appearing like it should work, :setCaptain on ShipDataBaseEntry:getCrew() doesn't appear to do anything. Entity():setCaptain works, but captain commands are all about not having the entities available.

That leaves blunt instrument #3: copy and paste the entire function just so I can comment out the two lines that check the class. And now it's all but guaranteed to be broken within a few patches, and all but guaranteed to conflict with any other mods wanting to touch the command.

The pattern then repeats for two more 100+ line functions in the file, with the same comment of two lines. "Modding" TradeCommand to remove merchant restriction boils down to replacing 2/3 of the file in its entirety despite the change really being six lines of code. (I'm exaggerating a little bit, but not that much)

 

That's what I mean about the opportunity with lua moddability -- just making structure more bite-sized for palatable change sizes.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...