[pull] master from beyond-all-reason:master - #216
Merged
Merged
Conversation
**Player Facing Summary** - After 15 minutes into the game, zombies will swarm all teams evenly once they reach 10% of the value of all players combined. - Zombies spawn with XP skewed to the minimum veterancy. - When zombie revive timer has been reset, a purple poof now appears above it. - Units that don't leave corpses like the Fiend will no longer respawn as zombies. - Zombie constructors get a boosted capture range of a minimum of 300. This makes them capable of capturing aircraft. - Zombies now can control aircraft when they're captured or produced. Zombie ai is now moved into its own gadget because it was getting too confusing to have it all in one place. **AI Rework** - reworked the zombie ai to have a persistent move goal that it remembers and falls back to when it's done fighting things. Changes when it gets stuck or some conditions change - zombie aggro is distributed fairly. All zombies are ranked by most to least powerful then random-sequentially picked for all alive allyTeams. - when aggro'd, zombies will move towards a random target's position belonging to the aggro'd allyteam. It'll change targets when it gets close enough. - aggro behavior triggers when zombies have 10% of the value of what all the players combined have. This is to force a desparate survival endgame. This can only happen after 15 minutes **Other Changes** - Zombies will now have a drastically lower chance of spawning with max veterency. It's now biased using disadvantage mechanics (like from DnD) to select the lowest of a few randomly generated numbers between 0.0-1.5. - there's now a little purple "poof" that emits above a corpse after its timer has been reset by reclaiming or resurrecting it a little bit. - fiends will no longer resurrect - constructors now have at least 300 range as zombies. This makes them capable of potentially capturing aircraft. oh yeah, - aircraft can now become zombies and can be controlled as zombies. They'll fly around fighting things. LLM Disclosure: Used Cursor's Grok 4.6, Cursor's auto mode, Fable 5.1 a bit, GPT 5.6 a bit. The AI did what I told it, I tested and reviewed code as I went. I did a final pass checking for hallucinatory stuff and it seemed alright and human readable to me.
…box (#9087) Branch: `tf-brush-improvements-14` Continues the Terraform Brush work. Two threads this time. The first is the campaign terrain tutorial MrBob recorded for the art team: watching a whole map get sculpted with one brush highlighted some potential improvements in handing brush strokes. The second is a batch of asks from using the editor on actual maps: soft influence bands for texturing, sun presets that survive a project load, an Open Project browser that copes with a cloned maps repository, and editor sessions that stop spawning commanders into the canvas. ## Features **FOLLOW STROKE.** A chip in SHAPE turns the brush shape to the direction you are dragging, so a square, hexagon or triangle leaves a ribbon with its flat sides along the path instead of a chain of same-angle stamps. The angle is smoothed over the last few dabs so mouse jitter cannot spin the shape, and quantised to 2 degrees, the step the brush's own falloff cache keys on. The protractor snaps it to the spoke grid when both are on, the brush ring shows the angle that will land, and your own rotation comes back when the stroke ends. Offered for the sculpt modes only: the other tools sharing the SHAPE row stamp rather than stroke. A **CLAY SCULPT** preset ships the whole setup MrBob makes a map with: clay on, intensity at the floor, the sharpest falloff, square with FOLLOW. **PASSABILITY overlay.** Every DISPLAY row gains a chip that tints ground steeper than a move class in the engine's impassable purple, so cliff height can be judged while sculpting without selecting a unit and pressing F6. Clicking cycles BOT, VEH, HOVER, AMPH and off, and the slopes are read off those units' real movedefs so the band matches what F6 draws. Needs the tileset shader. **INFLUENCE bands in SURFACE and LAYERS.** An altitude band and a slope band, each with a feather, that scale a stroke instead of cutting it the way the FILTERS do, so a texture does more of its thing in the lowlands or on the flats and fades out beyond them. SURFACE remembers a profile per texture (it follows the texture across slots and biome swaps, projects keep it in `surface.lua`, and Copy to all stamps it onto every slot); LAYERS keeps one per channel. Erasing is never scaled, and the Ctrl sneak peek shows the band, so what you see is what lands. **SURFACE SCATTER.** Position, size and strength jitter per stamp, on top of SPACING. With spacing near one and a half brush widths, one drag lays the hand-placed dot field the texturing pass wants instead of a solid band. The DOT preset now carries a generous falloff and the scatter, which is the texturing brush from the tutorial: dots with gaps, never fills. **Sun & Shadows PRESETS.** Three sun-only times of day (Canonical, Dusk, Overcast: direction, intensity, sun colours and shadow densities, nothing else), the harvested map moods the New Map wizard offers, and your own saved files. Save writes the whole live environment under a name to `Terraform Brush/Environments/`, so a look carries to every map and session; a SUN ONLY / FULL ENVIRONMENT switch decides what a click applies. The sun direction also gains AZIMUTH and ELEVATION sliders next to the vector rows. **Open Project browser.** A search box (matching the name, the folder path or the NxN size), RECENT / NAME / SIZE sort chips and a folder tree. Projects may live in subfolders of `MapProjects/` up to four levels deep, and a name may contain "/" to save into one, so a git clone of a maps repository placed inside `MapProjects/` lists as it is on disk and pulls straight into the browser. The date column reads as an age, and a project saved this session lists even while the engine's folder snapshot cannot see it yet. **AUTOMATIC DEPOSIT.** A SURFACE variant slot the shader claims on its own where wind-blown sand would gather: on the lee side of slopes relative to a wind direction, and in the pockets the intermediary already reads. It only fills ground no stroke claimed, so paint wins, cliffs stay clean, and it is off until a slot is chosen. **METAL SPOTS glow controls and BAND WIDTH.** The glow light gets the LIGHTS tool's point-light controls (intensity, radius, height, colour swatches with a preview bar and RGB sliders), graying out while the glow is off. BAND WIDTH sets how far the silhouette band, the rubble skirt Band layer and Band tone shape, reaches around a spot. Also: per-texture SELECTED SLOT tints in SURFACE > GRADING, SURFACE palette captions that name each texture's role (TINT, NORMAL and so on), `/tf_sunlog` for finding what reset a sun. ## Focus mode An eye button next to the pause button in the panel header. It hides the game interface the way F5 does but leaves the editor alive: the panel, the brush ring, the grid and water overlays and skybox switching all keep working, so a map can be looked at, sculpted and screenshotted without the HUD. RmlUi documents are rendered by the engine outside the hidden-interface gate, so the panel survives on its own; the brush widget reads the focus flag to keep drawing its overlays, and the flag is set with the explicit `hideinterface 1` / `0` forms so it cannot desync from F5. Skybox picks used to wait for the HUD to come back: the widget handler skips `DrawScreen` while the interface is hidden, and that was the one draw call-in the pending skybox apply lived in. The panel's deferred applies (skybox, New Map environment preset, fog-off, forcestart) now drain from `DrawScreenPost`, and the same audit moved two more jobs that would have stalled the same way: the brush widget's heightmap import and export and New Map drive, and the map project widget's Save / Open driver. Exits: the button, closing the panel or deactivating every tool, a `/luaui reload`, and F5 from outside all hand the interface back. Hiding the panel with its hotkey does not, so focus plus a hidden panel is the clean-screenshot setup. A map capture started in focus mode still comes out clean and leaves the interface hidden afterwards. ## Editor auto-open on New Map and Open Project A New Map and an opened project bring the Terraformer up by themselves: the brush arms in RAISE the moment the canvas is playable, at the New Map's forcestart and at the end of a project's load phases, unless a tool is already up. A plain `/luaui reload` on a running canvas does not trigger it. ## WORLDSPACE TINT (WIP) A new section in the Tileset window (after BIOME TINT) that makes world-height tinting one system with a wide look range, from the old three-colour grade to a layered canyon. One shared AXIS feeds every lever: Auto rides the map's height reference, so a flat canvas stays untinted; Manual pins it to elmos and can be tilted along a direction and wobbled. GRADE is the old three stops as colour chips with a movable split. STRATA lays repeating tint beds along the axis (one to eight, period, phase, hardness from a soft crossfade to a knife edge, wobble, per-bed jitter), with BASE / INTER / CLIFF / PLAT chips choosing which layers take them and a colour chip per bed. GRADIENT STOPS is MrBob's ask from Discord: an array of two to eight hue / saturation / value entries spread evenly over the height, in Multiply or Colorize mode. RAMP samples a painted gradient image along the axis (a PNG from `Terraform Brush/Ramps/`, picked from a file list with Rescan / Clear) in Multiply or Tint mode, with a strength and a repeat count. SATURATION scales colour from base to top, TIDE RINGS darkens rings above the waterline, and SNOW LINE whitens the tops above a height with a band, a slope limit and its own colour. Every colour chip (grade stops, beds, gradient stops, snow) selects what one shared COLOUR editor edits: the swatch palette, a preview bar, and Red / Green / Blue plus Hue / Sat / Value sliders that work for every chip whichever way it is stored, so a bed can be dialled in HSV and a stop picked from the RGB palette. Each sub-group has its own RESET and the header RESET takes them all. The chips are painted from the knob table, so a preset, a project load or a console `/tileset set` lands in the UI. The ramp file is saved with the project in `tileset.lua` next to the biome key and applied on Open. Needs the tileset shader (0.27); with the shipped defaults a map renders exactly as before. The section is marked WIP in the panel: it will get more work in a later release. ## IMAGE overlay Every DISPLAY row gains an IMAGE chip: lay a reference image over the whole map, a real coastline to sculpt against or a transparent sheet of guide lines, and paint over it. Images are read from `Terraform Brush/Overlays/` (PNG, JPG, TGA, BMP or DDS; alpha is kept, so only the lines of a transparent sheet show). The gear next to the chip, or a right click on it, opens the shared IMAGE OVERLAY window: the file list and the placement controls, OPACITY, OFFSET X / Y and SCALE sliders that preview live on the ground while you drag, STRETCH or KEEP ASPECT, FLIP H / V and RESET; a left click on the chip toggles the overlay once an image is loaded. The image is projected onto the ground through the map's depth buffer, so it hugs every slope at any map size for one fullscreen pass, and units and features draw over it (it needs `AllowDeferredMapRendering`, the BAR default). The pick and placement survive a reload; `/tfimage <file>` picks a file from the console, `/tfimage` alone toggles it, `/tfimage off` unloads it. New files: `luaui/Widgets/cmd_terraform_image_overlay.lua` and the two `luaui/Shaders/terraform_image_overlay.*.glsl`. ## Sculpt performance huskyvoiceyui and Moose reported 10 to 15 fps lost while dragging the clay brush on a big map, closer to 8 fps with FOLLOW STROKE on a square brush, and concentric rings on every clay stroke. Four things were behind it. The gadget committed one `SetHeightMapFunc` and one undo entry per dab, up to 48 a tick on footprints overlapping about 85 %, so the engine recalculated the terrain (mip heightmaps, normals, slopes, pathing, LOS, the normal and shading textures, mesh patches) up to 48 times a tick. The falloff-stamp cache keyed the rotation-invariant circle on angle and held four entries, so FOLLOW STROKE, whose angle changes every dab, rebuilt a stamp per dab. The widget forced a mesh re-tessellation for ten frames after every tick, which at 20 Hz is every frame of a drag. And the panel mirrored terraform state at frame rate with about fifty unguarded data-model writes and nineteen raw slider writes. - **A tick's dabs apply as one batch.** The dabs of a `$terraform_stroke$` message work against a copy of the cells they touch and the tick commits once: one heightmap write, one undo entry. Dab k still sees dab k-1's writes. A stub-engine harness fed both versions the same strokes: heightmaps identical to float noise, engine recalcs and undo entries per stroke down 6x, Lua time down about 3x, undoing a stroke 4x faster. - **Stamp cache.** Circle and ring are keyed angle-free, the cache holds stamps by a 3M-cell budget instead of four slots, and only very large shaped stamps quantise the angle coarser (2 degrees up to 40k cells, up to 30 degrees beyond), so a FOLLOW drag at big radius cannot rebuild a 100k-cell stamp per dab. - **Mesh refresh** is armed for two frames from the engine's own heightmap-update event, i.e. once per landed edit, instead of ten frames per brush tick. - **Panel** mirrors terraform state on every 4th frame while the brush is down on the world (frame rate again the moment the mouse is over it), and its per-frame slider writes go through the dirty-check helper. - **Performance mode** (Settings > General, persisted) for big maps and slower machines: wider dab spacing where the falloff can take it (a quarter radius for soft curves and clay, a fifth up to curve 2.0, unchanged above), 32 dabs per tick instead of 48, 6-degree FOLLOW steps, and the panel mirror strided all the time. Its description names the two free levers, pausing the game and Focus mode. - **Clay rings, at the root.** The clay plane was the live centre height plus the layer step, re-measured every tick, so from the second tick on it sat on the disc the previous tick had just raised: every tick stacked another disc one layer up, and the disc edges read as rings (a slow 40-tick drag at intensity 10 piled 2700 elmos). The plane now comes from the pre-stroke surface, averaged over the dab centre and four taps half a radius out, so every dab of a stroke agrees on one plane and the stroke lays exactly one layer of INTENSITY x 8 elmos. Settings > Stroke > Clay build-up restores the old stacking for anyone who wants a held brush to keep piling. ## Improvements - **Sculpt strokes follow the path the mouse actually drew.** The brush sampled the cursor 20 times a second and bridged a straight chord between samples, so a fast scribble arrived with its corners cut and its dabs delivered in visible bursts. Every mouse move is now recorded and the tick walks that polyline, dropping dabs at the brush's own spacing. If the callin never fires, the walk degrades to exactly the old chord. - **Clay strokes deposit per distance travelled, not per tick.** A tick's intensity was divided by the number of dabs it contained, and each dab re-derived its target plane from the already-raised centre, so the deposit fell with the square of the dab count: at the lowest intensity a slow drag laid about 0.08 elmo per dab and a fast tick with 48 dabs about 0.00003. Speed removed the stroke. A whole tick now goes out as one message and the gadget derives every clay plane from the heightmap as it was before the tick, so nothing compounds and the per-tick rise is still bounded by one brush step. It also cuts up to 48 network messages a tick down to one, which the multiplayer co-editing work will want. - **SURFACE brush size steps proportionally** (a tenth of the current size per scroll notch instead of a flat 8 elmos), so a small brush can be tuned. - **SAMPLE buttons on the SURFACE altitude bounds**, like the raise tool's HEIGHT CAP: the next click on the terrain writes that height into the bound, pushes the other bound along if the band would invert, and switches the filter or band on. - Project folders and names may contain spaces; Open Project rows are larger and the window wider. - The sun sliders keep the applied intensity on every nudge, re-assert ground and unit shadow densities separately, and restamp each other so the vector rows and the azimuth/elevation rows never disagree. ## Fixes - **The SURFACE Ctrl sneak peek works at every zoom again.** It only exists in the tileset shader's live path, and 1.13's far cache and clipmap take over the ground as soon as the camera pulls back, so the preview quietly stopped working past a close zoom. A pixel under the brush now takes the live path whatever the distance, and the cache-only shader program stands down while a peek is up. - **The sun config survives a project open and a preset.** Three paths could still lose it: the ENV panel's RESET buttons returned to the lighting the engine held when the panel first opened, which on a canvas is the flat blank-map default; a preset without an intensity forced it back to 1.0; and a skybox fade in flight restored the sun colours it had captured over a config applied mid-fade. - **Editor sessions no longer spawn commanders.** New Map and Open Project start scripts carry an `editor_sandbox` flag; the initial-spawn gadget skips the commander for those sessions and the game-end gadgets stand down on the same flag. Editor canvases also leave pregame on their own a few frames after boot, so terrain raised above the canvas base is clickable without a manual start. - **DISPLAY chip rows wrap** onto a second line instead of squeezing every label onto two lines once a tool has five chips. ## Also - 1.14 changelog section in `doc/TerraformBrush-changelog.md`; header badge bumped to 1.14. - The gadget gains a `$terraform_stroke$` packet carrying a whole brush tick. The per-dab packet is unchanged and still used by sticky-measure replay. - Three gadgets outside the Terraform Brush are touched, all for the commander fix and nothing else: `game_initial_spawn.lua` skips the commander when the start script carries `editor_sandbox`, and `game_end.lua` / `game_team_com_ends.lua` stand down on the same flag so a commanderless editor session is not scored as a loss. Each is a single guarded block. - One whitespace-only commit reindents a block in `game_initial_spawn.lua`. It was already unformatted on master, and the format check only looks at the files a pull request touches, so it stayed green until this branch edited that file. ## Testing Tested locally on generated canvases and real maps with the tileset shader running: fast and slow sculpt strokes with clay at the intensity floor, square and circle with FOLLOW on and off, the protractor and symmetry with FOLLOW, the PASSABILITY band against F6 for a bot and a vehicle, SURFACE scatter and the retuned DOT preset over a sculpt, INFLUENCE bands in both SURFACE and LAYERS including the sneak peek at several zoom levels, sun presets across project loads and skybox fades, the Open Project browser against a cloned maps repository with spaces and subfolders, and editor sessions starting without commanders. ## AI/LLM usage statement Written and implemented with Claude Code under my direction; I reviewed the diff. --------- Co-authored-by: Floris <ruwetuin@hotmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )