Transport Fever 2

Transport Fever 2

Create your own game world!
Give your game a personal touch and change it to your liking. Create, share and install mods. Customize the game with new landscapes, vehicles, stations, assets and more.
RadiKyle 6 24 May, 2024 @ 11:42am
Script command to check if a specific mod is active?
Hey all, I need a postRunFn lua command to check if a specific mod is active in a game. My searches are coming up empty. How can I do this?

The mod in question doesn't create any resources so I can't use the usual workaround of scanning resource tables.

I see the console / stdout echo a list of active mods when a savegame is loaded. Is there a command to access that list?

Thanks!
< >
Showing 1-15 of 29 comments
lollus 15 29 May, 2024 @ 3:26pm 
Not if the mod has no parameters! If it does, you can read "params" of postRunFn(settings, params).
RadiKyle 6 29 May, 2024 @ 4:50pm 
Yeah it's no unfortunately. On another site I learned that this particular mod isn't detectable by any of the limited methods we have in the API (which are already just workarounds). The game really needs an option for checking the list of active mods.

So instead I had to completely redo my .mtl definitions to be compatible with this particular mod that renders things incorrectly, because I have to assume that it's active.
lollus 15 29 May, 2024 @ 5:33pm 
Why don't you share your mod on github?
doug 29 29 May, 2024 @ 5:57pm 
It's Enzo's Shader mod that you're looking to detect, is it not?
RadiKyle 6 29 May, 2024 @ 6:03pm 
Originally posted by lollus:
Why don't you share your mod on github?

Both are already in the Workshop now.


Originally posted by doug:
It's Enzo's Shader mod that you're looking to detect, is it not?

Hi @Doug , yeah that's the one. It's all .fs scripts. Its mod.lua does set a shader flag, but it seems it's legacy as it's not an available parameter in the game. (And in any case wouldn't tell me *which* shader mod is loaded if there were more than one.)
doug 29 29 May, 2024 @ 6:11pm 
I don't think the flag is legacy - it's his own that he's using with his other mods.
However, it is detectable in the resource modifier functions, so...
Make a copy of one of the stock vehicle model files.
Rename it to menu_shader_signal.mdl, or some such. Just include the "menu" so that my Unlock Multiple Units mod will leave it alone.
Set the availability dates to yearFrom = 1 and yearTo = 2, so that it doesn't ever show up in the purchase menu.
Now, add a model resource modifier to your mod. Use it to check for your model file.
When that model file comes through the modifier, set
data.metadata.transportVehicles.multipleUnitOnly to the value of game.config.shaderMod
In postRunFn, you can pull that model file from the model repository and check the value of the multipleUnitOnly flag. You will now know whether the shader mod is loaded.
Last edited by doug; 29 May, 2024 @ 6:12pm
RadiKyle 6 29 May, 2024 @ 6:26pm 
Interesting... I tried using that flag before but only got errors. I'm trying to understand the nuance here (I'm brand new to all this)... Why can't I check the flag directly in my postRunFn, yet I can access it to set some random flag of a model equal to it? Is it some kind context thing, that it's inaccessible in postRunFn as a parameter? Where is it actually stored? Like can I check it in-game in console? (I tried before but had no luck.)

I need to check the wiki to learn about "resource modifiers"...
doug 29 29 May, 2024 @ 6:43pm 
runFn and postRunFn run in separate lua states.
https://transportfever2.com/wiki/api-testing/topics/states.md.html
They don't talk to each other much - not at all really, so you need to work around this issue, hence the hijacking of a convenient boolean variable in a dummy model file.
So yes, context is the issue.
Once the various models have been loaded into the repository, all of the non-canonical information that might have been included in the metadata has been removed, so you can't just make up some random metadata key to move information like this into the postRunFn.
There is a sample modifier function in the wiki. It checks the metadata for (I think) steam locomotives.
You will be checking the fileName parameter for the name of your model file.
You will be using string.find - have a look at Early Start. It does some of that.
RadiKyle 6 29 May, 2024 @ 6:45pm 
Okay read up on resource modifiers (again)... Sounds like it's got to be in the runFn. The other mod also sets their flag in the runFn, so I thought that meant it's not available to my mod until postRunFn?

Is the runFn basically a queue where all the mods commands are submitted, then they're all run collectively as a batch, values can be shared/influence each other, and only the results of all that is available in the resource tables via posRunFn? How does it ensure that their flag is set before my resource modifier checks it?

Maybe I'm just asking stuff I don't need to know, just trying to understand it.

