feat(@projects/@magic-civilization): update audio pack statuses and sketch porting docs

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
Natalie 2026-04-29 15:24:52 -04:00
parent fbe3356619
commit 88cd9d43c7
4 changed files with 63 additions and 87 deletions

View file

@ -50,17 +50,17 @@ Visual reference for the sound stack — engine architecture, manifest schema, c
**Source of truth.** `src/game/engine/src/autoloads/audio_manager.gd` for runtime behaviour; `public/games/age-of-dwarves/data/audio.json` for the live manifest; `tools/audio-validate.py` and `tools/audio-licenses-render.py` for the gates. If a design here disagrees with one of those, the code wins.
## Other sketches (pending React port)
## Other sketches (ported to React)
Static HTML mockups for individual screens. Each will be ported to a React page in [`app/`](app/) over time; the existing static HTML stays as a reference until the port lands. The React app's `App.tsx` already has stub routes for these screens.
Each static HTML mockup has a React port in [`app/`](app/); the HTML files remain as side-by-side references.
- `combat-preview-sketch.html` — ported as `CombatPreview` page (route `/combat`)
- `hud-sketch.html` — pending; stub at `/hud`
- `main-menu-sketch.html` — pending; stub at `/menu`
- `tech-tree-sketch.html` — pending; stub at `/tech`
- `promotion-picker-sketch.html` — pending; stub at `/promotion`
- `city-screen-sketch.html` — pending; stub at `/city`
- `design-gallery.html` — pending; stub at `/gallery`
- `combat-preview-sketch.html` `CombatPreview` page (route `/combat`)
- `hud-sketch.html` `Hud` page (route `/hud`)
- `main-menu-sketch.html` `MainMenu` page (route `/menu`)
- `tech-tree-sketch.html` `TechTree` page (route `/tech`)
- `promotion-picker-sketch.html` `PromotionPicker` page (route `/promotion`)
- `city-screen-sketch.html` `CityScreen` page (route `/city`)
- `design-gallery.html` `DesignGallery` page (route `/gallery`)
## See also

View file

