How to prototype BAR mods that use buildoptions and UnitDefs
When building nontrivial Beyond All Reason mods, figuring out where to hook buildoptions into UnitDefs without hitting load-order nulls is the real challenge. UnitDefs is not fully populated early in the game load cycle. Here is what works in practice.
Tags: BAR modding, prototype mods, buildoptions, unitdefs, lua gadgets, spring engine
UnitDefs load timing matters
If you try to access UnitDefs from a loaded gadget too early, the table is relatively empty. Unit definitions do not fully populate until later in the game initialization. Attempting to manipulate buildoptions at that point returns nil or incomplete data. The fix is to delay your unitdef work until after the game confirms all units are loaded. Use a gadget that hooks into gameStart instead of loaded.
Swapping buildoptions entries
To replace a build option on a specific unit, target UnitDefNames by name rather than relying on numeric indices in UnitDefs. The pattern looks like this:
UnitDefNames["armconsul"].buildoptions lets you access and modify the build menu entries for that unit. Direct assignment into a buildoptions slot works but you must check the slot exists first. Trying UnitDefNames["armconsul"].buildoptions[19] = "armzeus" will replace the entry at index 19 if that slot is defined. If the buildoptions table is shorter than your target index, you get a silent nil write.
Stripping and reassigning build pools
When redistributing build options across unit pools, collect everything into a temporary table first. Loop through each pool, extract every buildoptions entry into a shared list, nil out the originals, then redistribute from the pooled list. This prevents orphaned build options when you remove units from faction equivalents. Always check that bo exists and has length before iterating with pairs or ipairs.
The Spring RTS Lua_UnitDefs wiki
The Spring RTS wiki maintains a Lua_UnitDefs reference page that lists standard fields available on unit definitions. BAR uses the Spring engine, so most of those fields apply. Keep that page open when modding. It covers maxdamage, buildCostMetal, buildCostEnergy, and the other core definition properties you will reference constantly. Field names in the raw unitdef files match what the wiki documents.
Debugging actual errors
When a buildoptions modification crashes, Spring does not always surface the error cleanly at the point of failure. Wrap your unitdef changes in protected calls and print the actual error message when something goes wrong. A minimal test loop that targets a single unit and a single buildoption slot isolates the problem fast.
Creed of Champions
The modding side of Beyond All Reason is where a lot of players develop their deepest understanding of the game. Creed of Champions values that kind of patient learning. People here help each other debug without the gatekeeping that makes other communities exhausting. If you are building something for BAR and want teammates who actually give useful feedback, look us up.
[Crd] Having a space like here that offers a community, trainings, events, and the guarantee to not be judged or insulted by fellow members is really precious. Keeping the game safe, and more importantly, fun.