1-2 per building at second-floor height on metal brackets, double-faced
with generated ad graphics — the perpendicular sign clutter that defines
Akihabara/anime-city streets and makes rows read dense from street level.
Verified via street capture; smoke test 0 failures.
Co-Authored-By: Claude Fable 5 <[email protected]>
Final detail pass — no gameplay object remains a plain box:
- Markets: box stalls replaced with modeled kit stalls (4 styles seeded),
hidden box colliders keep the wood acoustics; hand carts at the market
mouths; standing lanterns between stalls
- Shrines: hanging lanterns on the stone pillars, wooden fences flanking
the torii approach
- Towers: giant mid-height wall ads on the street faces (the anime-city
mega-ad look), on top of crown boards and corner columns
- Storefront awnings (kit detail piece) on ~40% of buildings
- Traffic signals at every central-avenue crossing, diagonal from the
streetlights
- Fantasy Town Kit (CC0) installed at assets/props/town
Verified via street capture (wall-scale glyph ads, pharmacy signs,
banner ads, stalls, carts); movement 11/11, smoke 0, acoustics PASSED.
Co-Authored-By: Claude Fable 5 <[email protected]>
The city's flat color sign panels are now real graphic designs, closing
the street-level "graphic density" that anime cities live on:
- tools/generate_ads.py: procedural ad library (24 textures) — bold
two-tone layouts (diagonal splits, bands, circles, stripes) with
fake-glyph text blocks that read as kanji/kana from gameplay distance,
inked borders, seeded palette system
- Every building gets 1-3 street-level posters plastered on its facade
- Vertical sign columns render a stacked-glyph column texture
- Rooftop billboards, tower crown boards (both faces) and the central
4-face screen tower all show distinct ad graphics
- Posters under the viaduct arches on every pier
- All panels lit (albedo + emission of the same texture) so they glow
as signage without blooming out
Verified via street capture (glyph posters, pharmacy-cross signs, ad
boards visible down the avenue); movement 11/11, smoke 0 failures,
acoustics ALL PASSED.
Co-Authored-By: Claude Fable 5 <[email protected]>
Streets are now populated: seeded parking lanes hug the curbs of every
N-S street with sedans, taxis, vans, SUVs, hatchbacks, delivery trucks
and the occasional police car (~100+ across the city).
- Wheels attach at the models' wheel-socket empties at spawn
- Metal-tagged box colliders: cars are cover that sounds like cover
- Toonified + darkened base tint (kit albedo clips under the map light)
with per-car hue jitter for varied paint jobs
- Slight rotation jitter so parking reads natural, not stamped
Verified via street capture (colored cars parked down the avenue, no
clipping/glow); movement 11/11, smoke 0 failures, acoustics ALL PASSED.
Co-Authored-By: Claude Fable 5 <[email protected]>
Boxes with lines can't reach the requested fidelity — the city now uses
real modeled architecture, toonified into the cel style:
- Kenney City Kit Commercial (CC0, 41 GLBs) installed at
assets/props/citykit: 13 mid-rise buildings + 5 glass skyscrapers with
actual modeled window insets, doors, storefronts, awnings, trim and
rooftop detail, plus parasol/awning props
- Standard + market blocks: street edges fill with seeded kit buildings
(measured catalog drives placement, x13 scale -> 11-32m facades) over
box colliders; Akiba signage layer (corner sign columns, glowing
segments, roof billboards) attaches aligned to each model's bounds
- Tower blocks: kit skyscrapers (up to ~70m curtain-wall glass) on the
walkable podium, seeded rotation, crown billboards kept
- Market blocks add cafe parasols among the stalls
- SSAO enabled + exposure recalibrated for the kit's bright albedo
(sun 2.2 / ambient 1.7); lighter asphalt/paving to match; lighter haze
All kit meshes run through apply_toon_recursive: toon banding over the
kit textures, matching characters/weapons/VFX.
Verified: street + aerial captures (detailed facades at eye level, dense
believable skyline); movement 11/11, smoke 0, acoustics ALL PASSED.
Co-Authored-By: Claude Fable 5 <[email protected]>
Scaled the single block to a full 10x10 city grid (48m cells, 16m streets,
640m across) with a hand-authored layout so the fabric stays varied:
Block types:
- S standard retail (70%): paired parametric buildings facing the N-S
streets, seeded heights/colors per block; ~half get a mid-block alley
with fire-escape climbs so no two blocks play identically
- T landmark towers: 8-10 floors on a walkable retail podium, mega corner
sign, double-sided rooftop crown billboard (skyline wayfinding)
- J shrine courtyards: walled court, torii, slide-roof hall, lanterns,
trees — the green quiet break in the fabric
- M market streets: dense stall rows + lantern strings between low
buildings (close-quarters cover mazes)
- P plaza cluster at the city centre with planter cover and a giant
4-face screen tower at the exact middle (the Crossing)
- C construction sites: open slab frame to wallrun, access ramp, container
stacks, and a 28m crane whose jib is the city's tallest grapple anchor
City systems:
- Brick rail viaduct runs the full east-west width on per-block piers with
vending arcades under alternating arches + slide ramps at the centre
- Central avenues x=0/z=0 get matched streetlights and zebra crossings at
every block line; brick wall rings the district; city-haze fog for depth
- Detail pass per building: window bands every floor, water tanks/antenna
masts seeded on roofs, denser sign stacking
Perf/physics: decoration (signs, windows, leaves, lamp heads) is
render-only MeshInstances; only gameplay surfaces are static bodies, all
acoustics-tagged. Spawns distributed across block types facing centre.
Verified: full-city aerial (all 100 blocks, aligned grid), avenue-level
capture (clean canyon, viaduct vista); movement 11/11, smoke 0 failures,
acoustics ALL PASSED.
Co-Authored-By: Claude Fable 5 <[email protected]>
Complete new approach after the hand-placed layout shipped misaligned:
every element now derives from a street grid and its building's footprint,
so alignment is structural, not luck.
District structure (modeled on Akihabara's Chuo-dori / Denki-gai / JR
viaduct):
- 16m avenue flanked by continuous mid-rise rows; buildings defined ONLY
by z-interval + floor count (4m quantized floors), packed edge-to-edge
- _building() derives everything from the footprint: parapet lips on the
roof rim, inset glass storefront, sidewalk canopy, stacked per-floor
sign bands, a solid vertical corner sign column with glowing segments,
evenly spaced roof AC units, rooftop billboard on 4+ floor buildings
- Brick rail viaduct crosses the whole block on piers with an under-track
vending arcade; sidewalk-aligned slide ramps with handrails reach the
deck on both flanks
- Denki-gai alley cut through both rows (wallrun walls + fire escape
platforms climbing per floor); red SEGA-style landmark + blue
electronics building anchor the north corners
- Matched streetlight pairs every 16m with arms over the road; zebra
crossings at the alley mouth and south block; spawns on sidewalks/deck
facing the map center
Movement: viaduct high lane + roof-hop onto the 2-floor row, canopy lane
above each sidewalk, alley wallruns + fire escapes, grapple anchors on
lamp arms / sign columns / viaduct edge / billboards, slide ramps.
Acoustics: facades concrete, storefronts glass, canopies wood, viaduct
brick, signs/AC/vending/lights/escapes metal.
Renamed in the level selector: "Akiba Crossing". Verified via aerial and
street captures (aligned rows, clean canyon, viaduct framing); movement
11/11, smoke 0 failures, acoustics ALL PASSED.
Co-Authored-By: Claude Fable 5 <[email protected]>
- LevelMaterials.flat(): toon-banded FLAT color material (no greybox grid
texture) for dressed maps; cached per tint, rim/spec off
- Neon Alley overrides _box_static: every structure renders flat cel color;
prop-scale pieces (<10m) get an inverted-hull ink outline scaled to their
size. Building-scale boxes skip the hull — the inflated plates smear into
black voids at close range (found via fixed street-camera capture)
- Pylon wires render as flat ink lines; warmer wood + hotter vermilion for
flat shading (the grid multiply used to brighten tints)
- visual_capture: deterministic street-level shot after the aerial for
style comparisons
Street capture now reads properly BoomerangX: flat lavender asphalt, hard
light bands, torii framed down the underpass, neon strips + sign glow.
Co-Authored-By: Claude Fable 5 <[email protected]>
New map (scenes/maps/neon_alley/, auto-appears in the level selectors):
Layout for movement flow:
- Main N-S street = the long sightline, crossed by a pedestrian bridge
(slide ramps up both ends, underpass cover below, railed high ground)
- West machiya row: wooden two-story houses with a jump route
(awning -> balcony -> roof deck) and 25-degree slide roofs facing the street
- East concrete towers with glass storefronts; brick wallrun alley between
them (AC units to vault); metal fire-escape platform route to the roofs;
angled rooftop billboard as cover + grapple anchor
- Three power pylons with crossarms over the street chain a grapple route;
the torii gate crossbeam at the north shrine plaza is a fourth anchor
- South market: wooden stalls with neon canopies + metal vending machines
= scattered mid cover; shipping container corner piece
- Spawns ring the block and face the map center
Acoustics as level design: every surface is tagged (machiya/stalls/torii
wood, towers concrete, storefronts glass, alley+perimeter brick, escapes/
AC/rails/container metal) so occlusion tells you which structure a shot
came through and reflections differ per street.
Style: sunset sky + fixed dusk-lavender ambient (calibrated for the toon
shader's 1/PI light response), warm low sun, neon sign columns, shop signs,
lantern strings, billboard glow, underpass strip lights.
Verified: aerial + street-level + third-person captures; movement 11/11,
smoke 0 failures, acoustics ALL PASSED.
Co-Authored-By: Claude Fable 5 <[email protected]>
Audio (all CC0 — Kenney packs + OpenGameArt, see assets/sounds/SOURCES.md):
- Replace every procedural synth WAV with forged sounds (ffmpeg pitch/layer
mixes): distinct fire sounds per weapon with 2-3 variations, explosions,
footsteps x5, land/jump/dash/vault, knife swing, hit/kill confirms,
bullet impacts, reload, flight loops, UI hover/click/confirm/error,
match jingles, menu music
- AudioManager.stream_for(): AudioStreamRandomizer per sound id — every
weapon now gets variation + pitch randomization on each shot
- Explosions and bullet impacts play positional audio; landing has its own
sound instead of a pitched footstep; ambient wind bed on every map
Visuals:
- ExplosionVFX: shared cel-shaded burst (white-hot stepped core, ink
shockwave ring, star spikes, flat smoke puffs) replaces the orange
sphere in both local and remote-replay paths
- Comic star muzzle flashes on all weapons; unified cel tracer bolts with
ink outlines across hitscan/shotgun/remote paths
- Impact decals: hard-stepped ink-splat gradients instead of soft airbrush
- Toon shading on first-person view models + arms, third-person weapons,
and the procedural humanoid fallback (no hull outlines on FBX weapons —
their hard normals tear the inverted hull)
- Fix: giant soft "blob" highlight on floors — toon rim/specular disabled
on level-geometry materials (pre-existing artifact since the cel commit)
- Fix: own third-person weapon rendered into the first-person camera
(shadows-only now covers first_person_mode)
UI:
- UITheme: comic theme on the root window — Bangers display font (OFL),
paper panels with thick ink borders + hard drop shadows, papaya accent,
themed buttons/inputs/popups; hover/click sounds on all menu buttons
- Main menu: tilted comic wordmark, sunset toon diorama, looping menu music
- Match HUD: themed scoreboard/killfeed/kill counter
Viewports:
- 4x MSAA project-wide + viewmodel/diorama viewports (crisp ink lines)
- Viewmodel camera near plane 0.01; third-person camera FOV syncs settings
- debug/visual_capture.gd: dev tool to screenshot menu + level for review
Verified: 11/11 movement tests, spawn smoke test 0 failures, before/after
screenshot comparison of menu and level.
Co-Authored-By: Claude Fable 5 <[email protected]>
- SkinnedPlayerModel: generic play_oneshot() (generalizes the Land lock),
Hit and Dance in the clip table (Dance loops), restartable clips
- Hit flinch: victims visibly react on every peer's screen via the existing
damage broadcast — no new RPC
- Dance emote on B: toggles while grounded and idle, breaks on any movement;
synced to remotes via synced_is_dancing (all three spawner configs)
- Anime radial speed-lines overlay (canvas shader): fades in past ~1.2x walk
speed, spikes on dash, widescreen-corrected clear center
- New input action 'emote' (B) in project.godot
11/11 FSM tests, spawn smoke 0 failures.
Co-Authored-By: Claude Fable 5 <[email protected]>
- toon.gdshader: banded diffuse with cool-tinted shadows (3 tones), stepped
specular, rim light, and an optional world-triplanar albedo path so level
geometry keeps the 0.5 m grid with no UVs
- toon_outline.gdshader: inverted-hull ink outline, applied via
material_overlay so it works on skinned (deforming) meshes
- LevelMaterials: tinted() now returns toon grid materials; toonify()/
apply_toon_recursive() convert imported character/prop materials in place
- SkinnedPlayerModel: characters get toon shading + outline on load
- LevelEnvironment: shared stylized environment for all maps — saturated
anime sky, linear tonemap (filmic/ACES crush cel bands), bloom for
emissives, saturation+contrast grade, light depth haze; test level and
dust2 now use it and the procedural arena (which had NO environment)
gets it plus runtime toonification of its baked geometry
Co-Authored-By: Claude Fable 5 <[email protected]>
- Generated CC0-style prototype grid textures (0.5 m cells) and a shared
LevelMaterials factory: world-space triplanar mapping over every code-built
level (test level, dust2, procedural arena) with the existing color coding
kept as tints. Readable surfaces at speed instead of flat color boxes;
materials are cached per tint so identical surfaces batch.
- .gdignore + .gitignore the raw downloaded asset packs in addons/ whose
overlong paths broke Godot import scans and spammed git warnings.
- Replaced the rotted FSM test file (invalid call(t) on Callables, stateless
stub nodes, hung forever without quitting) with a real suite: 10 tests
covering state registration, jump bookkeeping, wall-run momentum
preservation and upward-carry cap, per-player dash cooldown (regression for
the old shared static), dash speed stacking, chain soft cap, landing
events, and slide entry momentum. New headless entrypoint:
godot --headless --path . -s res://movement/tests/run_fsm_tests.gd
Co-Authored-By: Claude Fable 5 <[email protected]>
- Quake-style air-strafe accelerate (real speed gain from strafing; external
speed from dash/rockets never clamped)
- Wall run: keeps entry momentum (incl. upward carry), accelerates along the
wall instead of hard-setting velocity, gravity fades in over the run
- Slide: slope physics (gravity projected along floor accelerates downhill),
flat-ground decel instead of multiplicative friction, entry boost, direct
slide->wallrun and slide->dash transitions
- Dash: cooldown 10s -> 2s, per-player (was a static shared across instances),
momentum fully kept on exit, FOV punch event
- Grapple: taut pendulum with active rope control (W reels in, S pays out),
release keeps swing energy
- Wall climb: carries upward momentum in, jump-off kick, shared vault helper
- Crouch capsule: single owner in the machine, smoothly lerped, ceiling check;
camera eye height follows via crouch factor (no more head snapping)
- Landing: machine emits 'land' events scaled by impact; camera dip + pitched
down thud; footsteps get pitch variation
- Camera rig: event-driven (land dip, dash FOV kick, vault pitch impulse),
slide roll tilt
- Model: Jump vs Fall split by vertical velocity, Land one-shot on heavy
landings, wall-run body lean (synced to remotes via synced_wall_side)
Co-Authored-By: Claude Fable 5 <[email protected]>
Layer a procedural SkeletonModifier3D (ShooterPoseModifier) on top of the base
clip so the character reads like a movement-shooter avatar:
- Directional lean: banks into the movement direction (right/left/back) and
blends smoothly for diagonals, driven by velocity relative to facing.
- Slide: leans the torso back and pitches the head up to look forward, instead
of the base clip's forward-torso/legs-out "spine break".
- Airborne: plays a composed Jump pose (weapon ready) rather than a flailing
fall.
- Weapon hold: the base clip already keeps the arms down (weapon at the hip);
on ADS both arms lift and swing in toward centre-front to aim. ADS is read
from the active weapon and synced (synced_is_ads) so remote players raise
their weapons too.
The controller feeds movement direction + ADS to SkinnedPlayerModel.set_locomotion()
each frame (works for local and remote via synced velocity/rotation). All
rotations are authored in skeleton space (fwd=+Z, up=+Y, right=-X) and converted
per-bone; tuning constants are at the top of ShooterPoseModifier.
Verified by rendering the poses (idle/strafe/back/slide/ads) in a real Godot
viewport. Smoke test 30/30.
Co-Authored-By: Claude Fable 5 <[email protected]>
Character pipeline (tools/):
- sketchfab_import.py: search/download via Sketchfab Download API with
license/attribution tracking (SKETCHFAB_API_TOKEN)
- autorig.py: headless Blender auto-rig — fits a Mixamo-named skeleton
to unrigged humanoids, binds automatic weights
- merge_animations.py: merges the shared Mixamo-skeleton animation
library onto any rigged character, strips root motion, canonical names
- pipeline.py: one command chains download -> rig -> animate -> register
In-game skin system:
- SkinManager autoload reads skins.json (auto-written by the pipeline)
- SkinnedPlayerModel rewritten: canonical clips with fallback chains,
blend times, speed-scaled locomotion, weapon bone attachment
- First-person: full animated body for the owner, head hidden via
SkeletonModifier3D; third-person: full model for other players
- Skin selector in main menu; skin id synced in multiplayer
- Fixed GLBLoader crash (GLTFDocument.get_animation_count doesn't exist)
Multiplayer sync overhaul:
- Movement is now client-authoritative: the owning peer simulates
locally (no input round-trip), server keeps health/kills/death
- Remote players interpolate synced_position/velocity with
extrapolation and snap-on-teleport
- Knockback/impulses routed to the simulating peer
Audio:
- AudioManager autoload: SFX/Weapons/Footsteps/UI/Music buses, pooled
3D players, variation + pitch randomization, auto-registration from
assets/sounds
Docs: 3D_ASSET_PIPELINE.md rewritten end-to-end, new ASSET_SOURCES.md
(non-procedural animation/map/sound sources) and SOUND_DESIGN.md.
Verified with debug/spawn_smoke_test.gd (headless: 24/24 checks pass).
Co-Authored-By: Claude Fable 5 <[email protected]>
The Miku model T-posed because the previous _update_skin() used
set_bone_pose(i, get_bone_pose(i)) which is a no-op when the pose
is unchanged. Replace with skeleton.notification(NOTIFICATION_UPDATE_SKELETON)
to force the Skeleton3D to recompute bone transforms and notify the
MeshInstance to update vertex buffers.
Also fix scale: the GLB is ~1.2m tall (not 1.6m as documented), so
set scale_factor=1.25 to fit the 1.8m player capsule, and add
position_y_offset=-0.2 to align the model's feet with the player origin.
Co-Authored-By: Hermes Agent <[email protected]>
The skinned player model was loading miku_rigged_final.glb which only
contained a single "Idle" animation (1 track, near-rest pose). This caused
"animation 'Jump/Walk/Run' not found" spam and a T-pose appearance.
Switch to miku_rigged_animated.glb which has all 7 animations
(Crouch, Death, Idle, Idle2, Jump, Run, Walk).
Additional fixes:
- Fix scaling: the GLB is already in meters (~1.6m tall), not cm.
Removed the unconditional 0.01 cm->m conversion that was shrinking
the character to 1/100th size.
- Fix bone track paths: use "MikuRig/Skeleton3D:" prefix matching the
actual scene tree structure (AnimationPlayer is sibling of MikuRig).
- Add _ensure_locomotion_animations() to create Walk/Run/Jump/Idle
procedurally if the GLB is missing them.
- Eliminate per-frame "not found" log spam with rate-limited warnings.
- Update level_runtime.gd and test_level_builder.gd to use animated GLB.
Closes #3d-player-model animation pipeline
The Blender GLTF exporter was stripping animation tracks (only 1 of 51
channels survived export). Now SkinnedPlayerModel detects this at
runtime and creates a proper Idle animation programmatically using Godot's
Animation API with 5 bone tracks (Spine, Arms, Neck, Hips).
Also switched model_path back to miku_rigged_final.glb since the
re-export wasn't adding usable animations.
- Remove duplicate is_local variable in level_runtime.gd line 224
- Remove orphaned animation code from old load_model in skinned_player_model.gd
- Both files now compile cleanly
Godot headless/CLI can't import GLB files — the GLTF loader only works
in the editor GUI. Switched SkinnedPlayerModel to use GLTFDocument.append_from_buffer()
which parses GLB data from raw bytes at runtime.
Verified: GLB parses successfully, generates scene with MikuRig skeleton,
AnimationPlayer, and 7 animations (Crouch, Death, Idle, Idle_001, Jump, Run, Walk).
Also added characters/glb_loader.gd as a reusable utility for loading
any GLB file at runtime.
- Add miku_rigged_animated.glb (3.27MB) with 18-bone skeleton and 6 animations
(Idle, Walk, Run, Jump, Crouch, Death) via Blender auto-rig script
- Add tools/rig_and_animate.py: reusable Blender script for rigging any humanoid
mesh with Mixamo-compatible bone naming
- Update SkinnedPlayerModel: scale_factor, first-person mode, animation state
matching (Idle/Walk/Run/Jump/Crouch/Death)
- Update level_runtime.gd: use skinned model for local player, procedural
humanoid for remote players
- Update skin_manager.gd and test_level_builder.gd to use animated model
- Fix Godot 4.2.1 'is not Type' syntax in 5 weapon files
- Add editor/import_miku_to_tscn.gd for editor-based GLB import
- Fix tab character in _build_elevated_walkways() call (line 63)
- Fix untyped 'pos' variable in grapple pillar loop (line 376)
- Remove fog_sky_affinity (Godot 4.3+ only property)
- Replace preload() with load() for runtime script loading
- Replace 'is DoubleBarrelShotgun' type check with duck-typing
- Fix 'is not OfflineMultiplayerPeer' syntax in grenade spawn
- Replace absf() with abs() in state_machine, state_air, state_ground
- Update test_level.tscn to remove stale UID reference
All fixes verified: PARSE OK and scene runs without script errors
on Godot 4.2.1 headless.
- state_wall_run.gd: typed ray_origin/ray_end as Vector3
- test_level_builder.gd: restructure builder to put MovementStateMachine
+ state children under Player, attach camera under Player too
- player_movement_controller.gd: @onready uses get_node so type is not inferred
- test_level.tscn: minimal Node3D root (zero SubResource references)
- debug/test_level_builder.gd: runtime floor/walls/lighting/camera/UI
shapes/meshes created from BoxShape3D/BoxMesh — no .tscn subresources
- project.godot: revert features to 4.6 (installed build is 4.6.3)
- Removed all SubResource BoxShape3D references from test_level.tscn
- Changed PackedStringArray feature from 4.6 to 4.2
Scene is now pure nodes + transforms, no external resource IDs
- scenes/test_level/test_level.tscn — playable test environment (30x30 floor + 4 walls + ramp)
Floor at y=-1, Player spawn at (0, 1.5, 8), FpsCamera at head height (y=1.7)
DirectionalLight + WorldEnvironment + UI label overlay (speed/state/chain)
- debug/debug_test_env.sh — launch wrapper for manual playtesting
No code changes: raw physics testbed. Intended to be opened as first scene in Godot window.
Closes#2 (test-level scene task)