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
맞춤형 Warhammer 40k·Horus Heresy 군대를 구축하고 포인트를 계산하며, 19 진영과 상세 유닛 데이터를 제공합니다
Build and calculate points for custom Warhammer 40k and Horus Heresy armies with 19 factions and detailed unit data
AI가 요약 · README에서
게임TypeScript · JavaScriptGitHub @Rigzar온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
An army list builder for a custom Warhammer 40,000 / Horus Heresy ruleset, covering 19 factions with full unit data, weapons, options, archetypes, legacies, traits and psychic disciplines.README 전문 보기 ↗An army list builder for a custom Warhammer 40,000 / Horus Heresy ruleset, covering 19 factions with full unit data, weapons, options, archetypes, legacies, traits and psychic disciplines.
React · TypeScript · Vite · Zustand · Tailwind CSS
git clone https://github.com/Rigzar/custom40k-builder.git
cd custom40k-builder
npm install
npm run build # verify — must pass with zero TypeScript errors
npm run preview # serve the built app at http://localhost:4173
Do not use
npm run dev— always usenpm run buildto verify correctness andnpm run previewto test the built output.
custom40k-builder/
├── src/
│ ├── components/ # React UI components
│ │ ├── LandingPage.tsx # Faction selection + Developer Update announcement
│ │ ├── UnitCard.tsx # Individual unit card (options, armory, traits)
│ │ ├── ArmyConfig.tsx # Archetype / Legacy / Traits panel
│ │ ├── ArmoryModal.tsx # Armory item picker
│ │ └── PrintView.tsx # Printable army sheet
│ │
│ ├── engine/ # Game logic (points, validation, rules)
│ │ ├── points.ts # Points calculation — base cost + options + traits + armory
│ │ ├── resolver.ts # Unit profile resolution — marks, variants, archetypes, FACTION_RESOLVERS dispatch
│ │ ├── validators.ts # Army-wide validation — slot limits, archetype constraints, engagement limits
│ │ ├── keywords.ts # Keyword-derivation seam — armour/mark gating, Ordo/Legacy unlock helpers
│ │ ├── equipMods.ts # Parses stat/ability text out of an armory item's description
│ │ ├── transportGate.ts # "Low Move, no transport" selection-gate helper
│ │ ├── archetypes/ # Archetype rule registry — base.ts (ArchetypeRule shape) + index.ts (all archetypes) + per-faction subfolders
│ │ ├── codex_<faction>/ # Per-faction engine module (one per faction): keywords, legacies, traits, slots, special-abilities, weapon-abilities, resolver, digest.md
│ │ ├── legacies/ # Legacy-gated discipline/prayer rules (index.ts dispatcher + per-faction files)
│ │ ├── resolvers/ # FACTION_RESOLVERS implementations (injected abilities per faction)
│ │ ├── traits/ # Per-faction Army Trait effect tables
│ │ └── validators/ # Per-faction validation add-ons
│ │
│ ├── data/
│ │ ├── loaders.ts # Assembles FactionData from per-faction folder files
│ │ ├── changelog.ts # Version history (English)
│ │ ├── known-issues.ts # Bug and limitation tracker
│ │ └── rules-model/ # Per-faction keyword/rules digest (<faction>.md) — audit reference, not loaded by the app
│ │
│ ├── store/
│ │ └── army.ts # Zustand store — army state and actions
│ │
│ ├── types/
│ │ ├── data.ts # Unit, Weapon, OptionGroup, FactionData, OptionEffect…
│ │ ├── army.ts # RosterEntry, ArmyState, TraitSelection…
│ │ ├── unit-types.ts # Canonical UnitType union (Infantry, Bike, Jump Pack Infantry…)
│ │ └── keywords.ts # ChaosMark, ArmourKeyword, MARK_GLYPHS typed constants
│ │
│ └── i18n/
│ └── index.ts # UI translation strings (EN / DE / ES)
│
├── data/
│ ├── parsed/ # ← FACTION DATA — one folder per faction (all 19 factions)
│ │ ├── chaos_space_marines/
│ │ │ ├── units/ # one .ts file per unit, by slot
│ │ │ │ ├── hq/ troops/ elites/ ...
│ │ │ │ └── index.ts # assembles { faction, slot_to_units, units }
│ │ │ ├── armory/
│ │ │ │ ├── general.json # General armory
│ │ │ │ ├── mark_khorne.json
│ │ │ │ └── legion_*.json # One per legacy (Black Legion, Iron Warriors…)
│ │ │ ├── psychic/
│ │ │ │ ├── pacts.json
│ │ │ │ └── prayers.json
│ │ │ ├── archetypes.json # { archetypes[], legacies[], traits[] }
│ │ │ └── animosity.json # { animosity, allied } — only CSM/CD (marks)
│ │ ├── space_marines/ (same structure, no marks)
│ │ ├── chaos_daemons/
│ │ ├── ... (16 more factions, same units/ + armory/ layout)
│ │ ├── _supplements/ # horus_heresy.json, escalation/…
│ │ └── _scratch/ # Parser audit files — never loaded by the app
│ │
│ └── source/ # Original HTML source files used for auditing
│ ├── Chaos Space Marines ENG/
│ └── ... (one folder per faction)
│
├── Codex/ # Canonical rules sources (not pushed) — Core Rules/Missions .txt, one .ods per faction
│
└── scripts/
├── _html2txt.cjs # Strip HTML source to readable text for auditing
├── _scan_mojibake.cjs # Detect encoding artifacts in JSON/TS files
├── _normalize_unit_types.cjs # Cross-faction unit_type casing normalizer
└── _scan_cost_bugs.cjs # Scan for pricing bugs (per-model, fill-model)
Each faction lives in data/parsed/<faction>/. The loader in src/data/loaders.ts assembles the
individual files into the FactionData shape the engine expects.
units.json — core unit data:
{
"faction": "chaos_space_marines",
"slot_to_units": { "HQ": ["Chaos Lord", ...], "Troops": [...] },
"units": {
"Chaos Lord": {
"name": "Chaos Lord",
"slot": "HQ",
"models": [{ "name": "Chaos Lord", "points": 65, "min": 1, "max": 1, "stats": { "M": "6\"", "WS": "2+", ... } }],
"equipped_with": "Every model is equipped with: Bolt pistol; Power sword.",
"weapons": [...],
"option_groups": [
{
"header": "May replace Power sword with:",
"constraint": { "type": "one" },
"choices": [{ "name": "Power fist", "points": 10 }],
"inline_pts": null,
"per_model": false,
"variant_link": null,
"is_unique_per_army": false
}
],
"abilities": ["..."],
"unit_type": "Character Model",
"is_character": true,
"is_vehicle": false,
"is_psyker": false,
"champion_has_armory": false,
"has_veteran_abilities": true
}
}
}
Every faction uses a
units/folder, not a singleunits.json— the JSON shape above shows the logical structure, but on disk it's split into one.tsfile per unit (units/<slot>/<unit>.ts, each exporting aUnit), with per-slotindex.tsfiles that the faction's top-levelunits/index.tsassembles into the same{ faction, slot_to_units, units }shape. The unit object fields are identical — only the on-disk layout differs.
archetypes.json — Army Customisation data:
{
"archetypes": [{ "name": "Legionnaire Warband", "desc": "Full canonical rule text..." }],
"legacies": [{ "name": "Legacy of the Warmaster", "desc": "...", "armory_key": "Black Legion" }],
"traits": [{ "name": "Siege Experts", "desc": "...", "pts_unit": "5", "pts_char": "0", "pts_monster": "5", "pts_veh": "5" }]
}
armory_keymust match the key insrc/data/loaders.tsfor that faction'sarmory_legionsobject. If they diverge the legacy armory tab will not appear.
| Field | Type | Notes |
|---|---|---|
unit_type | string | Must use Core Rules canonical spelling — see src/types/unit-types.ts |
option_groups[].per_model | boolean | Set true when header says "for +X points per model" (inline options) |
option_groups[].effect | OptionEffect | Structured rule change: stat_mod, adds_unit_types, set_unit_type, grants_abilities |
armourKeyword | string | Innate armour class — drives ᵀ/ᴳ armory gating |
pts_monster / pts_veh | string | Shared "Monstrous Creatures & Vehicles" column — must be equal |
⚠️ This workflow is Alpha. The goal is to automate it, but it is not yet fully automatic.
The maintainer can review faction data directly from the canonical Google Sheets source by pasting the sheet URL. The process:
Codex/core_rules_text.txt, missions_text.txt) before a fix is appliedIf you have the source data for an unaudited faction, open a GitHub Issue with the link or paste the data — that immediately unblocks a full audit. See OPEN_QUESTIONS.md for the current list of open items.
Each archetype, trait, and legacy in the engine files has the canonical rule text as a comment directly above its code block:
// SOURCE — Siege Experts:
// "The unit gains the 'Sunder(1)' ability for all ranged attacks."
// COST: 5 | 0 | 5
'Siege Experts': [
{ type: 'weapon_ability', name: 'Sunder(1)', weapon_type: 'ranged', applies_to: 'all' },
],
This makes it immediately visible if the code drifts from the rule. When the two diverge, fix the code — not the comment.
See CONTRIBUTING.md for the full guide. Short version:
npm installnpm run build — must pass with zero TypeScript errorsOpen data/parsed/<faction>/units/<slot>/<unit>.ts, compare it against your copy of the rules, and fix whatever is wrong. See CONTRIBUTING.md for the fields to check and the file templates for adding missing armory/psychic/archetype files.
If you find an error but are not sure how to fix the JSON, open a GitHub Issue using the Data correction template.
If you know the game and can answer an ambiguous rule, check OPEN_QUESTIONS.md — answering a rules question directly unblocks an engine implementation. Use the Rules question issue template on GitHub.
src/engine/ — see CONTRIBUTING.md for the engine file mapsrc/components/src/store/army.tsnpm run build is the gateSee the Changelog button in the app, or read src/data/changelog.ts / src/data/known-issues.ts directly.
Open questions and help-wanted items: OPEN_QUESTIONS.md.