How To Create Active Aero (cont.)
here comes the really fun part
To this point you should now know how to manipulate the .jbeam in order to move and scale your fixtures, and to change the mesh to allow your structure to move the way you want them to. You should also know how to install hydro
beams.
Between the last section and now I went back and changed the exported mesh a few times. Unfortunately I haven’t worked out how to re-export without having to make all of your .jbeam edits from scratch (very painful), so for now just be very very very sure you are not going to change any of your fixtures before you commit!
I’ve now updated all of the wings, supports and hydros.
You can see here that for the time being I consider the front two flaps to be too precariously positioned to actually take much downforce, so I’ve elected to keep my invisible wing hidden in the middle of the car as the one with collision triangles
, and the front two flaps will operate, but they’re cosmetic.
So with that, onto the next part:
6a. Defining your Vehicle Specific Binding
If you do not want to add any kind of DRS or manual switch/control over your active aero and just leave the whole thing automated, you can ignore this step
A Vehicle Specific Binding is a control which manipulates something, well, specific to your vehicle. That is to say you can bind a control to something special that you’ve programmed to work for this entity alone. In this case, that’ll be the DRS button, as the intention is to make these flaps work such that while DRS is active, the drag is reduced to a minimum. Furthermore I want to be able to turn it on, and off, but also to have it turn off automatically or not turn on at all if a certain set of conditions is not met. For that, I will have to create a .lua file to program the part. That will come later.
For now, start by reading the BeamNG documentation on Vehicle Specific Bindings. It covers everything in enough detail.
So now that you’ve done that, you should then have a file called input_actions
in the mod folder with all the .jbeam files:
(This file is called input_actions.json
)
And in it all you really need is something like this:
{ "drs":{"order": 1, "onUp":"electrics.values.drs = 1-(electrics.values.drs or 0)", "title": "DRS", "desc": "Toggles DRS" } }
order
: the order in which the commands come, which is useful if you have lists of commands for multiple various controller inputs. I’ve only got one command, so this is kind of superfluous
onUp
: the command is triggered when the relevant button is lifted. Which in this case means you can press and hold it and it won’t trigger, but when you release the button it’ll trigger.
electrics.values.drs
is a custom electrics
input I’ve designated for this command. At this point you’re going to want to read up on Streams. In short, these are the values that reflect the state of a component or characteristic of the vehicle. That is to say that this is all of the data of what the vehicle is doing that Beam has, and that determines how it behaves and interacts with its environment. You can also manipulate this information or use it to manipulate other things, which is exactly what I plan to do later. As said before, electrics.values.drs
is a custom value that will be manipulated by the .lua I will write.
The reason I’ve written the code the way it has been written above is because the same button turns ON and OFF (or between 0 and 1), but this one line covers both scenarios regardless of whether the state is ON or OFF. It’s especially important that I do it this way because the .lua program I’m going to use also has the power to switch DRS OFF (to 0), so I don’t want to confuse the system by having it try to turn the DRS OFF when the system already turned it OFF for me. This way, if I turn DRS ON and then my .lua script turns it OFF, if I hit the button again it’ll just try to turn it back ON.
Once you’ve done that you also need to create a file that sets a default binding for your Vehicle Specific Binding. This is so any user that uses your mod can then find that binding and change it to their liking.
So once you’ve made your input_actions.json
file, just open Beam, and set your binding. It should turn up in this menu:
ta-daaaaaaaaaaah
Once you’ve set your input, a temp .diff file will be created in a different folder (read the documentation to find out where). You rename it .json and move it into this folder:
Like so:
c29b046d is Beam’s designation for my Logitech G27
Then, when you open the file again, the vehicle specific binding will appear briefly in the top-right corner of the screen:
Only the Keyboard binding appears here because I don’t have my G27 connected
6b. Programming your Wings
This is the most fun part, as it’s where you take all the parts you’ve crafted up to now, and you write a series of logical expressions and you get those parts to do things. In the scheme of things making some flaps move up and down is pretty simple but the advantage of working with simple systems is that you can achieve complex things with their behaviour.
To prime yourself for this, you should familiarise yourself with .lua unless you already know how to code.
First, take a look at your car.jbeam file. Near the top is a subsection called "controller"
Now, create a folder called lua
(location shown below), and within it a subfolder called, you guessed it, controller
Here’s where you put your .lua files. Which should be named the same as what you specified in the .jbeam.
Make sure that you specify they are .lua files though, I once spent a good half an hour trying to figure out why my programming wasn’t doing anything before I realised I forgot to change the suffix!
At this point it’s probably a good idea to take a look at the file from the vanilla Beam car, the SBR, which you can find in Steam\steamapps\common\BeamNG.drive\content\vehicles
(depending on your root tree). You can also examine the .lua files of other mods for ideas, as some of them do all kinds of things with functions that pull math from places I don’t understand, change your UI, fly planes, fire missiles… but for now, just look at the SBR’s file.
I honestly still don’t know what some of these lines do. I have no idea what M.type
or M.relevantDevice
means. What I can say is that this file is divided into a few sections. The first section is about defining various variables. When you get to the line local function init{}
that is the line that initiates the code affecting behaviour. In this case it’s telling the spoiler to start at 0.
As you can see here, electrics.values.spoiler
is actually a custom electrics stream. spoiler
here is in fact the "inputSource"
that you specified for the hydros
, so make sure the names match up or it won’t input anything.
I’m not going to go into all the details of how the .lua logic works (some of it isn’t that intuitive but a lot of it is). If you can’t learn off this much you’ll probably struggle to make stuff of your own, and it’ll take me quite a long time to explain it all. If you want to see how I ruminated and struggled through it myself just look up a bit. Just know that you can pull values from the various streams and feed them into other streams, and that you can use math. And that for every if
there should be a then
and an end
(elseif
and else
optional depending on how many conditions you want, but if there is more than 1 alternative condition you need to use an elseif
, and the else
is the final alternative condition).
The really important thing about .lua is that you can nest if/elseif/else conditions within other if/elseif/else conditions. This is what makes using multiple sets of logical operations possible: hence how it’s possible to make a DRS logic and an automated wing logic at the same time.
Document what you do using the --
, this comments out the rest of your line in .lua. Otherwise you may forget what you were trying to do and since the code can get complex easily you can get lost.
7. Troubleshooting
This is the really annoying part. Chances are things are going to be really buggy. Chances are some beams are going to break, or you missed a tiny little detail. You’ll have to go over every step methodically to find where your error was. Common causes for things not working include:
- Syntax errors (the entire mod will not work if there is even one syntax error)
- “Beam reversal” where under force some beams flip around due to the geometry of the mesh or insufficient rigidity. This requires a lot of playing around with nodes, beams, nodeweights and beam spring. Just remember not to make the nodes too light for your mesh. The heavier the node, the more spring the beams it anchors will tolerate.
- The mod loads but the wings don’t do anything: probably an input mismatch. Check that your controller slot is appropriately named, your controller files are .lua, and that your input sources match
- The mod works and the hydros activate but the car’s handling sucks: you’re on your own. Work it out!
At the end of this all you might just end up having functional wings. It took me a few weeks to get this sorted from scratch and that’s only because I was absolutely determined to get this done. As for the result, well, you’re just gonna have to wait until the next Car Collectors Auction for a chance to get your hands on it, heh heh heh. If you don’t wanna wait that long, then learn how to do your own!