Edit: whups simul-post, just reading your reply now...
Last edited by RadiKyle; 29 May, 2024 @ 6:46pm
RadiKyle 6 29 May, 2024 @ 6:59pm 
Ok I think I get the workaround now. Basically use the throwaway model ( __ key in lua-speak lol) as a payload carrier, then check it in postRunFn to confirm that yup that unibrow baby is outside again, then I can do what I was trying to do with loading the suitable .mtl defs so my stuff renders as intended (mostly).

How it processes the all the parallelized runFns to ensure that their flag has actually been set before mine wants to read it is still confusion for me..., it sounds like it's a recursive process.
doug 29 29 May, 2024 @ 7:19pm 
The runFn for each mod is executed - in the order the mods were loaded in.
This is where the modifier functions are set up, but not where they actually run.
So, in the case at hand, that flag - game.config.shaderMod, has been set before any of the modifier functions have actually been called.
Now, all the resources are loaded, and handed to the resource modifiers, again, in the order those modifiers were themselves loaded. Once all those functions have been called, and the related modifications made, the modified files are loaded into the repositories, for use in postRunFn and the scripting API,
doug 29 29 May, 2024 @ 7:23pm 
In your model modifier function, you can actually edit the lods tree, as well as the metadata, so depending on the value of the flag, you could just set the models to use the material files of choice, rather than messing with the postRunFn.
The function 'data' that you see in the model file is the same 'data' that is being passed in to the modifier function. Anything in the model file can be accessed in the model modifier function.
RadiKyle 6 29 May, 2024 @ 8:25pm 
Many thanks for the description!

Ok so I built a test and got the flag info carried thru. However it didn't show up quite where I hoped it would be...

I had to choose which api.res table to poll in the postRunFn, so I chose the multipleUnitRep since we're playing with that element and that table is likely infinitely shorter to search than the insane modelRep table. But even tho the MU flag got set (because shader mod is loaded too), my fake model didn't appear in the MMU list. So there must be other reqts for a model to land in that table.

So instead I putted around in console and found my fake model as #4033 🙄 of the massive modelRep table (and that's just vanilla with only 2 mods loaded...).


As I've been learning all this modding stuff and seeing all these workarounds in postRunFn, I'm seriously wondering just how much of the savegame load time is because of all the costly recursive string if-then checks that mods are running.


I'll give your great idea to select the .mtl files directly in runFn some thought... I think it'll depend on the case. I have one mod that builds a long list of new dynamic resources (railroad crossings) from all loaded mods, so I think I'm stuck with postRunFn for that one. My other one doesn't, but it also checks for the presence of resources created by another mod, so I think I might still be tied to postRunFn for that one too, but I'll give it a check. I feel I might be safer staying in postRunFn tho, because I don't know what all the other mods are doing... (that's actually how I discovered your 1800s unmarked railroad crossing I didn't know was there lol)
RadiKyle 6 30 May, 2024 @ 3:29pm 
So now I'm wrestling with what happens to existing savegames if a user changes their use of the shader mod (turns it off or on) after my mod is on their map. My mod will specify a different set of .mtl files (and/or possibly .mdl files) than are already on the map, and I'm not sure everything will auto-update properly when the map is reloaded.

I started a new thread on what filenames be safely changed in a mod update, since it's a much broader topic than this one about detecting other mods. But my immediate example is still this same one.

I'm starting to test putting conditional code into the .mtl / .mdl files just to avoid dealing with 2 set of filenames that might break a savegame. It seems to work, but it departs from the "standard" .mtl / .mdl file contents.
RadiKyle 6 1 Jun, 2024 @ 2:14pm 
So I tried the suggestion to modify the models directly in the RunFn (instead of postRunFn) but cannot get it to work. I can't get any conditionals based on game.config.shaderMod (being true if loaded) to work, the code blows right past it as if it were false.

The code is simply:
if game.config.shaderMod then addModifier( "loadTrack", shaderModSupport ) end

but it won't call the addModifier. (Also tried it with if...== true, but no difference)

I've no idea what I'm doing wrong.

So I can only get the postRunFn method to work instead.

Edit: It also seems there is no way to modify an .mtl file contents, either by addModifier or api.res calls, because Materials are not one of the available categories. So Models/.mdl are as "low" as I can go down the resource tree.
Last edited by RadiKyle; 1 Jun, 2024 @ 2:17pm
< >
Showing 1-15 of 29 comments
Per page: 1530 50