OhMyGame
OhMyGame은 AI로 게임을 만들 수 있는 오픈소스 스튜디오로, 디자인·구축·플레이테스트·출판을 하나의 앱에서 모델 키와 함께 수행합니다
50cc부터 시작해 레이스·스킬·바이크 업그레이드·부품 제작·수입·집·작업장 건설로 모토크로스 명성 구축
Start on a 50cc and build your motocross legacy! Race championships, train skills, engineer and upgrade bikes, manufacture parts, earn money, build your home and workshop, and rise through the ranks.
게임TypeScript · HTMLGitHub @BigDaddy284온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기Start on a 50cc and build your motocross legacy! Race championships, train skills, engineer and upgrade bikes, manufacture parts, earn money, build your home and workshop, and rise through the ranks. Explore a world of tracks, rivals and challenges in an offline single-player RPG, with modding tools to customise skins, areas and tracks.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗A single-player, offline motocross career RPG. Start as an unknown rider with a broken 50cc and work your way up to legend.
| Home Town: the player by the old rusty truck | Race day at Farmland MX: bikes in the air over the double |
|---|---|
This is Alpha v1.1: the whole career loop from a broken bike to race days at three venues, player-made tracks, and now the Local Champion Championship for the Area 1 badge. All art is placeholder art in the agreed style, imported from the project's art threads.
This is a hobby project, made for fun in spare time. It is offered as-is, with no warranty, no support and no promised updates. There may be bugs, and some may never be fixed. Issues are turned off on this repository and I'm not able to answer questions, take requests or fix problems. You're welcome to play it, learn from it and change it for your own use under the terms of the MIT license, at your own risk. Back up anything you care about: your career is saved in the browser you play in, so use Load → Export save now and then to keep a copy as a file, and keep copies of your own tracks (the .track.json files in public/mods/tracks/, or the editor's Export).
The game loop: earn money, keep the bike going, race, level up, repeat.
It runs in a browser on desktop or on a phone held sideways, and saves automatically.
In a browser: once GitHub Pages is switched on (Settings > Pages > Source: GitHub Actions), every push to main publishes the game to this repo's Pages site.
On your own computer: install Node.js (LTS), then:
npm install
npm run dev
and open the address it prints (usually http://localhost:5173).
| Action | Keyboard and mouse | Touch |
|---|---|---|
| Walk | WASD or arrow keys, or click where you want to go | Tap where you want to go |
| Talk to an NPC or use an object | Click it, or face it and press E or Space | Tap it |
| Next line of dialogue | Click, E, Space or Enter | Tap the box |
| Zoom (50% to 200%) | Mouse wheel, + and -, or the on-screen zoom control | The on-screen zoom control: a Zoom button with a slider, or + and − buttons (Settings > Display > Zoom control) |
| Bike, bag and current task | Tab, I or B | Bike button |
| Skills | K, or the Skills tab in the Bike panel | Bike button, then Skills |
| Pause menu (save, settings) | Esc | ☰ button |
Hold the phone sideways: the game is laid out for landscape, and asks you to turn the phone if it is upright. For the most room, use the browser's Add to Home Screen: the game then opens full screen with no browser bars. The game draws at the phone's full screen resolution, and panels shrink to fit a short screen.
Your career is saved in the browser you play in, so another browser or device starts empty. Load → Export save gives you your career as a file (mxrpg-<rider>-<date>.save.json): a download on a computer, the share sheet on a phone or tablet (Save to Files on iPhone and iPad, Drive or Downloads on Android). Load → Import save on any browser or device picks that file and carries on the career there; Load is open even with no career saved, for this. Importing over a career keeps the one it replaces as Backup 1 under Load. A save from an older build is upgraded on import like any other; one from a newer build, or a damaged one, is refused with the reason. Export now and then as a backup: Safari can clear a website's storage after about a week without a visit (a Home Screen app is not affected). The code is in src/core/saves.ts (the file format) and src/ui/files.ts.
Mod tracks are race tracks made with the game's track editor and raced in the game from Mod Track on the venue road. A mod race day plays exactly like Farmland MX: the same entry fee, field, AI riders, prize money, XP and parts wear. Picking a mod track goes straight to the gate pick, without a venue area to walk round, and race day is the only mode (no practice): that is how mod tracks stay (Boss, 29 Oct 2026), with no modders' town area planned.
1. Build the track on a computer: the track editor needs a mouse and keyboard and isn't usable on a phone (racing mod tracks on a phone works, through Import track file). Open the track editor: tools/track-editor.html on the published site, or http://localhost:5173/tools/track-editor.html when running npm run dev. Choose New, draw the route, then add:
Then use Ready to race, which runs the game's checks.
2. Save it. The editor opens on the mod tracks: the example in public/mods/tracks/ and any saved there; the game's own four tracks are not listed (the Development edition has a Show the game's own tracks tick under the list, remembered in the browser, for working on the game itself). Tracks made with New, Duplicate or Import are mod tracks. The first Save asks for the track's name, and the track is saved as its own file, public/mods/tracks/<name>.track.json, never into the game's tracks.json. It can't overwrite another track: a name already in use is refused.
npm run dev, use the track editor at http://localhost:5173/tools/track-editor.html and Load the tracks from this server. Save then writes straight into public/mods/tracks/, and the game picks the track up on its next page load. Saved mod tracks are listed in the editor too, to carry on editing.public/mods/tracks/ folder there.public/mods/tracks/.Export still saves any track as a .track.json to share.
3. Race it. On your own copy, a track in public/mods/tracks/ shows under Mod Track in the game. For a built copy, rebuild with npm run build, because the build writes the folder's index.json (a website can't list a folder by itself). With npm run dev, Race it in the game in the editor opens a race day on a saved mod track straight away. On any copy, including the published site, you can also use Mod Track → Import track file in the game to pick a .track.json from your device. It is kept in that browser only, and can be removed from its race office. farmland-example.track.json is in the folder as an example.
What a mod track must meet. The game runs the same checks as on its own tracks:
A track that fails stays in the list, and picking it shows the reasons. An import that fails isn't added. Each track is listed by its name, with its file name under it. Mod tracks get their own ids, so they never clash with the game's tracks. The code is in src/core/modTracks.ts.
Older builds (Alpha v1 and the test builds) are in docs/CHANGELOG.md.
Checked against the last open line of the "Starter career slice" checklist (Systems Specification section 22): the Local Champion championship (3 rounds, one per track, 16 riders with qualifying) awards the badge, and the main area championship (6 rounds) then unlocks.
championships.json (checked at start-up): the Local Champion Championship (rounds at Farmland MX, Riverside Arena and Longmoor Enduro) and the Area 1 Championship (two rounds at each, in the same order), both 50cc (Spec 12.5, 18.6).area2.ready, which nothing sets yet). Entering is free; each round is entered at its own track's race office, where Local Champion round N replaces the local race day while your next round is on there (Spec 18.6, 6C). There is no calendar, so a championship waits until you ride its next round.buff in championships.json. Normal race days and challenges are unchanged.kerbs in vehicles.json). Two-lane roads are driven on the left: east in the top lane, west in the bottom one, north on the left, south on the right. Steering and click-to-drive keep to the lane and a U-turn swaps lanes; junctions, car parks and entrances shorter than 4 tiles have no lanes. Too long to turn round on a two-lane road, the hauler turns at junctions instead.The Map button (or M) opens Boss's world map: Areas 2 to 8, the Race Hub with its tracks, Home Town and the Industrial Zone, the Tracks badges and the roads between them. The only marker is your biggest bike, in its brand colour with no outline, standing in the middle of the zone you're in. Inside a building, that's the zone of the map its door is on. Travel is still by the roads out.
tools/art/world-map.py, which draws the map, a version of Home Town and the Industrial Zone without their little pictures, and a map bike for every class and brand.data/world.json worldMap lists each zone's maps and where its bike stands (src/core/worldMap.ts).Every step of the opening chain shows where to go next (src/core/waymarks.ts, drawn by src/world/Waymarks.ts):
Markers come from story.json and the maps' doors and exits, so a new step needs no marker data. They never point down a road that is still shut. Reduced effects (Settings) keeps them still.
talk rule with sets in npcs.json is said once).challenges.json, src/core/challenge.ts). Mickey Alington at the Home Town practice track gate races you for £50, 8 riders over 3 laps. Dan Smyth by the Industrial Zone practice yard races you one on one for £70 over 3 laps. Win, and you get your entry back plus the same again; anything but first wins nothing. Win or lose, you can race again straight away, with normal wear and XP. Each challenge needs its own new track, so until that track is in tracks.json the challenger says it's still being built. Both tracks are now in (Boss, 29 Oct 2026): Home Town Practice (challenge-home) and Industrial Zone (challenge-industrial), so both challenges are open.tracks.json are replaced by Boss's versions from the track editor. The example mod track is now First Try MX (public/mods/tracks/first-try-mx.track.json); the Farmland copy and the Industrial Zone draft are gone from the mods folder.
challenges.json, to balance with Boss, ready for Areas 2 to 8 to aim at bigger classes.training.json, src/core/training.ts).racing.json sim.fitness), at level 99:
Wheels and tyres can't be repaired or sold to any shop (consumables in shops.json). Ride them until they hit 0% and break, then buy a new set. Buying and fitting a new set in the shop trades in the set on the bike for money off: the old set's new price × its condition, the full amount one grade up and a third less for each grade beyond, nothing from 4 grades up, and never more than half the new price (tradeIn in src/core/shops.ts; table in alpha-v1.1/tyres/tyre-trade-in.md in the project files). A set bought as a spare and fitted later at the garage still puts the old set in your bag. The scrapyard owner's repair errand no longer lends tyres.
The driving controls and feel are unchanged (no driving or physics code was touched), Home Town's map file is byte-for-byte the same (pinned by a hash test), and the race-day camera stays fixed.
src/world/VanView.ts)., and . shorten and lengthen it, a click or Enter places it and Esc cancels. A piece must join the end of the last one (gaps and kinks over 20° are refused with the reason); the piece that meets the first closes the lap. Ready to race runs the game's checks. The game leaves draft tracks out. Existing tracks are unchanged., and . shorten and lengthen it, it shows green or red with the reason, a click or Enter places it and Esc cancels. Move start straight and Remove start straight are beside it. The race starts from the gate along it and the run to the lap is not counted as a lap. Start board official (with a picture of the official and board) picks the official in Scenery or selects the one placed; it can be placed, turned and routed before there is a start straight, and stands where placed until there is one. Checks on a new track say when the start straight, the official or its route is missing. Raise and Lower now go to ±36 m (was ±24 m, 1.5 times), with a 3 m strength added and a message when a dab reaches the limit; nothing is clamped silently. Where the start straight runs into the lap on sloping ground, it eases to the lap's level so the two surfaces meet. Tracks without elevation (all the shipped ones) are unchanged.[ and ] keys, or Shift + middle-drag to turn freely. Clicks land on the ground under the pointer at any angle; the race keeps its fixed camera.Tests: npm test (232 tests) and npx tsc --noEmit pass. For the elevation tool overhaul, a Playwright suite drove the editor's UI and race view through 21 checks, all passing: the Height pane opening on Raise the track with its length and height; the preview highlighting 16 units centred under the pointer on a straight, on the map and as a band in the race view, changing at once with the length setting, following the route round a corner, and changing nothing; a click applying exactly the previewed stretch; a raised straight with its peak at the centre, monotonic, symmetric and back to level at both ends; a lowered straight the same; a raised corner with every lane's position, banking, centre profile and skirt byte-identical; a hill on a section boundary changing no section or feature; a hill over the finish line wrapping as one hill; the same stretch clicked twice more stepping one hill to 3 m; undo and redo; the riding surface's edges exactly on the surface model through the hill with the bank's foot under the ground; the grass side graded from the track's level down to the land at no more than 1 in 1.5 on the terrain mesh with the ground texture; collision matching the surface; the five hills saved and reloaded identical with the track still race-ready; and the shipped tracks byte-identical. Unit tests cover the hill profile, wrapping, cutting at open ends and overlap, the lift and the unchanged cross-section on Farmland, continuity, grades, the steep warning and the height error, the schema and a race. Then the holder walk and four full races (Race 8×, 4×, 2× and 1×, 16 riders, 5 laps) on the suite's track with its five hills all finished in order with every rider on 5 laps, nobody stuck or going backwards and no errors, riders slowing over the 3 m hill. For the first-marker, first-corner and free-placement refinement, a Playwright suite drove the editor's UI and race view through 36 checks: the first click shown at once with its preview, undone, redone, dragged while drawing, place-move-place reversed by three undos, Esc clearing the preview; a route of five points with two rounded corners making one plain section and no typed corners; a flat corner on a straight, a hairpin on a 90° corner and a rutted corner on a sweep placed by hand, stretched, moved and the route reshaped under them with every type kept and no shape warning; a feature placement cancelled and undone leaving everything as it was; the start straight joined with no First corner section made, the first corner reported from the join to the next point and moving with the join; the draft saved, reloaded and made Race-ready; Farmland byte-identical with its own first-corner section kept, and Use features keeping every corner type. Unit tests cover the first corner's span, its own timed stretch each lap, its difficulty applied to that stretch only, lap 1's incident landing in it, and any type on any drawn shape passing the layout check. For refinement 4, three more Playwright suites drove the editor's UI and race view through 35 checks, all passing: every kind of join (straight to corner, corner to straight, straight to jump, jump to straight, corner to hairpin, hairpin to straight, turned and mirrored) leaving every earlier section's points, metres and type unchanged, heights under the track kept, the start straight added and the lap closed with nothing moved, saved and reloaded identical, a section deleted leaving a gap with nothing else moved; five moulding points on straights, jumps and the start straight, a middle point dragged moving only its own section's metres, undo, redo, save and reload; the boundary crossed by a dragged point and by a placed piece (named in Checks, not race-ready, reloaded as a draft, a second piece refused while one is out, far out refused, back inside ready again), scenery outside to the margin; and fans placed, set up, routed, refused on the track, saved and reloaded, built in the race view with their own timing, walking in at walking pace to exactly the end of the route, and reacting to a passing bike and resting. Unit tests cover the fans' checks and schema and the first-corner incidents and pile-ups (10–60% of races, sizes vary, in the first corner on lap 1 only, the player not always down, laps intact). For refinement 3, a second Playwright suite drove the editor's UI and race view through 29 checks, all passing: a circuit built and closed with no start straight (nothing laid, no finish line, valid draft, saved and reloaded); the finish line placed, moved, put on a selected point, dragged, removed, undone, saved and reloaded in place with no extra key; the start straight joined part way round and about a metre before and after the finish line with the lap untouched, Ready to race passing, an invalid join explained; the green ring dragged freely before there is a lap, placing a piece on it, dragging it along the lap, a broken join flagged and dragged back on; the Geometry warning for knife-edge corners and Round corner clearing it; and an existing track's checks, Reverse and export unchanged. Unit tests cover a start joining just before and after the line (5 laps, no extra or missing lap), the mitred corner (no lane folds, lip stands as a kerb, same on slopes and reversed, AI riders through), bikes kept moving and on the surface through the tightest corners of every shipped track, and a race on the track built in the suite. For refinement 2, a Playwright suite drove the editor's own UI and race view through 30 checks, all passing: building from a start straight placed first through a First corner and on round, rotating and moving pieces, the refusals and their reasons, Close the lap, a continuous loop, saving and reloading open and closed; deleting pieces (no track triangles left where they were, open ends shown, neighbours kept, old views disposed, undo and redo, repeated delete and close, save and reload with a gap); and the holder near the gate, mid-straight and at the far end, Plan walk, the walk timed in the race view itself (at A until 5 s, at B from 1 s, no jumps, the whole route walked), refusals, the start straight turned and moved, and save and reload. Then three full races (Race 8×, 16 riders, 5 laps) on the circuit built in the suite, with its holder, and one on Farmland all finished in order with every rider on 5 laps and no errors. In one of the three, a serious crash in the first corner held most of the field for about 15 seconds behind it, which is the race simulation's existing passing rule. For the earlier refinement, a brand-new track was built through the editor's own UI (start straight placed first, turned, moved, cancelled and undone, a lap built from its end and closed, saved and reloaded as a draft, the official placed, turned, routed, saved and reloaded, Ready to race passing), and full races (Race 8×, 16 riders, 5 laps) were run on Farmland flat, at ±24 m and at ±36 m (four times), and on the new track flat, on a 36 m hill and in a 36 m dip: every race finished in order with every rider on 5 laps, nobody stuck or going backwards, no errors. In-game runs through the real UI with Playwright: a full race on Farmland (Race 8×, 16 riders, 5 laps, results in order, no editor camera), an Auto Complete start on Farmland (riders still through the hold, board sequence, official in frame, gate drop at 0), all 10 Home Town doors walked in and out, a custom building walked into and out of, every route walked and the van driven out by a route.
Known limits: a finish line placed inside a bend splits that section, and a short remainder may then need retyping (the ghost warns; a straight is the usual place). Bikes drawn right on the edge of a knife-edge corner swing round its centre of curvature, a few centimetres back for a moment, while the surface there is a mitred point; the Geometry check names such corners. In deep valleys the fixed race camera can lose riders behind nearer high ground. Bikes dip up to about 0.6 grid units into the surface for a moment at some jump crests, flat or not (as before this change). Ground steeper than the 35% warning is still allowed. Opened straight from disk, the editor runs the published game, which gets these changes only once PR 20 is merged. The marshals reuse the running coach's sprite (no art for them yet). Buildings can't be rotated, since each picture is drawn for one view. The L-shaped engine rebuilder with lock-up is in the library but not placed on any map. The 35×18 example block fits on no shipped map and was tested on a blank map.
To resume: npm install, npm test, npm run dev, then open /tools/ (the toolkit) or /tools/track-editor.html or /tools/map-editor.html.
Testing aids to take out before the final release:
testPayMultiplier in world.json (5× for Alpha v1.1). The moneymoneymoney money cheat was removed for the Alpha v1.1 release.Logged so they are not forgotten, not planned for a build yet:
trackParts.json name a .glb under public/assets/, and match the scale (one grid unit is one metre). Static scenery first (bales, stands, arch, pit boards); riders and bikes need rigging and animation and come later.| Path | What it holds |
|---|---|
src/core/ | Game rules with no graphics: pathfinding, saves, settings, content checks, doors and exits, money, bikes and the opening chain (career.ts), story changes to maps (mapState.ts), skills and XP (skills.ts), the race simulation (race.ts), race days, practice and venues (raceDay.ts), and shops, repairs and spares (shops.ts). Covered by tests. |
src/scenes/ | Phaser screens: boot, menus, settings, the world, the on-screen HUD, and the race and practice screen. |
src/world/ | Drawing maps, characters and the van (VanView.ts). |
public/data/ | Game content as JSON: NPCs, dialogue, bikes, items, the opening chain (story.json), the world map, locks and shift jobs (world.json), shops and repairs (shops.json), and the vans (vehicles.json). Every file is checked when the game starts. |
public/assets/ | Art and baked maps, written by the import tool. Don't edit by hand. |
tools/import-art.mjs | Copies the art from the shared art folder and bakes each Tiled map into one game-ready file. |
tools/index.html | The toolkit's front page (/tools/ beside the game), listing each editor as its own page, with placeholders for the outfit and character designers to come. |
tools/map-editor.html | Standalone map and tile editor for the game maps and the Tiled sources. |
tools/track-editor.html | Standalone editor for the race tracks in public/data/tracks.json. |
tests/ | Unit tests, plus checks that every door, exit and NPC on the real maps works. |
TypeScript, Phaser 3 and Vite, with Vitest for tests. Saves are JSON in the browser's storage; a desktop app wrapper (Tauri) with saves as files comes in a later build. None of the Adventure Land code is used.
When the art threads change a map or sprite, run the import tool against the shared art folder and commit the result:
npm run import-art -- /path/to/art
npm test
To update only the van sheets (from art/vehicles/sheets/map/) without re-baking the maps: npm run import-art -- --vehicles /path/to/art.
The editors are kept apart from the game as the Motocross RPG Toolkit: its front page is tools/index.html, published at …/tools/ beside the game (http://localhost:5173/tools/ with npm run dev), listing the Track Editor and the Map Editor, with the Outfit Designer and Character Designer to come. How to use each editor, mode by mode, is in docs/TOOLKIT_INSTRUCTIONS.md (the toolkit's own instructions, linked from its front page). The track editor builds everything from motocross tracks to supercross (triples, step-downs, dragon's backs, tunnels through a tabletop with the lap riding under it, podiums, pyro and a stadium tunnel). The track editor builds everything from motocross tracks to supercross (triples, step-downs, dragon's backs, tunnels through a tabletop with the lap riding under it, podiums, pyro and a stadium tunnel). To add a tool, put its page in tools/, add a card to tools/index.html, and add its file to TOOLKIT_PAGES in vite.config.ts so the build publishes it.
The race simulation (src/core/race.ts) decides every result. The rider AI (src/core/riderAI.ts) then acts the race out: each rider picks a line, brakes into corners and drives out, swings out to pass or tucks in behind, jumps, skims whoops, crashes and remounts, always reaching the end of each section when the simulation says. How each rider rides comes from their skills, their bike and their race message (src/core/riderProfile.ts), plus an optional style for CPU riders in riders.json (line, aggression, jumps). The race view (src/world/RaceView.ts) draws it all as an isometric 3D scene with three.js, in the spirit of Super Off Road. The track is a solid surface (src/core/trackSurface.ts): jumps have take-off faces, tables and landings, whoops and braking bumps ripple, berms bank up, hills rise out of the ground, and a raised lip and earth bank mark both edges. Each bike's wheels are put on that same surface, so bikes pitch over jumps, lean into corners and land on the track. The camera follows your rider (the orange one with the arrow), or the leader once you are out, and a map in the corner shows the whole lap, the start straight and every rider. Tall scenery such as stands and trees fades when a rider is behind it.
The race opens on the start straight: the field lines up behind the gate on a concrete pad, wider than the track so a row of 8 fits, in two rows of 8 for a full field, and the straight narrows as it runs onto the lap, where the lap's lip and bank open up so the two surfaces merge.
The gate you pick is your slot: gates 1 to 8 are the front row from one end to the other, 9 to 16 the second row behind them, and riders arrive at the line-up in gate order. A gate past the field's size, or one already taken, is refused rather than swapped.
The start procedure is the same for a Race and for Auto-complete. When the race opens, 4 front-row riders are already in their slots (more for a bigger field) and the rest wait scattered just behind the pad. Over about 6 seconds they ride up to their own slots at different moments and speeds, several at once, easing onto their lane line, without touching. A second-row rider only sets off once the front-row rider in their own lane has stopped in their slot, so second-row riders in lanes that are already filled go early while other lanes are still filling. The line-up is drawn from a seed made of the track and the gate order, so each moto lines up differently but the same race always looks the same. An official (drawn at 90% of their first size, board included) waits beside the straight near the gate (A) from the moment the race screen opens, with the START 30 board low and its plain white back out. When everyone is still and the 5-second hold starts they raise it face out and walk up the straight to B, upright at 5 and 4, turned sideways at 3 and 2, and lower it white side out at 1, just before the gate drops; they stay at B with it lowered for the rest of the race. A, B and the whole walk are planned per track (src/core/startOfficial.ts) clear of the track, its lip and slope, and the scenery, with room for every turn of the board, and a track with nowhere clear fails the checks. There is no countdown on screen; the board and the riders show it. The procedure runs in real time at any playback speed, and Pause stops it. Practice has no line-up or board.
After the flag each finisher rides a slow cool-down lap down the nearer edge of the track, in single file behind the finisher ahead on that edge, giving way to riders still racing (before, every finisher stopped in one heap on the track about 40 m past the line at Farmland, where riders still racing rode through them).
Riders sit on the race-day bike model from the vehicles thread (Boss, 25 Oct 2026: "use the model from the coloured race day rides"): a youth bike for the 50 to 85 classes and an adult bike above, in the bike's brand colours, with the rider in their gear colours (src/world/raceBike.ts). It only changes how a rider looks. The tyres touch the ground exactly where the old bike's wheels did, so every rider takes the same line round every track as before.
Scenery may not stand on the racing surface, the start straight included; the game's checks and the track editor's Checks refuse it (see the toolkit instructions).
npm test # unit tests and map checks
npm run build # type check and production build into dist/
art on each design).rider in npcs.json) and says they're the current Area Champion.tools/art character script in project files).career.champs), added when you first enter one, with no migration needed for that (the renamed ids below bring saves to version 5).public/assets/art/ui/badge-area1.png, drawn by tools/art/badge-area1.py in the reference palette). It shows on the final standings when you win the Local Champion Championship, and in the Task tab once won. A reward can name its picture with image in championships.json.practiceRiders on a venue in tracks.json). The backyard loop stays yours alone. The lap counter, XP and wear on the practice screen follow the clock, so stopping early counts only the laps you have ridden.riverside-arena.png, drawn by tools/art/arena-riverside.py in the reference palette), with double glass doors on the venue trigger in place of the MX track gate.area1-venue-riverside and area1-venue-longmoor, venues venue-riverside and venue-longmoor, and their track officials and route marshals. Saves move to version 5, and an older save's ids are renamed when it loads.errands.json, src/core/errands.ts). The scrapyard owner in the Industrial Zone lends you one of his worn parts (Grade 2 or 3, 30% to 70%, never broken) to get repaired at the garage and bring back. He pays you back the repair plus £5, to be balanced later. You get one job at a time, and the next one is offered straight away. The part is tagged as his in the save. It can't be fitted, sold or dumped (or put in the modifier machine, when that comes), and trying says "I don't own this part. I'm trusted to fix it and take it back to the scrapyard owner." It is repaired from the garage's Repairs tab.art/characters/tools/make_characters.py, npc-13 to npc-16).dialogue in npcs.json at a new dialogue key: the bubble turns orange again for everyone. When a new area opens, move his map and tile to the next road block. He waits until the tutorial is done, like the other NPCs outside the opening chain. Joseph Halden (npc-18) owns Farmland MX and runs its race office.public/mods/tracks/industrial-challenge.track.json) for Boss to brush up in the track editor. It has a concrete yard with tight corners and a chicane, and a mud half with whoops, ruts and berms.start_official scenery item. In Scenery, place it like any other item, then Draw route and click the points of the walk; points can be dragged, and Cancel and Reset route are there. The walk must be at most official.maxWalk grid units (8, in public/data/trackParts.json), keep out of solid scenery and the riders lined up at the gate, and end clear of the track; the race walks it between five and one second before the drop, with the board sequence unchanged. Farmland places it as in the reference picture.finish: false while unfinished): closing the lap and joining the start straight create nothing, and a closed circuit with no start straight or finish line is a valid draft that saves and reloads. Finish line (Start and finish, or + Finish line above the view) snaps a chequered bar onto the closed lap; placing it makes that spot the lap's first point (a point is added if none is there), splits and turns the sections round so the lap is laid out as before, and keeps surface patches in place; Finish here does the same for a selected point, Remove finish line takes it off, and the map and race view draw no chequer until one is placed. The start straight joins the lap anywhere, about a metre before or after the finish line included (a join just before the line makes lap 1 the start straight and a whole circuit; the old "first half of the lap" rule is gone); its end, the green ring, drags freely until there is a lap, then along the lap, and turns red with a Race start check when it is off the lap. While a piece is in hand a click on the start straight's points moves them unless the piece is joining there (the immovable green circle was the start straight's end, which placing mode swallowed and whose drag crashed without a lap). Checks are grouped Circuit, Race start, Finish line, Height and Geometry: a missing start straight or finish line is listed as still needed to race, never as a fault, with a ✓ line for each part in place; Ready to race asks for them. The race view's surface no longer folds inside a corner tighter than a lane is far from the middle of the track (the inner lip swept across the apex as a raised wedge): such a lane is mitred to the point where its straight edges in and out meet, bikes drawn in it swing round the centre of curvature instead, and Geometry lists each corner too tight for the edge to follow, with Round corner as the fix. Saved tracks are byte-for-byte unchanged.sim.firstCorner in racing.json: 30%) puts one to three riders down in the lap's first corner section, never always the player, and any crash can take a nearby rider down with it (sim.pileup: 35% within 0.8 s, at most 3); the start straight's bend onto the lap is not a corner section, so it never hosts the first-corner incident. The ground height range stays at ±36 m.layout in tracks.json when any point is smooth), the drawing the game races is generated from it, and jumps and special sections are features on the route from which the sections are generated. Drafts save at any state (a point, an open route, no start or finish, warnings), the Route box shows Draft / Draft with warnings / Ready for validation / Race-ready, and nothing becomes race-ready without Ready to race. Existing tracks load and save byte-identical, keep their sections, and race as before; see docs/TOOLKIT_INSTRUCTIONS.md.firstCornerSpan in src/core/trackGeom. (Since moved to the start straight itself: see the first-corner bullet below.)ts), which the race times as its own stretch and rides with the first corner's existing difficulty, skills, damage and lap 1 incident; a feature placed there (a berm, a rutted corner) rides as itself, and tracks saved with their own first_corner section keep it. Nothing is typed from the route's shape any more: between features the route rides as plain track, and every corner type (flat corner, berm, rutted corner, hairpin, fast sweeper) is a feature placed by hand, of any shape, keeping its type when moved or reshaped; the editor's and the game's checks no longer tie a section type to a drawn shape (layoutProblems in src/core/trackCheck.ts), while the geometry checks (self-crossings, corners tighter than the edge, the build boundary) stay.lapPlan's stretch -2, after the run from the gate, -1) and rides it with the first corner's rules (racing.json's first_corner: difficulty, skills, damage) and lap 1's first-corner incident; the rest of the start straight rides as the start (gate bonus, start skills) as before, and the section times panel names it. On a start straight of only two points it is the last quarter. First corner is gone from the section drop-down, no section row is marked as it, and a First corner section on an older track (the game's own four keep theirs in their data) rides and shows as a flat corner; the example mod track and the test fixture are cleaned up. The map draws the stretch blue, labelled First corner in Layout, and the route note and Checks give its length. Riders cooling down after the flag who took it within three seconds of each other heading for opposite edges now hold single file while they pull over, so they never ride through each other. src/core/trackGeom.ts (firstCorner), src/core/race.ts, src/core/riderAI.ts, src/scenes/RaceScene.ts, tools/track-editor.html (firstCornerLeg).public/data/buildings.json is a library of every building: a footprint of any size or shape (# solid, . walkable, space for none), the pictures it is drawn with (pieces of sheets), its doors into interiors and its return tiles. In the map editor (tools/map-editor.html), Buildings lists them; Place shows the building green where it fits and red with the reason where not; a placed building can be selected, moved, replaced or removed. Edit… and New… open the building editor: paint the footprint, add pictures, doors and returns, and New interior from this copies an interior as the building's own. Unfinished buildings save as drafts and can't be placed. The game checks every placed building against its entry (src/core/buildings.ts). Doors still work through the existing door and return objects (src/core/travel.ts).places and routes in public/data/world.json). A route marshal stands by each area's way out (Home Town, Industrial Zone, Farmland, Quarry, Woodland; guide: true in public/data/npcs.json) and reads its directions from that map's real exits, including shut roads. For a road with a choice of places, pick one with the marshal or at the road when you leave; the bus stop no longer fast-travels. Minimaps are unchanged. A new area needs only its exits, a route entry if an exit has a choice of places, and a marshal entry.