beyond-all-reason / beyond-all-reason/RecoilEngine
SetHeightMapFunc should allow synced Lua to modify terrain when mapDamage is disabled
- Dominant language
- C++
- Stars
- 679
- Forks
- 290
- Avg merge
- 3d 2h
- Merged PRs (30d)
- 40
Description
### Problem
`Spring.SetHeightMapFunc()` silently returns `0` (nil in Lua) and never executes its callback when `mapDamage->Disabled()` is true — i.e. when the `disablemapdamage` modoption is enabled or the map has `notDeformable` set.
This makes it impossible for synced Lua gadgets to perform any heightmap modification on such maps, even with cheats enabled. The same guard blocks all related APIs: `LevelHeightMap`, `AdjustHeightMap`, `RevertHeightMap`, `SetOriginalHeightMapFunc`, etc.
### Relevant code
[`rts/Lua/LuaSyncedCtrl.cpp` — `SetHeightMapFunc`](https://github.com/beyond-all-reason/RecoilEngine/blob/master/rts/Lua/LuaSyncedCtrl.cpp):
```cpp
int LuaSyncedCtrl::SetHeightMapFunc(lua_State* L)
{
if (mapDamage->Disabled()) {
return 0; // silently refuses, Lua sees nil
}
// ...
}
```
The same pattern exists in `LevelHeightMap`, `AdjustHeightMap`, `RevertHeightMap`, `LevelOriginalHeightMap`, `AdjustOriginalHeightMap`, `RevertOriginalHeightMap`, and `SetOriginalHeightMapFunc`.
### Use case
BAR is developing several synced Lua gadgets that modify terrain via `SetHeightMapFunc` (not yet merged):
- **Terraform Brush** (cmd_terraform_brush.lua) — interactive terrain sculpting tool (raise, lower, level, smooth, noise)
- **Clone Tool** (cmd_clone_tool.lua) — copy/paste terrain sections
- **Dev Helpers** (cmd_dev_helpers.lua) — `/invertmap`, `/flatten`, etc.
- **Water Level** (map_waterlevel.lua) — adjusts terrain for water level changes
All of these are gated behind `/cheat` or similar authorization checks. None of them work on maps with `disablemapdamage` enabled or `notDeformable` maps, and there is no Lua API to override this at runtime.
These dev tools are being developed with the intent to contribute them upstream to Recoil as part of its standard dev/editor tooling, making them available to all Recoil-based games — not just BAR. Resolving this engine-level restriction would ensure they work reliably across all map configurations, which is essential for general-purpose editor tools that ship with the engine.
### Proposal
The `disablemapdamage` modoption's intent is to prevent **weapon explosions** from deforming the map during normal gameplay. It should not prevent **explicit synced Lua API calls** from modifying the heightmap, since those are already developer/cheat-gated.
**Option A** (minimal): Skip the `mapDamage->Disabled()` check in `SetHeightMapFunc` and `SetOriginalHeightMapFunc` only, since these are explicit programmatic calls (not explosion-driven damage). The `RecalcArea` call at the end would need to work on `CDummyMapDamage` or be called on `readMap` directly.
**Option B** (broader): Skip the check in all synced Lua heightmap APIs (`LevelHeightMap`, `AdjustHeightMap`, `RevertHeightMap`, `SetHeightMapFunc`, and their Original/SmoothMesh variants). These are all explicit Lua calls, not engine-driven explosion damage.
**Option C** (runtime toggle): Expose a `Spring.SetMapDamageDisabled(bool)` synced API so gadgets can enable/disable map damage programmatically, allowing full control.
In all cases, `CDummyMapDamage::RecalcArea` would need to either forward to the actual path recalculation or the Lua functions would need to handle recalc themselves.
### Environment
- Engine: RecoilEngine (BAR fork)
- Affected APIs: `SetHeightMapFunc`, `SetOriginalHeightMapFunc`, `LevelHeightMap`, `AdjustHeightMap`, `RevertHeightMap`, and their Original/SmoothMesh variants
Contributor guide
Research direction
Start in rts/Lua/LuaSyncedCtrl.cpp and trace the mapDamage->Disabled() guards in SetHeightMapFunc, SetOriginalHeightMapFunc, and the related heightmap APIs. Inspect CDummyMapDamage::RecalcArea and determine which proposal is appropriate; done means the selected synced Lua calls work with disabled map damage while preserving the intended behavior for weapon-driven deformation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, lua
- Domain
- api, game-dev
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100