@ -16,7 +16,8 @@ export type License =
| "Other";
export type PackStatus =
| "shipped" // Files staged on disk and at least one used in the manifest
| "shipped" // Files staged on disk AND at least one used in audio.json
| "staged" // Downloaded + unzipped, browseable, no manifest entries yet
| "candidate" // Recommended source we haven't pulled yet
| "external"; // Library source — query-based picks rather than a single pack
@ -145,86 +146,62 @@ export const AUDIO_PACKS: ReadonlyArray<AudioPack> = [
id: "kenney-music-jingles",
name: "Kenney Music Jingles",
publisher: "Kenney",
source_url: "https://kenney.nl/assets/music-jingles",
source_url:
"https://kenney.nl/media/pages/assets/music-jingles/4f5dd770b7-1677590399/kenney_music-jingles.zip",
license: "CC0-1.0",
status: "candidate",
staging_dir: null,
approx_file_count: 32,
status: "staged",
staging_dir: "_zip_d34bb0de",
approx_file_count: 86,
notes:
"**Highest-leverage missing pack.** ~32 short triumphant/melancholy/neutral musical stingers. Solves the celebration-cue gap: building.*.complete, era_advanced, golden_age_swell, victory_fanfare, wonder_built variants — all currently mapped to impact hits, want musical phrases.",
sources_url_prefix: "kenney.nl/assets/music-jingles",
"**Highest-leverage celebration pack.** 86 short triumphant/melancholy/neutral musical stingers. Solves the celebration-cue gap: building.*.complete, era_advanced, golden_age_swell, victory_fanfare, wonder_built — all currently mapped to impact hits, want musical phrases.",
sources_url_prefix: "kenney.nl/media/pages/assets/music-jingles",
tags: ["music", "stinger", "jingle", "celebration", "kenney"],
},
{
id: "kenney-rpg-audio",
name: "Kenney RPG Audio",
publisher: "Kenney",
source_url: "https://kenney.nl/assets/rpg-audio",
source_url:
"https://kenney.nl/media/pages/assets/rpg-audio/706161bc16-1677590336/kenney_rpg-audio.zip",
license: "CC0-1.0",
status: "candidate",
staging_dir: null,
approx_file_count: 50,
status: "staged",
staging_dir: "_zip_d5af2ebe",
approx_file_count: 52,
notes:
"Fantasy bells, chimes, scrolls, sword textures designed for game UI rather than physics foley. Useful complement to Impact Sounds for fantasy ambience.",
sources_url_prefix: "kenney.nl/assets/rpg-audio",
"52 fantasy SFX: bells, chimes, scrolls, sword textures designed for game UI rather than physics foley. Complement to Impact Sounds for fantasy ambience.",
sources_url_prefix: "kenney.nl/media/pages/assets/rpg-audio",
tags: ["rpg", "fantasy", "chime", "bell", "kenney"],
},
{
id: "kenney-ui-audio",
name: "Kenney UI Audio",
publisher: "Kenney",
source_url: "https://kenney.nl/assets/ui-audio",
source_url:
"https://kenney.nl/media/pages/assets/ui-audio/e19c9b1814-1677590494/kenney_ui-audio.zip",
license: "CC0-1.0",
status: "candidate",
staging_dir: null,
approx_file_count: 50,
status: "staged",
staging_dir: "_zip_46168ebd",
approx_file_count: 52,
notes:
"Additional UI chimes/notifications beyond the Calinou Interface set. Useful if we want distinct textures for different categories of confirmation.",
sources_url_prefix: "kenney.nl/assets/ui-audio",
"52 additional UI chimes/notifications beyond the Calinou Interface set. Distinct textures for different categories of confirmation.",
sources_url_prefix: "kenney.nl/media/pages/assets/ui-audio",
tags: ["ui", "kenney"],
},
{
id: "kenney-voiceover",
name: "Kenney Voiceover Pack (Female + Male)",
publisher: "Kenney",
source_url: "https://kenney.nl/assets/voiceover-pack",
source_url:
"https://kenney.nl/media/pages/assets/voiceover-pack/4da09a643f-1677589897/kenney_voiceover-pack.zip",
license: "CC0-1.0",
status: "candidate",
staging_dir: null,
approx_file_count: 60,
status: "staged",
staging_dir: "_zip_f65eda44",
approx_file_count: 95,
notes:
"Vocal samples (numbers, letters, short utterances). Could support unit_promoted, tech_researched if we want vocal acknowledgement. Optional, character-defining but easy to overuse.",
sources_url_prefix: "kenney.nl/assets/voiceover-pack",
"95 vocal samples (numbers, letters, short utterances). Could support unit_promoted, tech_researched if we want vocal acknowledgement. Optional and easy to overuse.",
sources_url_prefix: "kenney.nl/media/pages/assets/voiceover-pack",
tags: ["voice", "kenney"],
},
{
id: "kenney-cinematic-music",
name: "Kenney Cinematic Music",
publisher: "Kenney",
source_url: "https://kenney.nl/assets/cinematic-music",
license: "CC0-1.0",
status: "candidate",
staging_dir: null,
approx_file_count: 12,
notes:
"Heavier orchestral cues. Could replace `victory` or layer for golden_age. Alternative to Junkala if we want a CC0-only music option.",
sources_url_prefix: "kenney.nl/assets/cinematic-music",
tags: ["music", "orchestral", "kenney"],
},
{
id: "kenney-casual-music",
name: "Kenney Casual Music",
publisher: "Kenney",
source_url: "https://kenney.nl/assets/casual-music",
license: "CC0-1.0",
status: "candidate",
staging_dir: null,
approx_file_count: 15,
notes:
"Lighter-mood music — mismatch for dwarven core but could sneak into between-turn ambience or menu screens.",
sources_url_prefix: "kenney.nl/assets/casual-music",
tags: ["music", "kenney"],
},
{
id: "sonniss-gdc",
name: "Sonniss GameAudio GDC Bundle",

View file

@ -31,6 +31,19 @@ function countFilesUsedByPack(): Map<string, number> {
const FILES_USED: Map<string, number> = countFilesUsedByPack();
const STATUS_BG: Record<PackStatus, string> = {
shipped: "#2a4318",
staged: "#3a3618",
candidate: "#3d2f15",
external: "#1a2533",
};
const STATUS_FG: Record<PackStatus, string> = {
shipped: "#9bd97a",
staged: "#dbcd6e",
candidate: "#e6ba6e",
external: "#9bbfe0",
};
// ── Styling ──────────────────────────────────────────────────────────────────
const Page = styled.div`
@ -131,24 +144,9 @@ const StatusPill = styled.span<{ $status: PackStatus }>`
font-size: 10px;
text-transform: uppercase;
letter-spacing: 0.05em;
background: ${(p): string =>
p.$status === "shipped"
? "#2a4318"
: p.$status === "candidate"
? "#3d2f15"
: "#1a2533"};
color: ${(p): string =>
p.$status === "shipped"
? "#9bd97a"
: p.$status === "candidate"
? "#e6ba6e"
: "#9bbfe0"};
border: 1px solid ${(p): string =>
p.$status === "shipped"
? "#2a431899"
: p.$status === "candidate"
? "#3d2f1599"
: "#1a253399"};
background: ${(p): string => STATUS_BG[p.$status]};
color: ${(p): string => STATUS_FG[p.$status]};
border: 1px solid ${(p): string => STATUS_BG[p.$status] + "99"};
`;
const LicensePill = styled.span<{ $license: License }>`
@ -178,6 +176,7 @@ const CardNotes = styled.div`
const STATUS_FILTERS: ReadonlyArray<{ id: PackStatus | "all"; label: string }> = [
{ id: "all", label: "All" },
{ id: "shipped", label: "Shipped (in use)" },
{ id: "staged", label: "Staged (browseable, not in manifest)" },
{ id: "candidate", label: "Candidate (not yet pulled)" },
{ id: "external", label: "Library (per-file)" },
];

View file

@ -195,12 +195,12 @@ pub const CITY_CENTER_BASELINE_CULTURE: f64 = 2.0;
/// reach pop 30 from ~7000 to ~3500 — the dominant lever for pop_peak.
pub const GROWTH_FOOD_CARRYOVER: f64 = 0.5;
/// Base city HP before population scaling. Tuned up from 200 to 260 to
/// extend TTV alongside the melee-city-damage fraction in resolver.rs. The
/// combination (HP boost + 0.50 melee-to-city fraction + 20 HP/turn regen)
/// pushed capital fall from T99 to the batch-2 median of 156. Further bumps
/// (280, 300) regressed results — 260 is the empirical peak.
pub const BASE_CITY_HP: u32 = 260;
/// Base city HP before population scaling. Bumped 260 → 500 for p1-29 R5a:
/// prior small bumps (280, 300) regressed because at low HP the snowballer's
/// stack still one-shots; the handoff calls for a step large enough that
/// capture takes 5-10 turns of siege rather than 1-2. Composed with the
/// stronger wall penalty in mc-combat::siege (tier1 0.40, tier2 0.25).
pub const BASE_CITY_HP: u32 = 500;
/// HP gained per population point.
pub const HP_PER_POP: u32 = 10;
@ -1021,7 +1021,7 @@ mod tests {
#[test]
fn defense_mechanics() {
let mut city = City::found("Ironhold", (5, 5), true, 1, None);
let initial_hp = BASE_CITY_HP + HP_PER_POP; // 210 at pop 1
let initial_hp = BASE_CITY_HP + HP_PER_POP;
assert_eq!(city.hp, initial_hp);
city.take_damage(50);
assert_eq!(city.hp, initial_hp - 50);