Tweakdefs let you modify unit definitions directly from the lobby, but a single typo or missing subtable will throw errors and kill your mod before the game even starts. Here is what works and what trips up new modders.
Tags: beyond all reason, tweakdefs, modding, lua, beginners guide, unit tweaks
Tweakdefs apply changes to unit definitions at lobby time through a base64-encoded string you paste into the lobby settings. If you want to change a unit's metal cost, add a build option, or alter a custom parameter, tweakdefs is usually the fastest path.
There are two related systems:
Both let you modify existing units without touching the main game files.
Most tweakdefs failures come down to two things.
The first is base64 encoding issues. The popular site base64encode.org ships results using a character set that BAR may not parse correctly. If your code looks right but the lobby rejects it, switch to base64encode.net instead. Many modders in the community have found that the default settings on certain encoders introduce characters that Spring interprets as invalid commands.
The second is unitrestricted comparisons. You cannot use greater-than or less-than operators in tweakdef expressions. Something like unit.radardistancejam > 0 will silently fail. Tweakdefs do not support conditional comparisons of that type.
When you write a new tweakdef, BAR expects certain subtables to exist. If you try to set a value inside a subtable that does not already exist on a unit, the definition fails silently.
The key subtables are:
unit.buildoptions — the list of units a factory can buildunit.customparams — custom parameters used by gadgetsunit.weapondefs and unit.weapons — weapon configurationFor buildoptions specifically, tweakunits requires you to write the entire list or modify a specific slot by index. You cannot simply append to it. Tweakdefs handle this differently and can add entries with the pattern unit.buildoptions[#unit.buildoptions + 1] = "unitname".
When a tweakdef fails, open the infolog and search for "error". BAR usually logs a nil reference or an invalid command line. The most common pattern is a missing subtable that the code tried to write into.
Check for Nil errors specifically. These typically mean you referenced a property the unit does not have defined. Some unitdefs simply do not list fields like metalcost explicitly, even though the unit has a metal cost. Loop through all units with for name, ud in pairs(UnitDefs) do and check whether the field exists before modifying it.
To disable the Arm Lichet T4 and Core Crawltide T4 using tweakdefs:
{
armlichet4: { unitrestricted: 1 },
corcwt4: { unitrestricted: 1 }
}
Encode that as base64 using a compatible encoder, paste it into the lobby tweakdef field, and those units disappear from their build lists without touching any game files.
The Spring RTS wiki hosts the authoritative reference:
The BAR repository on GitHub also contains working examples in the luaui/Widgets/ directory. Reading existing widgets gives you a much better feel for how the API actually behaves than any standalone tutorial.
Modding takes patience. The players who get good at it spend time reading existing code, testing small changes, and checking the infolog after every tweak. That kind of methodical approach is exactly what we value in Creed of Champions too. We play with discipline, we learn from each other, and we keep drama out of the lobby.
[Crd] The removal of toxicity, the goal of fun and learning, makes for a refreshing spot to play and spend time. It has also made a game with plenty of complexity a bit less daunting to dive into.
If you want teammates who actually enjoy the process of figuring things out together, look us up.