Underground 2 Revived
Play Need for Speed: Underground 2 (2004) in Chrome and Firefox with WebGPU graphics, Web Audio, up to 120 fps widescreen, controller support, free roam and Online races with friends. Fan project, not
Play medieval mercenary games: solo survival, 1v1 duels, and 2v2 skirmishes
Translation pending
AI summary · website and README
GamesHTML · JavaScriptGitHub @YOU-CANT-GUARD-MEOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Loading the full README. The saved excerpt is shown below.
BLOODSWORN — Mercenaries of the Ashen Realm.
A dark medieval top-down shooter: survive The Hunt solo, fight
The Duel (online 1v1, best of 3), or band up for Skirmish (online
2v2, best of 3) against strangers or your warband.Read the full README ↗A dark medieval top-down shooter: survive The Hunt solo, fight The Duel (online 1v1, best of 3), or band up for Skirmish (online 2v2, best of 3) against strangers or your warband.
public/index.html — loading screen + lobby (accounts, warbands, gold,
Hall of Legends)public/game.html — The Hunt (single-player waves)public/showdown.html — The Duel (online 1v1)public/skirmish.html — Skirmish (online 2v2)public/config.js — shared by all pages: server address + login tokenpublic/mercenary.js — draws a mercenary in a given look (lobby + games)public/maps.js — every map layout, per mode; public/terrain.js paints thempublic/coop.js — the co-op Hunt (loaded by game.html)public/gameclock.js — runs every game at 60 steps a second on any screenpublic/i18n.js — English and Korean text for every page (see Languages)server/ — Node server: HTTP API + WebSockets on one port
server.js — Duel matchmaking and authoritative round/score stateskirmish.js — Skirmish matchmaking (warband + public fill) and 2v2 matcheslobby.js — sign up / log in, warbands (parties)api.js — leaderboard, profile, Hunt resultsdb.js — Postgres access; creates its tables on startupauth.js — scrypt password hashing, session tokensarmory.js — the Armory's upgrades, prices and effectswardrobe.js — looks (colours, helm styles, bolt trails), prices, titlesevents.js — limited-time events (the Prism)maps.js — which Duel/Skirmish arenas exist and their spawn pointscoop.js — co-op Hunt rooms: gathering, relaying, payoutsAll accounts, gold and stats live in Postgres. The server creates its tables the first time it starts, so a new database needs no manual setup.
postgresql://user:[email protected]/neondb?sslmode=require.DATABASE_URL (Render: your web service →
Environment → add DATABASE_URL). Keep it secret: it's the database
password.The server refuses to start without DATABASE_URL.
cd server
npm install
DATABASE_URL="postgresql://…your Neon string…" npm start # http + ws on :8080
Then serve public/ with any static file server (e.g.
python3 -m http.server 5500 -d public) and open
http://localhost:5500. Pages opened from localhost talk to the server on
localhost:8080 automatically.
To test several players, use separate browsers or private windows: tabs in the same browser share one login, and the newest tab takes over.
Sign up with a name (3–16 letters, numbers or _, unique ignoring
case) and a password (6+ characters). Returning logs in from any
device. Passwords are hashed with scrypt; the browser keeps a random
session token, and the server stores only its SHA-256 hash. LEAVE (top
right) logs out and deletes the session. 5 wrong passwords lock that name
for a minute.
Gold: the Hunt pays bounty ÷ 10 when you die (retreating forfeits the run). A Duel pays 100 for a win and 25 for a loss; a Skirmish pays 150 and 40. Leaving mid-match forfeits it and pays nothing.
The Armory (ARMORY in the lobby) sells permanent Hunt upgrades, each with 5 levels costing 150 / 400 / 800 / 1500 / 2500 gold:
| Upgrade | Effect per level | Max |
|---|---|---|
| Hardened Mail | +20 max health | 200 HP |
| Deep Quiver | +6 bolts per quiver | 60 |
| Barbed Bolts | +20% bolt damage | +100% |
| Fleet Boots | +0.15 move speed | 4.55 |
| Firepot Satchel | +1 starting firepot | 8 |
| Field Medic | heal 5% of max health after each wave | 25% |
Prices and effects live only in server/armory.js. The lobby shows the
catalog the server sends, and the Hunt loads its starting stats from
/api/me. A purchase is one SQL update that re-checks the gold and the
current level, so double clicks or two devices can't overspend.
Your mercenary (MERCENARY in the lobby) is a dressing room with a
live preview. Four slots: cloak colour, helm style, trim & metal, and bolt
trail. A few of each are free; the rest are bought once with gold (300 to
1500) and can be worn any time after. Looks are cosmetic only and show
everywhere: your party slot portrait, the Hunt, and to opponents in the
Duel and Skirmish (where a ring in your side's colour keeps friend and foe
clear). Titles are earned, not bought: e.g. the Butcher for 100
Hunt kills, the Duelist for 10 Duel wins, Warmaster for 50 Skirmish
wins. The worn title shows in party slots and the Hall of Legends.
Colours and prices live in server/wardrobe.js; the server resolves a
player's chosen ids into colours and sends those to other players.
The Prism (event, 4–18 October 2026): in roughly 1 Hunt in 15, one shot fires as a rainbow bolt. Strike a foe with it to win the limited bolt trail, which can't be bought and can't be won after the event. The server rolls the chance when a run starts () and only grants the trail for that run (), refusing claims sooner than that many shots could take; a Hunt can start at most every 20s. Dates and odds are in . This keeps out casual cheating but a determined scripter could still claim it without hitting anything.
| Method | Path | Notes |
|---|---|---|
| GET | / | Health check |
| GET | /api/leaderboard | Top 10 Hunt bounties, Duel and Skirmish records |
| GET | /api/me | Your profile, upgrade levels and Hunt loadout (Authorization: Bearer <token>) |
| POST | /api/hunt | { score, wave, kills } for a finished Hunt (bearer token; one per 10s) |
| POST | /api/hunt/start | Begin a Hunt run; returns { runId, prismShot, event } (bearer token; one per 20s) |
| POST | /api/hunt/prism | { runId }: claim the rainbow-bolt hit for that run (bearer token) |
Lobby and Duel traffic goes over the WebSocket: hello {token},
signup/login {username, password}, logout, buyUpgrade {id}, buyItem {slot, id},
wear {slot, id} (slot title for titles), warband messages, then
findMatch and the match messages below.
The game is in English and Korean. The ⚙ button in the lobby header opens Settings, where players pick a language; it's saved in the browser and used by all three pages. A first visit follows the browser's language.
All text lives in public/i18n.js: STRINGS.en and STRINGS.ko hold the
same keys, and tr('key', { n: 3 }) fills in {placeholders}. The server
still sends English, so its error messages and Armory upgrade names are
translated in that file too (SERVER_MESSAGES, ARMORY_TEXT). If you add a
server message, add its Korean there or players will see it in English.
Movement and hotkeys in both games use physical keys (event.code), so they
work with a Korean keyboard input method switched on.
A warband (2–4) that picks The Hunt and presses TO BATTLE hunts together; solo players still get the normal Hunt.
game.html#coop. The run starts when the
whole warband has arrived, or after 12 seconds with whoever came. The
server picks the map. Someone who arrives late joins the run in progress.Every mode has three maps, one per look: Ashen Keep (stone dungeon), Blighted Wood (trees for cover, murky ponds) and Frozen Pass (snow, snow-capped rock, a frozen lake). The map is random every match: the server picks it for the Duel and Skirmish and tells the players (so everyone fights in the same arena), and the Hunt picks one each run. Its name shows on the first round's banner, or the Hunt's wave-1 countdown.
# (wall), . (floor) and ~ (water/ice: walkable)
in public/maps.js; all maps of a mode share its size.server/maps.js and must be
open floor. Duel arenas are rotationally symmetric and Skirmish arenas are
mirrored both ways, so no spawn is favoured.showdown.html#party,
which joins the line automatically.SKIRMISH in server/maps.js) must sit on open floor
in each arena (MAPS.skirmish in public/maps.js).roundStart with spawn points and resets health to 100.iHit. The server owns health and broadcasts it.Two services: the Node server on Render, and the static public/ site on
Vercel (or a Render static site).
server, build
npm install, start npm start, and set DATABASE_URL (see above).DEPLOYED_SERVER_HOST in
public/config.js to the Render hostname (no https://, no trailing
slash).public/.Render's free tier sleeps when idle, so the first visit after a while can take 10–30 seconds; the loading screen says the gatekeeper is slow to wake.
POST /api/hunt/startPOST /api/hunt/prismserver/events.jsHall of Legends (LEGENDS in the lobby) shows your record and the top 10 Hunt bounties and Duel records.