Repository navigation
Engine Roadmap
Status as of b111 (delivery logs for b57-b111 below). This page is the living
gap analysis for the Angels95 / AngelTech engine: what exists, what is missing
compared with a conventional game engine, and the prioritized plan to close the
gaps. Each entry lists the file:line evidence so work can start without
re-auditing.
Legend: [0] security/correctness, [1] engine fundamentals, [2] multiplayer completeness, [3] presentation, [4] tooling/UX.
-
Campaign maps rebuilt (b111): the eleven placeholder worlds became authored
levels,
Sektor_02/Sektor_03gained a second district each, and two audits (collision reachability + the cross-world portal chain) found and fixed eight progression bugs, including a gate with no floor and a sealed final room. SeeWiki/World-Design-Pass.md. -
Renderer (b102-b111): sky-portal faces (
SURF_PORTAL) sample a pre-rendered sky view by screen position; HDR bloom and a grade pass; the instanced particle path was rewritten for raylib 6.0 (rlDrawRenderBatchclears the program and VAO,BeginShaderModeonly records, camera matrix composition, sampler by texture id) with a gameplay reserve in the pool; and the glow halo now emits only the emissive term instead of re-adding the lit face. - Animation (b102-b111): pawn/item/player animation wired end to end, combat feedback, and the editor GLB preview panel with live playback.
-
CI/deploy: automatic server deployment over SSH + systemd on
b*tags.
-
Sky seams closed by deriving V from world elevation in
Sky.fs. The six skybox quads disagreed on their per-face V mapping (33–40 colour levels at a corner, measured with a pixel scan); corners fell to 1–5 levels and the cap band from 50 to 1. Legacy panoramas now sample their upper half only. -
Generated content textures with reproducible, deterministic PowerShell
generators:
tools/gen_sky_textures.ps1(sky gradients/caps) andtools/gen_water_textures.ps1(water_pool,waterfall_streaks,foam). -
tools/worldcheckis part of the gate:make testruns it over every shipped world with--headroom-alland--asset-refs, and now fails on a failing suite instead of grepping the log forFAIL.
- Campaign content:
World_endless_snow(b83/b84), the EngineTest desert path (b93), theAethelgard_Ruinsmission world, SilentPines Gorge and Dusk Falls (b101). All-brush terrain, 0.9 risers, impact foam at every cascade. - Surface decals and brush-wide surface scope (b89/b94); sky/water authoring
recipes documented in
Wiki/Outdoor-Maps-Changes.md.
- Editor layer tree (Core/Subsystems/Resources/UI) and the event bus (b89/b90).
- Responsive title menu, server browser, character select,
--world(b97); build-id versioning (Source/Version.hpp) and TDM team rules (b98). - Issue templates and the README/docs refresh (b101).
-
Complete at b56 (see Tier 0 roadmap below). b59 adds the HTTP Bearer gate
(
--auth-token/OZ_AUTH_TOKEN) andFILE_TRANSFERreject-notice.
- Per-zone physics overrides (
gravity/jump/terminal/water_*/ladder_speed/fly_mult) viaPhysicsInfo+ZoneEnvOverrides(b80). -
ZoneManagerextraction — zone volumes, portals, env-override merging live outsidePawnSystem(b80/b82). - Client settings persistence applied before
InitWindow(VSync/MSAA/window size honoured at creation).
- Scene sync, ammo sync, weapon grants, typed network NPCs with server-owned
AI (b58); NPC death/respawn + broadcast, pickup
respawn_time(b58). - Server world seeding from
World.ozone,PlayerData.dat, V2 world saves with autosave (b59/b61); join loads the server's map (b72); network NPC sync keyed by (world, npc, partition) — no pawn explosion after map switches (b73). - Admin
COMMAND(list/say/kick, b59/b61); stance replication (b78–b80). - Internet discovery: HTTPS master uplink (WinHTTP/curl, no vendored crypto),
default master
https://angels95.tribewarez.com/master, working Internet browser (b61/b70);--bind+ anti-spoofpublicipfor VPS (b65).
- First-person weapon view-models with Idle/Fire/Reload clips + procedural recoil (b74); FBX→GLB pipeline (b54+).
- Vertex-keyframe
.ozanimmorph animation + skeletal mesh clips (b74); wind sway shader (Wind.vs) (b74). - Particle system replaced by a 4096-particle
OzParticleSimulationManagerpool (b74). - Audio:
DspReverbon the master mix (b57);SoundManagerfacade with zone ambience/reverb handling (b82). - Skybox rendering/packaging overhaul — levelinfo priority, package
.dds, editor viewport skybox (b63–b68); looping title video (b57).
- Editor: full-document undo/redo (b81), world texture import (b81), Script Manager (b60), def-aligned Entity Properties (b60), animation authoring tool (b74), asset-scope tree + pack-on-import (b82).
- CI: raylib 5.5 build fix (b75), per-binary release assets (b69).
- Server-authoritative world simulation on a dedicated server (
AngelServ, no raylib dep) with raw-socket UDP networking (Source/Network/Network.hpp). - CSG brush worlds in the OZONE format with a Win32 editor (
AngelEd) and per-zone scripting (.ozls). - Data-driven pawn/weapon/item systems via LightningScript entities
(
Source/Script/,Source/Pawn/). - Package streaming for models/textures/sounds/music/worlds
(
Source/Package/). - A working 3D forward renderer: CSG brushes, billboards, rlights
directional/point/spot, particle effects, post-processing blits
(
Source/Renderer/). - Internet server discovery:
AngelMastermaster server +AngelServheartbeat uplink + client Internet browser (Source/Master/,Source/Menu/InternetBrowser.hpp; seeWiki/Master-Server.md). - Build + test matrix (
make test, CI on Linux + Windows).
| Gap | Detail | Evidence |
|---|---|---|
| [3] Shadows |
castShadow flag parsed but never used by the light pass |
Source/Renderer/LitLightning.hpp |
| [3] Materials | Diffuse-only; no normal/specular/PBR maps | Source/Renderer/LitLightning.cpp |
| [3] LOD / instancing | Not present; every renderable drawn every frame | Source/World/OzOzoneLoader.cpp |
| [3] Post shaders | Toon/Sobel/Line loaded but never applied | Source/Core.hpp |
Closed since b56: frustum culling (Source/World/OzoneFrustum.*),
vertex-keyframe + skeletal mesh animation and first-person view-models (b74),
4096-particle pool (b74), VSync/MSAA applied at window creation, looping title
video (b57).
| Gap | Detail | Evidence |
|---|---|---|
| [1] Collision is AABB-only | CSG brushes as AABBs; MAX_SPLITS=64
|
Source/Physics/OzBsp.hpp |
| [1] No collision APIs | No raycast, sphere/capsule cast, or query — gameplay can't reuse the BSP | Source/Physics/ |
| [1] Position restore | Player slide solved by restoring pre-frame snapshot; no swept/continuous collision | Source/Core.hpp |
| [3] Rigid bodies | No physics engine at all (no joints, no ragdolls) | — |
| [3] Navmesh/AI perception | No true pathfinding — server PATROL follows PathNode graphs (b74), everything else is distance checks |
Source/Server/GameState.cpp |
| [3] Input | No rebinding, no gamepad tuning, no mouse-look sensitivity setting | — |
Closed since b56: dual WDL/OZONE collision paths (WDL dropped b77), per-zone physics overrides (b80).
| Gap | Detail | Evidence |
|---|---|---|
| [3] Positional audio | Zero pan/attenuation calls; all sounds global | Source/Audio/ |
Closed since b56: zone ambience/reverb via SoundManager::UpdateSoundZones +
DspReverb on the master mix (b57/b82); title video wired (b57).
| Gap | Detail | Evidence |
|---|---|---|
| [0/2] Prediction/interpolation | NPC interpolation landed (lerp + shortest-arc yaw); remote-player prediction still open | Source/Server/Server.cpp |
| [0/2] Reliability |
sequence is never set/checked (raw UDP, no acks) |
Source/Network/Network.cpp |
| [2] Entity replication | NPCs keyed by (world, npc, partition) triples (b73); still no stable net IDs | Source/Network/Network.hpp |
| [2] Game modes |
levelinfo maxPlayers/friendlyFire enforced (b58); gameType/timeLimit/scoreLimit still cosmetic; no scoreboards/timers |
Source/Server/GameState.cpp |
| [2] Respawn | Server NPC death/respawn implemented (b58); player death/respawn flow still open server-side | Source/Server/GameState.cpp |
| [x] Admin |
COMMAND (b59/b61): list/say/kick via --admin-token/OZ_ADMIN_TOKEN; ban list deferred (UDP identity is ip:port) |
Source/Server/Server.cpp |
| [x] Ping | Real RTT (PING/PONG sequence-paired round-trip) | Source/Network/Network.cpp |
| [x] Join UX | LAN + Internet browsers; join/host ports functional from UI; angels95://join deep link (b60/b71) |
Source/Menu/TitleMenu.hpp; Source/Network/Network.cpp
|
| [x] Internet discovery | HTTPS master uplink (b70), default https://angels95.tribewarez.com/master, client browser with /status RTT |
Source/Network/MasterHttp.hpp; Source/Menu/InternetBrowser.hpp; Wiki/Master-Server.md
|
| [2] Reconnect | None — dropped client must restart | Source/Network/Network.cpp |
| [x] Game stats | Player persistence (b61): Saves/PlayerData.dat, saved on disconnect + 60s autosave + shutdown; world state V2 saves |
Source/Server/GameState.cpp |
| Gap | Detail | Evidence |
|---|---|---|
| [1] Fixed timestep | Client runs a 60 Hz accumulator; server tick capped at 10 Hz (done); uncapped paths remain in Main.cpp
|
Source/Main.cpp; Source/Server/Server.cpp
|
| [2] Save UX | Client save drops stats (hotbar names only) | Source/Script/LightningEntityManager.cpp |
| [4] Profiling/telemetry | None | — |
| [4] Crash reporting | None (no crashpad/minidumps) | — |
| [4] Mod loading | None; GameData is baked at pack time | Source/Package/ |
| [4] Streaming | No async asset loading; home screen scans disk at boot | Source/Main.cpp |
| [3] Cutscenes/sequences | None | — |
| [4] Localization | String literals throughout | — |
Closed since b56: client settings persistence (System/Angels95.ini read
before InitWindow, saved on exit).
| Gap | Detail | Evidence |
|---|---|---|
| [2] Timers/delays | No wait/timed actions; all script is synchronous |
Source/Script/LightningScriptContext.* |
| [2] Data types | No arrays/strings; only flat fields | Source/Script/LightningScriptParser.* |
| [2] Functions/coroutines | No user functions or coroutines | Source/Script/ |
| [2] Debugger | No breakpoints/step/trace | — |
| [2] Event bus | Actions fire ad-hoc; no publish/subscribe | Source/Script/ |
| Gap | Detail | Evidence |
|---|---|---|
| [4] Multi-select / prefabs | Single-object ops only | AngelEd/Source/Editor.hpp |
| [4] Lightmap baking | none | — |
| [4] CI drift | CI builds editor with inline g++ commands, not the AngelEd/Makefile
|
.github/workflows/ci.yml |
| [2] Hardcoded pickups |
EditorPickupType still not fully registry-mapped (Weapons tree landed b58) |
AngelEd/Source/Editor.hpp |
Closed since b56: full-document undo/redo (b81), world texture import (b81), Script Manager + def-aligned properties (b60), animation authoring tool (b74), asset-scope tree + pack-on-import (b82).
| Gap | Detail | Evidence |
|---|---|---|
[4] make test in CI |
CI only smoke-tests the server binary | .github/workflows/ci.yml |
| [4] Formatting/lint | No clang-format / clang-tidy / .editorconfig
|
— |
| [4] Sanitizers | No ASan/UBSan build variant | Makefile |
- Roadmap doc (this page)
- S6 — clamp world-list JSON to
MAX_MESSAGE_SIZEon join - S1 — clamp client
SCENE_UPDATE/CHATpayload reads - S2 — ownership + clamps on
PLAYER_HURT/PLAYER_KILL; drop spoofed clientPICKUP_COLLECTED; clampWEAPON_AMMO - S3 — finite/teleport validation on
PLAYER_UPDATE; server-authoritative relayed health - S4 — auth race: client confirms on first non-challenge message; retry
sends
CLIENT_AUTH; server re-acks re-auth; idempotentadd_player - S5 — explicit
COMMAND/GAME_STATEhandling (warn + drop) - Test coverage for the above
- Real RTT ping (PING/PONG sequence-paired round-trip; client heartbeat at
Network.cpp, HUD already rendersget_ping_ms) - Enforced 10 Hz server tick (fixed-timestep accumulator, catch-up capped) + client fixed-timestep (60 Hz accumulator for movement physics/pawns/projectiles)
- NPC interpolation on the client (smooth 2.5 Hz broadcasts via
prev/targetlerp + shortest-arc yaw) - Position/state validation moved into
GameState::update_player_position(single choke point, finite + teleport clamp) - Client settings persistence (
LoadClientSettingsreadsSystem/Angels95.inibeforeInitWindow; VSync/MSAA/window-size applied at window creation; saved on exit) - Frustum culling for renderables (camera-geometry planes + AABB test in
OzoneFrustum/OzOzoneLoader)
- Server-authoritative death/respawn + timers; scoreboard UI (NPC respawn done b58; player flow open)
-
levelinfo→ real game modes (DM timers, score limits; maxPlayers/friendlyFire enforced b58) - Kick/ban + server console (
COMMANDimplemented b61: list/say/kick behind --admin-token; ban list still open) - Player roster + LAN browser UI; honor the join port field (b57)
- Internet discovery:
AngelMastermaster (UDP heartbeats + HTTP/JSON list, expiry/rate limits),AngelServHTTPS uplink (b70), client Internet browser with direct status/RTT queries (seeWiki/Master-Server.md) - Server world population from world files + server saves (b59/b61: seed_world_entities, PlayerData.dat, V2 world saves, autosave); join loads the server's map (b72)
- Stable entity replication IDs (replace index-triples)
- [~] ACK/retry for critical messages — pickup collect done: refusals now name
their reason and answer with a re-sync of the player's own world, state
re-syncs on join / every 15 s / on a client
PICKUP_RESYNC, and the collected node is actually hidden (PickupNode::netId+ApplyPickupNetState). Weapon fire still has no ack. Pinned by the loopback round-trip cases intests/GameState.test.cpp. - Client prediction + reconciliation for own player
- FILE_TRANSFER: rejected by design (b59 notice + rate limit); implement chunked transfer or drop the packet type
- Shadow pass (directional + point)
- First-person weapon view-model (b74; Idle/Fire/Reload + procedural recoil)
- Title video wired (b57: looping title video)
- Positional audio (attenuation/pan) — zone ambience/reverb landed via
SoundManager(b57/b82) - 3D particles (b74: 4096-particle
OzParticleSimulationManagerpool) - Animation for NPCs + dropped items: the three unrigged enemies (Walker/Skaarj/Floater) drive generated
.ozanimIdle/Walk/Run/Death clips (tools/gen_pawn_anims.py), the Brute plays its embedded skeletal take, and dropped guns idle-animate. The shipped player-character pack has only combat/stunt takes (no idle/walk), so remote players stay on the bind pose until a locomotion clip is authored - a def still needs its own clips to animate.
- Editor undo/redo; [ ] multi-select; [ ] prefab library
- CI runs
make testand a game-state suite; build editor via its Makefile - clang-format/clang-tidy +
.editorconfig - ASan/UBSan CI build variant
- Save-slot UX + full player-data persistence
- FOV/ADS sensitivity settings
- "LAN discovery works": the server announces on UDP 27100 and the client's Multiplayer → Join page scans LAN on demand (b57) — but there is no passive background discovery; scans are manual.
- "Dedicated server standalone works": it does for world/NPC simulation, but
player damage is client-authoritative for world hazards (
PLAYER_HURT) — now closed by Tier 0 ownership checks. - "INI config is supported": the client reads/writes
System/Angels95.ini(window/VSync/MSAA/gfx/audio), and the server now readsSystem/OzServer.ini([Server]/[Auth]/[MasterServers]) with CLI flags + envOZ_AUTH_TOKEN/OZ_ADMIN_TOKENoverriding it. - "HTTP API is open": it still is unless
--auth-tokenis set (b61 adds the Bearer gate); the token is not a security boundary on unencrypted LAN. - "Linux server build": AngelServ/AngelMaster are standalone and POSIX-clean
(MasterClient now includes its own socket headers);
--bindon both controls the listening interface for VPS hosting. SeeSystem/angels95-serv.service.
To add an item: file it under a tier, with file:line evidence, then tick it
off when landed. Keep this page the single source of truth for engine gaps.
Angels95 - AngelTech Engine | repository | 5a75146
Built on raylib 5.5.