Releases / v0.102.0-rc1

v0.102.0-rc1 Leaves A Mark

2026-09-29 Engine Latest

Blood, scorch marks and bullet holes wrap round edges and climb walls without being nodes. Characters can reach for things, look at things and plant their feet, and animation gets blend states, additive layers, masks and mirrored clips. A map view stops tearing up the terrain, a lowered render scale stays sharp, and a host whose connection blips keeps its lobby. Spawning, raycasts and terrain edits get cheaper. This is a beta: switch the Hub to the beta channel to try it.

Marks that wrap round corners

decals.add lays a picture on the world's surfaces: level meshes, terrain, and Collidable boxes and planes. Near an edge it folds over and carries on down the side. On a floor by a wall it climbs the wall and never pokes through. On a rock it follows the rock. It's lit, shadowed and fogged like the surface it lies on.

lua
decals.add{ texture = "textures/decals/blood.png",
            pos = vec3(hit.x, hit.y, hit.z), normal = vec3(hit.nx, hit.ny, hit.nz),
            size = 0.8, rotation = math.random() * math.pi * 2 }

A decal isn't a node. Every decal that shares a picture is one draw, so a fight can leave hundreds. The engine keeps the budget: 1024 until decals.setMax says otherwise, dropping the oldest. decals.set fades or tints one, decals.remove and decals.clear take them off, and perf.counts().decals says how many there are.

Characters reach, look and plant their feet

A script can now change a rigged model's pose after its animations have posed it, one frame at a time:

  • anim:setBoneRot and anim:addBoneRot turn one bone, and anim:setBonePos and anim:addBonePos move one. For example, lean the chest over a run, or drop the hips on a slope.
  • anim:reach("Hand", target, { pole = elbow }) bends an arm or leg so the hand or foot lands on a point: a grapple line, a wall, a step.
  • anim:lookAt({ "Spine2", "Neck", "Head" }, target, { limit = 80 }) turns a head, or a whole neck, toward something, within a limit.
  • anim:boneWorld("Hand") says where a bone ended up. It now also works under floptle run and on a dedicated server, so a hitbox can follow a hand where nothing is drawn.

The animation guide has a foot-planting recipe for uneven ground.

Controllers can do more too:

  • A blend state mixes clips by a number a script sets with anim:setParam, such as aim left, centre and right by aimX.
  • An additive layer adds its motion on top of the layers below.
  • A mask limits a layer to the bones you name.
  • mirror: true plays a clip as its left-right mirror image, so one left wallrun serves as the right one too.
  • anim:setSpeed(x, "Movement") speeds up one layer and leaves the others alone.

A map view leaves the terrain alone

terrain.lodAnchor(node) makes terrain detail, far planets and far craft follow that node instead of the camera. Pulling a map camera out into space no longer throws away the ground under the player, and closing the map no longer rebuilds it. Scattered props keep nothing loaded while the camera is far above them.

A lower render scale stays sharp

A render scale below 1 now sharpens as it scales up. app.setRenderSharpness sets how much, from 0 to 1 (the default is 0.4). draw.nativeLines(true) draws script lines over the finished picture at full resolution: one pixel wide and exactly the colour asked for, where before they came out soft and shimmering.

A host that blips keeps its lobby

When a listen host's connection dropped for a moment, its lobby was held for it, but only a host on a managed relay could claim it back. Every relay now gives the host a private token along with its lobby code, and a host that reconnects gets its lobby, code and players back with it. The relay needs this version too.

Cloud data by name

cloud.rank("laps"), cloud.docs("stages"), cloud.blobs("replays") and cloud.counter("installs") read and write the Cloud's data collections without building paths by hand. Every call reports errors the same way: { code, message, status }. floptle check warns about a collection a script uses that the project doesn't declare.

Cheaper spawning, rays and terrain edits

  • Spawning or destroying a node no longer costs time for the whole scene. A game that still makes the scripts re-read the whole scene every frame gets one Console warning naming the cause.
  • raycast checks only what the ray passes near, and hits level meshes exactly. On a level of a hundred models, a ray costs a fraction of what it did. raycastMany casts a batch in one call, and perf.counts() reports the rays cast and their time.
  • terrain.sculpt(..., "flatten") levels to a planet's up where it stands, or to a plane you name with { normal = ... }. Edits beyond 64 a frame wait their turn instead of being dropped, and a frame's edits are applied together.

Shadows you can budget

The 32 shadow casters nearest the camera are the ones that cast, and node.castShadow = false takes one out. env.shadowSteps trades shadow-edge precision for speed on a weaker GPU. perf.gpu() shows how long each pass took on the graphics card, so you can see where frame time goes.

Also

  • draw.polyline draws a line through a list of points, and draw.conic draws an orbit's ellipse or hyperbola.
  • A script's variables survive its node being switched off and on.
  • An export skips anything listed in .floptleignore, lists the heaviest files nothing in the project names, and no longer warns wrongly about files outside the project.
  • floptle shot --frames looks through the scene's own camera unless --turn is given.

Floptle Hub

Linux x86_64 9.0 MB Download → sha256 d35989fa65911f35bc36160a42d29beea7686b798502c131b82666e37f029c2a
macOS Apple Silicon 5.9 MB Download → sha256 707ad0a6ffa1358aa3a783eb37e1a6b40abab19e95544e8cb3786f5ed122d850
macOS Intel 6.4 MB Download → sha256 e0edf0b7a77deb0f72b94d4fd99a8e58826380b10b6d1d643045e69c3a4e7225
Windows x86_64 7.3 MB Download → sha256 7e0a03ae14e91ad18471c22951bbf36e75774ba7119a7b83172db05ef18528cb

Engine

Linux x86_64 37.1 MB Download → sha256 3489993fd63270b7f7ee2efb31903e5efc6e10fa396f56026a6516c15a3ceab3
macOS Apple Silicon 28.6 MB Download → sha256 d41fa6b8efdb113dd0eaebbde89ee64bbaec20c5713051ceb0c276f80a9968a8
macOS Intel 30.9 MB Download → sha256 3fdd19184e7a4cb0a5212731091ebc175413768561d4e3ee0c38478a78fe0a0e
web 4.5 MB Download → sha256 e2293c7bf2ab3025a1897ac8eec5b9b6b2afb0afc088e93e8ccda878628d027d
Windows x86_64 34.9 MB Download → sha256 22744767ae7b0d844e2141094a1ca1ece847f62f6b5f45f2d601616952f50845

The binaries are not signed yet. On macOS, right-click the app and pick Open the first time. On Windows, if SmartScreen appears, pick More info then Run anyway.