City Service Window & DMV
A click-through mock of the two in-city desks at City Hall — the City Services window and the DMV instructor — rebuilt button-by-button from the live code so you can confirm every option, field and fee. Tap any menu row to open the sub-menu, input form or dialog that sits behind it. Labels are exact; values are mock. Gaps are flagged gap.
What these are
Both desks stand inside City Hall (Del Perro). They are talk-to-ped windows built on ox_lib menus + ox_target — no NUI.
City Services window (resource crestwood_doj) is the main citizen counter: get your ID, request a license, file a form, register for the Bar or a professional exam, pay/collect documents, raise an IT ticket, and message DOJ officials.
DMV instructor (resource cw_dmv) stands a few steps away and runs the driving-license pipeline: written knowledge test → practical road test → issuance back at the City Hall counter.
Where they are
- City Services desk
- -1292.02, -572.11, 30.57 · hd 309.9 cityservices_1
- City Hall counter
- -1291.97, -572.21, 30.57 · hd 20.0
- DMV instructor
- -1300.69, -575.74, 34.37 · hd 43.3 dmv_1
The City Services desk ped is /placer-placed (registry cw_points); every callback is distance-gated to ~3 m or it returns "you are not at a City Services desk". The DMV instructor is also a cw_points collection (dmv_%d).
The intended citizen flow
Straight from the window's own "New in CrestWood — first steps" guide and the DOJ site's Quick Guide / Driver's Handbook (§5.2–§5.3). Rule: your first Basic ID is free; every other credential is billed by invoice and must be paid before issuance (Title V §5.1). No driver's license may be issued without a verified pass on both DMV tests.
1 · City Services window crestwood_doj
ox_target label "City Services" (fa-solid fa-building-columns, 2.5 m) opens the context menu titled "City Services". Tap a row to drill in.
📖 City Guide & Legal Help fa-solid fa-book-open ▸
Opens a sub-menu of four read-only info pages (each an lib.alertDialog).
🚩New in CrestWood — first stepsfa-solid fa-flag▸
2. Set up your phone; it auto-creates your email and mails you the getting-started guide.
3. Set up your DOJ account passcode at any City Hall DOJ terminal (or the phone DOJ app — §4.1).
4. Want to drive? Visit the DMV instructor: pass the written test, then the road test, then have a Clerk issue your license at City Hall (§5.3). You must carry your Basic ID in your pockets to sit either test.
🔒Your DOJ accountfa-solid fa-user-lock▸
🪪IDs & licensesfa-solid fa-id-card-clip▸
⚖️Legal helpfa-solid fa-scale-balanced▸
📄 Submit a Formfa-solid fa-file-lines ▸
Built live from the DB (document_templates where citizen_submittable=1 AND active=1), grouped by category. Empty state: "No forms are available for public filing right now."
📁Civil Filings3 form(s)▸
📝Small Claims Complaint$150 fee▸
Field types map text→input · textarea→textarea · date→date · select→select. On submit → crestwood_doj:cs:submitForm(tpl.id, payload); a $150 cw_invoices row is raised titled "Small Claims Complaint filing fee". Notify: "A clerk is on duty — your filing was sent to the Clerk's office for review." / "Your filing has been submitted to the Clerk's office."
📝Name Change PetitionNo fee▸
A template with a fee but no fields shows "File this form for a $N fee?" instead.
📁Family & Personal2 form(s)▸
Same pattern — e.g. Marriage Application, Records Correction Request. Each opens its own confirm alert or field dialog built from its fields_json.
📋PermitsBuilding / door & garage move permits for your propertyfa-solid fa-file-contract▸
conditional / dead Only renders if resource crestwood_property is started — but that resource is retired & stopped (housing moved to ps-housing/ps-realtor). So this row, Legal Filings, and Request a Contractor below do not currently appear in-city.
⚖️Legal FilingsFile a stay, or pay to cure a foreclosure/eviction (§12)fa-solid fa-scale-balanced▸
conditional / dead Fires crestwood_property:client:openLegalAid — gated on the retired property resource.
🦺Request a Contractor / Work PermitGet work done on a property you ownfa-solid fa-helmet-safety▸
conditional / dead Opens an lib.inputDialog with one field "Work description" (textarea, required) → crestwood_doj:cs:requestContractor. Gated on the retired property resource.
📑 Request a Certified Copyfa-solid fa-copy Fee $500 ▸
Fee = Config.Documents.reprintFee = $500 → a cw_invoices row "Certified copy — Marriage Certificate" + a queued print_jobs row. Success: "Your certified-copy request has been sent to the Clerk's office for printing." Matches the posted Fee Schedule (Certified Reprint — $500).
🪪 Request Identification or Licensefa-solid fa-id-card ▸
Six credential types. Each row shows "On record — <status>" or "Not yet issued" and opens its own sub-menu.
🆔Basic IDNot yet issued1st FREE▸
ℹ️Info: requirements & fee▸
Your FIRST Basic ID is issued instantly and free of charge (§5.2). Later basics and lost/damaged replacements carry the posted fee.
🆕Request my first Basic ID (FREE)▸
First-ever → free, filed for a clerk to print. If already held, the row instead reads "Request a replacement" ($300). Subsequent (non-first) Basic ID = $250 invoice.
🚗Driver's LicenseNot yet issued$250▸
ℹ️Info: requirements & fee▸
Requires: a completed application form
A first-time application is never instant — file it at a DOJ terminal or the phone DOJ app under Licensing.
Web pipeline (licensing.php) additionally blocks the application unless a completed DMV pass is on record: "No completed DMV examination is on record…"
✍️Apply for a new Driver's LicenseNever instant — routes to the licensing pipeline▸
🔫Weapons LicenseNot yet issued$750▸
Info alert: Fee $750 · Background check required · Waiting period: 3 day(s) · requires a completed application form. "Apply for a new Weapons License" routes to the licensing pipeline; if held → "Request a replacement" ($300).
🏹Hunting LicenseNot yet issued$300▸
Info alert: Fee $300 · Prerequisite: an active weapons · Waiting period: 2 day(s). Routes to the licensing pipeline; replacement $300.
🎣Fishing LicenseNot yet issued$150▸
Info alert: Fee $150. Routes to the licensing pipeline; replacement $300.
🏢Business LicenseNot yet issued$500▸
Info alert: Fee $500 · requires a completed application form. Routes to the licensing pipeline; replacement $300.
Non-Basic credentials are never issued at the window — they route to the licensing pipeline (form → background check → wait → Clerk issuance). Fees shown come from license_types (seeded by v2_seed_license_fees.sql). Replacement of any credential = Config.CityServices.replacementFee = $300.
🧾 Check My Documents & Invoicesfa-solid fa-file-invoice-dollar ▸
📦My Documents — PickupCollect credentials & certified copies waiting for youfa-solid fa-box-open▸
📦Basic ID 8U51K657BReady to collect — DOC-26-0912▸
→ crestwood_doj:printer:collectMyPickup(row). Errors surface as "your inventory is full — make room and try again" / "that item is not ready for pickup yet".
Rows are print_jobs a clerk marked ready_pickup. Empty state: "Nothing waiting for pickup".
💵My InvoicesOpen your invoice list (same as /invoices)fa-solid fa-file-invoice-dollar▸
Validates via crestwood_doj:cs:canOpenInvoices then runs ExecuteCommand('invoices') — the same invoice list as the /invoices command. This is the primary pay-invoices channel.
⚖️ Register for Examinationfa-solid fa-scale-balanced ▸
⚖️Bar ExaminationLegal practice licensing exam$5,000▸
→ crestwood_doj:cs:barRegister. Success: "Registered — code F7K2Q9ZB emailed to you. Pay invoice INV-26-000771 ($5,000) here at the window, then use any DOJ terminal." Fee = exam_config.fee for bar (posted Fee Schedule: Bar Examination $5,000).
🎓Business OwnerProfessional licensing exam (registration only — question bank added later)▸
no question bank Registration works (code + invoice), but the exam itself has no questions yet. Same for the other six below.
🎓IT ProfessionalProfessional licensing exam (registration only — question bank added later)▸
no question bank prof_it_professional
🎓RealtorProfessional licensing exam (registration only — question bank added later)▸
no question bank prof_realtor
🎓ContractorProfessional licensing exam (registration only — question bank added later)▸
no question bank prof_contractor
🎓Event PlannerProfessional licensing exam (registration only — question bank added later)▸
no question bank prof_event_planner
🎓Insurance BrokerProfessional licensing exam (registration only — question bank added later)▸
no question bank prof_insurance
🎓ParalegalProfessional licensing exam (registration only — question bank added later)▸
no question bank prof_paralegal
🛠️ Submit an IT Work Ticketfa-solid fa-screwdriver-wrench ▸
→ crestwood_doj:cs:itTicket. Notifies all it-role DOJ users. Success: "Your IT work ticket has been filed — IT services have been notified."
✉️ Contact DOJ Officialsfa-solid fa-envelope ▸
→ crestwood_doj:cs:contactOfficials. Success: "Your message has been sent to the DOJ Notifications inbox of the selected official(s)." Error if no one holds that office: "no one currently holds that DOJ office — try again later".
🖊️ Property Closingsfa-solid fa-file-signature conditional ▸
conditional / dead Fires crestwood_property:client:openClosings. Only shown while crestwood_property is started — that resource is retired & stopped, so this option is not currently present in-city.
📋 Permit Queuefa-solid fa-file-contract conditional ▸
conditional / dead Fires crestwood_property:client:openPermitQueue — same retired-resource gate.
Every callback re-checks you are within ~3 m of a live City Services point, so these options can't be triggered remotely.
1b · City Hall counter cw_cityhall duplicate desk
A second, older ped counter (ox_target label "City Hall Services") sits at essentially the same coordinate as the City Services desk. This is where the in-game Driver License is actually granted — self-service, with its own separate slugs and fees.
🪪ID Card — $50▸
→ cw_cityhall:buyIdCard — charges $50 to the treasury society, grants the id_card item. Success: "ID card issued." Note this is a different credential from the DOJ "Basic ID".
📋My licenses▸
→ cw_licensing:mine. Each row: "<type> — <status>" · "<license_no> | expires: <date/never>". Empty: "No licenses on record".
🚗Apply: driver license — $250▸
no DMV check → cw_cityhall:applyLicense('driver') issues immediately for $250 with no verification of a DMV pass. Success: "License granted: LIC-xxxx".
🔫Apply: weapon license — $1500Requires a clean warrant record▸
Denied with an active warrant: "application denied — active warrant on record".
🏢Apply: business license — $1000▸
Immediate issuance.
🛠️Apply: crafting license — $500▸
Immediate issuance. (No matching web slug — see findings.)
🏹Apply: hunting license — $150▸
Immediate issuance.
🎣Apply: fishing license — $100▸
Immediate issuance.
Apply rows are generated from Config.LicenseFees (order not guaranteed — built with pairs). Admin /setcityhallped moves this ped.
🚩 Two counters, two fee tables, one spot
The cw_cityhall counter uses different slugs (driver / weapon) and fees than the crestwood_doj City Services pipeline (drivers / weapons). They disagree:
| License | City Hall counter | City Services / web |
|---|---|---|
| Driver | $250 driver | $250 drivers |
| Weapon | $1,500 weapon | $750 weapons |
| Business | $1,000 | $500 |
| Hunting | $150 | $300 |
| Fishing | $100 | $150 |
| Crafting / Construction | $500 crafting | $500 construction |
Decide which desk is canonical, then retire or re-price the other so a citizen can't get the "wrong" license path.
2 · DMV cw_dmv
ox_target label "Speak with the DMV Instructor" (fa-solid fa-id-card-clip, 2.5 m) opens the menu titled "CrestWood DMV". The ped only registers codes and runs the road test; the written test itself is taken at a DOJ terminal.
📘Take the Written Knowledge TestRegister a code + fee invoice for a classfa-solid fa-book▸
🚗Class C — Passenger Vehicle▸
Invoice INV-26-000820 has been issued for $250.
Once the invoice is paid, take this code to any DOJ terminal in the city and open the Bar & Examinations page to begin.
→ cw_dmv:written:register. Requires your Basic ID in your pockets, else "You must carry your Basic ID in your pockets to take a test." When the invoice is paid, the code flips to active and you're emailed to begin — no code needed at the terminal.
🏍️Class M — Motorcycle▸
Same flow, test vehicle faggio2.
🚚Class CDL — Commercial▸
Same flow, test vehicle mule.
Written test — rules & bank
- Fee
- $250 (charged at registration)
- Pass mark
- 80%
- Time limit
- 30 minutes
- Retake wait
- 1 day
- Per sitting
- 20 questions — 10 road rules, 5 signage, 5 right-of-way
- Question bank
- 70 DMV questions (36 road rules · 17 signage · 17 right-of-way)
Config lives in DB exam_config (exam = dmv); questions in exam_questions. Full answer key is on the Exams page.
🚗Take the Road TestRequires a passed written test + the road test fee paidfa-solid fa-car▸
misleading label The description says "the road test fee paid", but the server charges no road-test fee — Config.RoadTestFee = 150 is defined and never used (comment: "the written-test fee covers the whole licensing process").
🚗Class C — Passenger Vehicle▸
→ cw_dmv:road:request gates, in order:
- Basic ID in pockets — else "You must carry your Basic ID in your pockets to take a test."
- Written test passed for this class — else "You must pass the written knowledge test for this class first."
- Not already passed — else "You have already passed the road test for this class."
- Retake wait (24h) cleared
- A route exists — else no route in DB "No road test route has been placed for this class yet. Ask an admin."
On start, the test vehicle spawns at checkpoint 1 and you're warped in; for car/CDL the instructor rides shotgun, for motorcycle he narrates over the radio. A GPS route + yellow marker guide you to each checkpoint in order.
🏍️Class M — Motorcycle▸
Same engine; instructor narrates by radio.
🚚Class CDL — Commercial▸
Same engine; instructor rides along.
Grading (server-authoritative)
- Fail above 5 total errors (MaxErrors)
- Score = max(25, 100 − errors×15)
- Speed zones 50 / 80 / 120 km/h, +5 grace; each over-limit = 1 error (10s cooldown)
- Damage: 1 error per 20 damage; instant fail at 250 — "Vehicle damage exceeded the test limit."
- Mandatory stops: within 8 m at ≤2 km/h, else 1 error — "That was a stop sign back there!"
- Route: warn at 120 m, instant fail at 220 m — "You left the test route."
- Checkpoint arrival radius 12 m, reached in order
Result
Pass → writes dmv_test_passes; applicant told "Road test passed — visit City Hall to have your license issued by the Clerk." and every clerk is pinged "<name> has passed the … examination — issuance pending at City Hall." Instructor: "That's a pass. Head back to City Hall and have the Clerk issue your license."
Fail → writes cw_dmv_attempts (24h retake). Instructor: "That's a fail today. You're welcome to try again after the retake wait."
📋My DMV StatusWritten / road test status by classfa-solid fa-clipboard-list▸
Written: 90% | Road: 100% ✅ eligible for issuance
Class M — Motorcycle
Written: 85% | Road: not passed
Class CDL — Commercial
Written: not passed | Road: not passed
→ cw_dmv:status, read from dmv_test_passes.
License classes the DMV tests
| Class label | Slug | Test vehicle |
|---|---|---|
| Class C — Passenger Vehicle | car | asea |
| Class M — Motorcycle | motorcycle | faggio2 |
| Class CDL — Commercial | cdl | mule |
DMV tests only car / motorcycle / CDL — no boat, pilot or firearm class. Weapons/hunting/fishing are separate credentials issued at the counter, not by the DMV.
The issued license (mock)
Granted at City Hall after a verified pass — from the web issuance pipeline (licensing.php)- Holder
- Ava Marston
- Status
- Active
- Issued
- Jul 19, 2026 · by Clerk R. Doss
- Expires
- Does not expire
Issuance mints a stable per-soul number, writes licenses + issuances, and queues a credential print_jobs row to collect at the print desk. The web pipeline blocks issuance while the fee invoice is unpaid and (for drivers) requires a DMV pass on record.
Findings & gaps
🚩 Two service desks at one spot
City Services (crestwood_doj) and the City Hall counter (cw_cityhall) overlap at ~-1292, -572 with different license slugs and fees. Pick one as canonical.
🚩 Driver License bypasses the DMV in-game
cw_cityhall:applyLicense('driver') grants a $250 driver license with no check against dmv_test_passes. Only the web pipeline enforces the DMV pass, so the DMV tests are effectively optional if a player uses the counter.
🚩 7 professional exams are registration-only
Business Owner, IT Professional, Realtor, Contractor, Event Planner, Insurance Broker, Paralegal register a code + invoice but have no question bank ("question bank added later").
🚩 No road-test route exists yet
cw_dmv_routes is empty, so the road test errors "No road test route has been placed for this class yet" until an admin builds one via /placer → DMV Routes.
🚩 Dead / misleading road-test fee
The Road Test row says "the road test fee paid", but Config.RoadTestFee = 150 is never charged. Either drop the wording or wire the fee. (Note: the site's Fee Schedule labels the $250 as "DMV Practical Examination", though it's charged at written registration.)
ℹ️ Property options are gated on a retired resource
Property Closings, Permit Queue and the three property form entries only render when crestwood_property is started — it's retired/stopped, so they never appear now. Re-point them at ps-housing/ps-realtor or remove them.
Faithful button/field labels from crestwood_doj, cw_cityhall and cw_dmv; all record values are mock. Not the live portal.