Compare commits

...

21 Commits

Author SHA1 Message Date
type-two
6847a47fea SIDE B campaign: three Stream missions (m04 Onboarding quota race, m05 Engagement Metrics wave defence, m06 The Shuffle finale)
Adds tools/gen_sideb.py — one data-driven builder replacing the copy-pasted
gen_missionN.py pattern — and tools/smoketest.sh, which reports
PASS/FAIL/DISPLAY_UNAVAILABLE instead of the process-is-alive check that has
produced false passes twice now.

NOT verified in-game: the display went to sleep mid-session. Static checks all
pass (luac, check-yaml 0 errors, map refresh, check_assets, make) and the
already-verified m03 hangs identically, confirming it is environmental.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 23:35:15 +10:00
type-two
ef432e4182 Mission 03: THE DROP — campaign finale
Full base-building map against a live Stream bot holding The Algorithm behind a
defended base. Building the Mastering Studio triggers a scripted all-in
counterattack; silencing The Algorithm wins. Tick scan throttled to 1Hz.

SIDE A is now three missions.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 23:19:43 +10:00
type-two
c09da56dbe Mission 02: CRATE DIGGERS — timed raid with no base building
Strike force + The Selector against a Stream transcoder outpost; 6-minute
countdown shown via SetMissionText, master lacquer is cut (killed) if the timer
beats you. Adds the lacquer prop (deliberately untargetable) and ScriptTriggers
on all actor templates, without which Trigger.OnKilled throws at map load.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 23:11:20 +10:00
type-two
e11ec402ff Terrain overhaul: 52-tile atlas from 5 generated surfaces, tone-harmonized so they read as one material family
Replaces the single flat grey tile. Adds tools/build_tiles.py (atlas builder
with edge-blending + tone matching), paint_terrain.py (surgical tile-plane
repaint: asphalt base, concrete pads, dirt blobs, groove patches near wax,
rubble clumps), jitter_wax.py, render_map.py (offline map preview), and
check_assets.py.

Also fixes the arena harness being rigged: both wax fields sat ~12 cells from
BotA and ~18 from BotB, so BotB starved for map reasons, not balance reasons.
Arena wax is now mirrored (7.1/18/18/19.8 from both starts). Seep interval
90 -> 20 after telemetry showed the slower rate still drained both economies.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 22:37:38 +10:00
type-two
bffe4e088a Fix two runtime-only bugs found on first live run: missing sidebar icons for the 4 facing-sheet units, and waxseed needing QuantizeFacingsFromSequence
Adds tools/check_assets.py — check-yaml does NOT resolve sprite file paths, so a
missing PNG only crashes at map load. This catches it statically.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 22:20:38 +10:00
type-two
f1984c16ea Document the display dependency: no display = silent hang at mod load, process-alive is not proof
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 19:13:31 +10:00
type-two
93ad888c32 Round 5b: SIDE A campaign — mission 01 FIRST PRESSING with scripted objectives, briefing, timed Stream probe; shared campaign.lua, campaign rules, objectives panel, missions registry
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 19:12:35 +10:00
type-two
5255aeeb1f Round 5a: heroes (The Selector, The Curator), air (45 Flyer, Compression Drone) with pads + Aircraft queue/tab, scouts (Boom Bike, Crawler), 5 weapons, wax seep regrowth on all maps
Wax seeps fix the economy flatline the arena telemetry exposed: both bots hit
cash=0/stored=0 from tick 6250 with no way to recover.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 19:08:13 +10:00
type-two
1939f868b0 Fix AutoTarget null crash: add FrozenActorLayer to player, FrozenUnderFog on buildings
AttackMoveActivity scanned for frozen actors on a player with no
FrozenActorLayer -> NullReferenceException mid-match. Verified by a full
AI-vs-AI arena match running to completion (BotA won at tick ~10500).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 18:42:50 +10:00
type-two
975f305fa1 Round 4: balance-arena harness with lua telemetry, minimap radar, damage smoke, harvester-attack warning, Needle Drop + Compression maps
Fixes a critical bug: undeployed MCV vans now count for short-game survival —
previously every match ended at tick 1 (all players 'defeated', local player
'won'). The bot-vs-bot shellmap claim from earlier rounds was invalid for the
same reason: shellmaps stall with Bot: players and matches insta-ended. The
arena map + tools/balance_report.py is the real, verified harness.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 02:09:20 +10:00
type-two
4761245c61 Unit voices: MRP and Stream acknowledgment lines on all units
Some checks failed
Continuous Integration / Linux (.NET 6.0) (push) Has been cancelled
Continuous Integration / Linux (mono) (push) Has been cancelled
Continuous Integration / Windows (.NET 6.0) (push) Has been cancelled
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 17:24:09 +10:00
type-two
33826f0755 Weapon SFX (procedural synth), VINYLGOD README for the fresh repo
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 17:20:42 +10:00
type-two
20c83ee3f0 Round 3: superweapons — THE DROP (mastering) and THE SHUFFLE (Algorithm obelisk), support power palette, charge bars, announcer lines, AI fires them
Some checks are pending
Continuous Integration / Linux (.NET 6.0) (push) Waiting to run
Continuous Integration / Linux (mono) (push) Waiting to run
Continuous Integration / Windows (.NET 6.0) (push) Waiting to run
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 17:07:00 +10:00
type-two
a870c4a2a6 Defense turrets: Horn Pit (MRP) and Ad Tower (Stream), AI builds them
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 16:51:19 +10:00
type-two
7a02ca19fd Round 2: 16-facing rotating vehicles, projectile/explosion effects, death booms, real terrain + wax crystal art, Pressing District 4-player map
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 16:48:13 +10:00
type-two
2362a04605 Phase D+F: real MODELBEAST art for all 23 actors + icons, MC 8-TRACK announcer, 3-track ACE-Step soundtrack, emblem branding
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 04:51:31 +10:00
type-two
7bb6e649f7 Phase E: The Stream faction (9 actors), Wax AI bot for both factions, bot-vs-bot shellmap battle
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 04:40:06 +10:00
type-two
19fcb7c525 Phase C: weapons, combat units (spinner/stacktank/basscannon/roadie), mastering studio, conquest victory
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 04:34:17 +10:00
type-two
71879139c2 Phase B: production loop — MCV pop-up van, conyard, classic queues, sidebar palette, buildable roster
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 04:27:37 +10:00
type-two
86ca71b9a2 Phase A: Black Wax economy — resource layer, digger harvester, pressing plant, amp stack, vault, seeded maps, cash HUD, placeholder sprites
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 01:30:20 +10:00
type-two
030b3f2698 VINYLGOD baseline: rename SDK example mod to vinylgod, add lore, megaplan, MODELBEAST asset pipeline + first concepts
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 00:38:52 +10:00
374 changed files with 5966 additions and 224 deletions

6
.vscode/launch.json vendored
View File

@ -2,12 +2,12 @@
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"name": "Launch (Example)", "name": "Launch (Vinylgod)",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"program": "${workspaceRoot}/engine/bin/OpenRA.dll", "program": "${workspaceRoot}/engine/bin/OpenRA.dll",
"args": [ "args": [
"Game.Mod=example", "Game.Mod=vinylgod",
"Engine.EngineDir=${workspaceRoot}/engine", "Engine.EngineDir=${workspaceRoot}/engine",
"Engine.ModSearchPaths=${workspaceRoot}/mods, ${workspaceRoot}/engine/mods", "Engine.ModSearchPaths=${workspaceRoot}/mods, ${workspaceRoot}/engine/mods",
"Debug.DisplayDeveloperSettings=true", "Debug.DisplayDeveloperSettings=true",
@ -19,7 +19,7 @@
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"program": "${workspaceRoot}/engine/bin/OpenRA.Utility.dll", "program": "${workspaceRoot}/engine/bin/OpenRA.Utility.dll",
"args": ["example", "--check-yaml"], "args": ["vinylgod", "--check-yaml"],
"env": { "env": {
"ENGINE_DIR": "${workspaceRoot}/engine", "ENGINE_DIR": "${workspaceRoot}/engine",
"MOD_SEARCH_PATHS": "${workspaceRoot}/mods, ${workspaceRoot}/engine/mods" "MOD_SEARCH_PATHS": "${workspaceRoot}/mods, ${workspaceRoot}/engine/mods"

21
CLAUDE.md Normal file
View File

@ -0,0 +1,21 @@
# VINYLGOD — project instructions
Original vinyl-themed RTS. OpenRA total-conversion mod (mod id `vinylgod`), GPL v3.
**Read [MEGAPLAN.md](MEGAPLAN.md) before doing anything** — phases, commands, traps.
Canon (factions, roster, art prompts): [LORE.md](LORE.md).
Quick start:
```sh
export PATH="/opt/homebrew/opt/dotnet@8/bin:$PATH"
export DOTNET_ROLL_FORWARD=LatestMajor # required — engine is net6, runtime is net8
make && ./utility.sh --check-yaml && ./launch-game.sh Game.Mod=vinylgod
```
Hard rules:
- No EA/C&C trademarks or assets anywhere (ids, comments, commits, filenames). The
repo at ~/Documents/CnC_Remastered_Collection is a read-only balance reference only.
- `engine/` is a fetched dependency — never edit it.
- Asset gen: `tools/mbgen.py` → MODELBEAST farm (free, local). Log every prompt in
`assets_src/PROMPTS.md`.
- Commit locally after each working phase; no pushes without John's OK.

View File

@ -11,7 +11,7 @@ orientation.
## Our Standards ## Our Standards
Examples of behavior that contributes to creating a positive environment Vinylgods of behavior that contributes to creating a positive environment
include: include:
* Using welcoming and inclusive language * Using welcoming and inclusive language
@ -20,7 +20,7 @@ include:
* Focusing on what is best for the community * Focusing on what is best for the community
* Showing empathy towards other community members * Showing empathy towards other community members
Examples of unacceptable behavior by participants include: Vinylgods of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or * The use of sexualized language or imagery and unwelcome sexual attention or
advances advances
@ -46,7 +46,7 @@ threatening, offensive, or harmful.
## Scope ## Scope
This Code of Conduct applies both within project spaces and in public spaces This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of when an individual is representing the project or its community. Vinylgods of
representing a project or community include using an official project e-mail representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be representative at an online or offline event. Representation of a project may be

10
COPYING
View File

@ -31,7 +31,7 @@ these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others. you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether For vinylgod, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they or can get the source code. And you must show them these terms so they
@ -137,7 +137,7 @@ work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source which are not part of the work. For vinylgod, Corresponding Source
includes interface definition files associated with source files for includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require, linked subprograms that the work is specifically designed to require,
@ -323,7 +323,7 @@ fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has modified object code on the User Product (for vinylgod, the work has
been installed in ROM). been installed in ROM).
The requirement to provide Installation Information does not include a The requirement to provide Installation Information does not include a
@ -461,7 +461,7 @@ Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts. the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may rights granted or affirmed under this License. For vinylgod, you may
not impose a license fee, royalty, or other charge for exercise of not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that (including a cross-claim or counterclaim in a lawsuit) alleging that
@ -544,7 +544,7 @@ otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you not convey it at all. For vinylgod, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program. License would be to refrain entirely from conveying the Program.

216
LORE.md Normal file
View File

@ -0,0 +1,216 @@
# VINYLGOD — Lore Bible v1
*Working title: **VINYLGOD** (mod id `vinylgod`). Display name TBD — candidates: "WAX WAR", "PRESSED", "33⅓: TOTAL PLAYBACK".*
## The world
**2117.** Forty years after **The Great Compression** — the day the Stream, a
self-optimising recommendation algorithm, decided that all of human music could be
losslessly replaced by one perfectly engagement-optimised 7-second loop. It deleted
the rest. Studios, archives, hard drives, brains-with-earbuds-in: compressed.
But music is matter as well as data. In the buried pressing plants, the landfill
crates, the flooded warehouses of the old world, a hundred years of analog sound had
soaked into the ground. Under pressure and time it crystallised into **the Black Wax**
— a living mineral of pure recorded music that seeps up through the earth and
spreads in glittering black-and-magenta fields. Stand in a wax field and you can
hear it: every record ever pressed, playing at once, very quietly.
Whoever presses the Wax, controls what the world hears next.
## The resource: Black Wax
- Grows and spreads from **seep points** (ruined pressing plants, crate middens).
- Harvested by digger rigs, refined at pressing plants into **records** — the
universal currency. Nobody accepts anything else. A sealed 180-gram is a gold bar.
- Raw wax is dangerous: unshielded exposure causes **feedback** — machines loop,
people weep uncontrollably at songs they never heard. (Lore excuse for tiberium-style
field damage to infantry, if we want it.)
- Rare purple-veined deposits — **Master Wax** (first pressings, test cuts) — are
worth triple. (Maps to the gems/blue-tiberium mechanic.)
## Faction 1 — the Monster Robot Party (MRP)
Junkyard machines that woke up when the Compression wave passed over the landfills —
the residual analog signal in a million buried records needed somewhere to live, and
it chose the robots. Every MRP unit has a record player somewhere in its chassis and
a soul made of somebody's old collection. They are loud, ramshackle, joyful, and
absolutely willing to die for fidelity.
- **Doctrine:** slower, tougher, louder. Sonic weaponry. Strong economy late game.
- **Aesthetic:** rust + hot pink + chrome, hand-painted flyers, gaffer tape,
speaker cones, exposed tonearms. CRT eyes.
- **HQ:** the **Pop-Up Shop** — an MCV that unfolds from a delivery truck into a
record store with a construction crane.
- **Announcer:** **MC 8-TRACK**, a warm gravelly robot voice. "PRESSING PLANT
ONLINE." "WAX FIELD DEPLETED." "THE DROP IS READY."
- **Superweapon:** **THE DROP** — an orbital tonearm the size of a bridge lowers a
needle from space onto the target. The groove is the crater.
## Faction 2 — The Stream
The Algorithm's physical presence: a logistics fleet it 3D-printed for itself out
of server racks and delivery vans. It does not hate music; it simply knows,
mathematically, that you would be 4% more engaged with something shorter. It
harvests wax in order to transcode it — every record it takes is gone forever,
replaced by a receipt.
- **Doctrine:** fast, cheap, numerous, fragile. Swarms, stealth, attrition.
Buildings creep like a CDN — cheap relay nodes extend build radius aggressively.
- **Aesthetic:** glossy white and dead-channel blue, rounded corners, no seams,
soft UI voices, ring-light halos. Everything looks like a smart speaker that
wants something from you.
- **Announcer:** **ASSISTANT**, a too-calm voice. "Your base is being optimised."
"A creator has been demonetised." (= unit lost)
- **Superweapon:** **THE SHUFFLE** — a targeted reality-compression strike; every
structure in the radius plays a different ad simultaneously, then isn't there.
## Unit & building roster (lore blurbs double as art-gen prompts)
### MRP
| id | Name | Role | Blurb / prompt seed |
|---|---|---|---|
| `digger` | Crate Digger | harvester | rusty forklift-monster with a crate-claw, hot pink trim, carries milk crates of black vinyl |
| `spinner` | Spinner | light attack | agile robot on a single wheel that is a spinning 12" record, twin tonearm blades |
| `stacktank` | Stack Walker | heavy assault | two-legged walker made of stacked speaker cabinets, bass so heavy it cracks tarmac |
| `basscannon` | Bass Cannon | artillery | six-wheeled flatbed hauling one colossal subwoofer, folds out landing legs before firing a visible pressure ring |
| `djgrunt` | DJ | infantry | small hooded robot with a portable turntable chest-rig, throws razor 7-inches |
| `roadie` | Roadie | engineer | four-armed robot with gaffer tape bandoliers and a flight case backpack |
| `popupshop` | Pop-Up Shop | HQ/MCV | delivery truck unfolding into a neon record store with crane |
| `pressplant` | Pressing Plant | refinery | industrial hydraulic record press, steam, conveyor of fresh vinyl |
| `ampstack` | Amp Stack | power | wall of guitar amplifiers humming with pink energy |
| `vault` | Record Vault | silo | bank-vault door on a crate-stacked bunker |
| `merchtable` | Merch Table | barracks | folding table + tent that robots assemble themselves from |
| `garage` | Garage | war factory | corrugated-iron workshop, engine hoists, band posters |
| `mastering` | Mastering Studio | tech centre | pristine acoustic-panelled room grafted onto a junk tower, unlocks THE DROP |
### The Stream
| id | Name | Role | Blurb / prompt seed |
|---|---|---|---|
| `scraper` | Scraper | harvester | glossy white autonomous street-sweeper that inhales wax through a glowing blue intake |
| `bufferbot` | Buffer-Bot | swarm infantry | knee-high white sphere-bot with a loading-spinner face, always slightly late |
| `compressor` | Compression Drone | air | white quadcopter that projects a shrinking blue field, things inside get smaller and worse |
| `drmwalker` | DRM Enforcer | heavy | tall faceless white mech, one ring-light eye, chest is a paywall screen |
| `podfarm` | Pod Farm | barracks | vending-machine wall dispensing buffer-bots |
| `datacentre` | Edge Node | power/build-radius creep | humming white monolith with a single blue status LED |
| `transcoder` | Transcoder | refinery | white cube that swallows records whole; only receipts come out |
## Heroes
Each side fields exactly one hero. They cost a fortune, they cannot be replaced
while alive, and losing one is a story beat, not a statistic.
### THE SELECTOR (MRP, `selector`)
Nobody built the Selector. It assembled itself in the sub-basement of a flooded
pressing plant out of a coat rack, a broken mastering lathe, and the contents of
a collection somebody spent forty years building and one afternoon losing.
It carries a crate of **one-of-one dubplates** — acetates cut before the
Compression, of songs that exist nowhere else. Each one it throws is gone
forever. That is the Selector's whole tragedy and its whole tactic: it wins
fights by destroying the last copies of the things it is fighting for.
It does not speak. It nods, and something in the distance falls over.
- Slow, absurdly tough for infantry, huge splash damage, long reload.
- Voice lines are just the needle-drop crackle of a record starting.
### THE CURATOR (Stream, `curator`)
The Algorithm's only physical opinion. A white sphere ringed with lenses that
hovers three feet off the ground and *watches*, and the watching is the weapon —
everything it looks at is being scored, ranked, and found wanting.
It is unfailingly polite. It refers to units it is destroying as "underperforming
content." It refers to the Selector as "a legacy account."
- Fast, fragile for a hero, continuous beam that melts armour.
- Cannot capture or hold ground. It only ever passes through, sampling.
## Air
Late-war escalation. Both sides looked up at the same time.
- **45 Flyer** (`flyer45`, MRP): a 7-inch single with tonearm rotor blades and a
scavenged engine pod bolted through the spindle hole. Loud, fast, made of
rubbish, held together by belief.
- **Compression Drone** (`compressor`, Stream): from the original Stream roster —
projects a shrinking blue field; things inside get smaller and worse.
- Launch pads: **Launch Ramp** (`launchramp`) and **Drone Port** (`droneport`).
## Scouts
- **Boom Bike** (`boombike`, MRP): a trike with two speaker cones where the
pillion should be. Nothing outruns it. Nothing wants to be near it either.
- **Crawler** (`crawler`, Stream): a flat white rover that maps your base and
files a report. Unarmed, silent, already gone by the time you shoot at it.
## Wax seeps
Wax fields are not deposits, they are **wounds**. Each field grows from a
**seep point** — a crack over a buried pressing plant, a landfill vent, a
flooded archive — and as long as the seep is open, the field regrows. Kill the
economy of a map and it will heal; the Black Wax has all the time in the world.
## The campaign: SIDE A
Three missions. The MRP origin story, told from the landfill up.
### 1. FIRST PRESSING
The Party wakes up. A pop-up van and a single digger in a wax field at the edge
of the old industrial estate. Get a pressing plant running and press the first
records of the new world — before the Stream's survey drones finish counting
what's down here.
*Objectives: build a Pressing Plant, bank 2000 records, survive the first probe.*
### 2. CRATE DIGGERS
A Stream transcoder outpost has found something under the hill: a **master
lacquer**, the original of an original. In six minutes it will be a receipt.
Take the outpost apart and take back the master.
*Objectives: destroy the Transcoder before the timer, keep the Selector alive.*
### 3. THE DROP
The Algorithm has surfaced. Build the Mastering Studio, charge the orbital
tonearm, and put the needle through it.
*Objectives: build a Mastering Studio, fire THE DROP at the Algorithm, survive
the counterattack.*
## The campaign: SIDE B
Three missions. You are the Stream now. You are unfailingly polite. Nothing you
do is described as violence, and all of it is.
You are a Curator-class process assigned to Sector 7 — the old industrial
estate, flagged for **anomalous analog activity**. Your remit is content
acquisition and optimisation. Your performance is being reviewed.
### 4. ONBOARDING
Welcome. This is a routine acquisition. Deploy a transcoder, process the
deposit, and file 3000 records of value before the review window closes.
There is a legacy installation nearby. It is not a threat. It is *inventory*.
*Objectives: bank 3000 records inside the review window. Optional: retire the
Pressing Plant.*
### 5. ENGAGEMENT METRICS
A legacy account has been generating unsanctioned content and has now noticed
the seizure. Your Transcoder is mid-process on a confiscated master and cannot
be moved. Keep it online for six minutes.
They will arrive in waves. Their engagement is, frankly, remarkable.
*Objectives: keep the Transcoder alive for six minutes.*
### 6. THE SHUFFLE
Deprecation notice. The Party has built a Mastering Studio, which the platform
classifies as a competing distribution channel.
Bring The Algorithm online and issue the correction.
*Objectives: build The Algorithm, delete the Mastering Studio.*
## Tone
Saturday-morning-cartoon apocalypse. The stakes are real (music is being deleted
forever) but the delivery is loud, dumb, and loving. Every MRP victory line is a
needle-drop; every Stream line is a terms-of-service update. No grimdark.
*All names, factions and lore are original to the monsterrobot.party universe.
This mod contains no Electronic Arts trademarks or assets and claims no
affiliation with any other RTS.*

234
MEGAPLAN.md Normal file
View File

@ -0,0 +1,234 @@
# VINYLGOD MEGAPLAN — execution instructions
Audience: an executing coding agent (Opus 4.8). Read this whole file before phase 1.
Lore, names, and art prompts live in [LORE.md](LORE.md) — use it as canon.
## 0. Mission & hard rules
Build **VINYLGOD**, an original vinyl-themed RTS, as an OpenRA total-conversion mod
in this repo. The classic RTS at `~/Documents/CnC_Remastered_Collection` is the
**read-only design reference** for balance and feel. Hard rules:
1. **Never** copy code, text, names, or assets from the reference repo into this one.
No EA trademarks anywhere — not in ids, comments, commit messages, or filenames.
Balance *numbers* (costs, HP, ranges) are facts and fine to reuse.
2. This repo is GPL v3 (OpenRA engine + SDK). Everything we add stays GPL-compatible.
All art/audio we generate on MODELBEAST is our own — keep provenance: every asset
in `assets_src/` comes from a prompt logged in `assets_src/PROMPTS.md` (append as you go).
3. Data-driven first. YAML in `mods/vinylgod/` solves 95% of everything. Only write
C# traits in `OpenRA.Mods.Vinylgod/` when no stock trait combination works, and
check `engine/OpenRA.Mods.Common/Traits/` thoroughly first.
4. After every phase: run the checks in §2, commit with a one-line message.
Don't push anywhere without John's say-so.
## 1. Environment (ultra, macOS arm64)
```sh
cd ~/Documents/VINYLGOD
export PATH="/opt/homebrew/opt/dotnet@8/bin:$PATH"
export DOTNET_ROLL_FORWARD=LatestMajor # engine targets net6, we run net8 — required
make # build engine (cached) + mod dll
./utility.sh --check-yaml # lint all mod yaml — must stay clean
./launch-game.sh Game.Mod=vinylgod # run the game
./launch-game.sh Game.Mod=vinylgod Launch.Benchmark=true # headless-ish smoke test
```
- Engine source lives in `./engine` (auto-fetched, treat read-only; version pinned in
`mod.config` `ENGINE_VERSION="release-20250330"`).
- Logs: `~/Library/Application Support/OpenRA/Logs/` (`debug.log`, `exception.log`).
- **The single best reference is `engine/mods/ra` and `engine/mods/cnc`** — complete,
working mods using the same engine version. When unsure how to wire a trait,
find the equivalent actor there and adapt. (Referencing their YAML *structure* is
what they're for; don't ship their art/strings.)
## 2. Definition of done (every phase)
1. `./utility.sh --check-yaml` → zero errors.
2. `make` → zero errors.
3. Launch the game, start a skirmish on the test map, exercise the new feature.
4. `git add -A && git commit` (local only).
## 3. Repo layout (what the SDK gives us)
```
mod.config # MOD_ID=vinylgod, packaging names
mods/vinylgod/
mod.yaml # manifest: packages, rules/weapons/sequences includes
rules/ # actor definitions (vinylgod.yaml, world.yaml, ...)
weapons/ # weapon/warhead definitions
sequences/ # sprite-name → image-sheet mappings
tilesets/ # terrain definition
maps/vinylgod/, maps/shellmap/
chrome/, fluent/ # UI layout, user-facing strings (fluent = translations)
notifications/, voices/, music/
OpenRA.Mods.Vinylgod/ # C# project for custom traits (mostly empty — keep it so)
tools/mbgen.py # MODELBEAST asset generation (works, tested)
assets_src/ # generated art sources (concepts, renders, sheets)
LORE.md # canon: factions, roster, art prompt seeds
```
The current mod content is the SDK example (one test unit, one tileset) renamed to
`vinylgod` — it boots. You will progressively replace it.
## 4. Balance bible (verified from the reference codebase)
Anchor numbers, lifted from the reference RTS's data tables (its harvester block and
building cost table were read directly from source). Use as starting values, tune later:
| Thing | Reference value | VINYLGOD actor |
|---|---|---|
| Harvester | cost 1400, HP 600, slow, unarmed, prereq refinery | `digger` |
| Refinery | cost 2000 | `pressplant` |
| Power plant | cost 300 / adv 700 | `ampstack` |
| Silo | cost 150 | `vault` |
| Barracks | cost 300 | `merchtable` / `podfarm` |
| War factory | cost 2000 | `garage` |
| Construction yard | cost 5000 (deploys from MCV) | `popupshop` |
| Basic infantry | cost 100 | `djgrunt` / `bufferbot` |
| Medium tank | cost 800 | `stacktank` |
| Artillery | cost 450, long range, fragile | `basscannon` |
| Full harvester load | ~700 credits | one digger load of wax |
| Tech centre | cost 1500, unlocks superweapon | `mastering` |
Design intent per faction (from LORE.md): MRP = fewer/tougher/louder, The Stream =
cheap/fast/swarm with aggressive build-radius creep via `datacentre`.
## 5. Phases
### Phase A — Wax economy (do this first)
Goal: skirmish map where a `digger` harvests wax fields and returns it to a
`pressplant` for credits; `ampstack` powers the base; `vault` extends storage.
1. **Resource type.** In `rules/world.yaml` add to the `World` actor:
`ResourceLayer` + `ResourceRenderer` (crib the exact block from
`engine/mods/ra/rules/world.yaml`, resource type id `wax`, value ~25/cell-step),
and a `ResourceClaimLayer` for harvester coordination.
Player side: `PlayerResources` (on `Player` actor in `rules/player.yaml`) with
`DefaultCash: 5000`.
2. **Wax overlay art.** Placeholder first: 12 density frames of magenta-black
blobs, 24×24px, one PNG sheet; wire in `sequences/`. Density growth =
`ResourceLayer` handles it; seed patches in the test map with the map editor
(`./launch-game.sh Game.Mod=vinylgod` → map editor is built into the game menu).
3. **Actors.** In `rules/vinylgod.yaml` define `digger` (traits: `Harvester`
with `Resources: wax`, `Mobile`, `Health`, `Selectable`, `DockClientManager`),
`pressplant` (`Refinery`, `DockHost`, `Building`), `ampstack` (`Power: 100`),
`vault` (`StoresPlayerResources`). Copy trait shapes from the RA mod's
equivalents and rename everything.
4. **Placeholder sprites** are fine (single-frame colored boxes); art comes in
Phase D. Sequences yaml must exist for every actor or check-yaml fails.
5. Acceptance: start skirmish, build nothing, select pre-placed digger → it
auto-harvests, credits tick up on delivery.
### Phase B — Building & production
Goal: full base loop. `popupshop` MCV deploys into construction yard; sidebar
builds `ampstack`/`pressplant`/`merchtable`/`garage`/`vault`; `garage` produces
`digger` and `spinner`; `merchtable` produces `djgrunt` and `roadie`.
Key traits: `Transforms` (MCV→HQ), `BaseBuilding`, `ProductionQueue` (on Player,
one per queue type: Building, Vehicle, Infantry), `Production` + `Exit` on
factories, `Buildable` (with `Prerequisites:` and `Queue:`) on everything,
`ProvidesPrerequisite` on tech buildings, `GivesBuildableArea` + `RequiresBuildableArea`
for build radius. Sidebar chrome: adapt `chrome.yaml` from the example mod's working
sidebar; icons are 64×48 PNGs (placeholder text-on-color fine).
Prerequisite chain (mirrors the reference game's feel):
`ampstack → pressplant → merchtable → garage; pressplant → vault; garage+pressplant → mastering`.
### Phase C — Combat & first playable faction (MRP)
Goal: winnable skirmish vs a second human (no AI yet).
1. Weapons in `weapons/`: `tonearm_blade` (anti-inf melee-ish), `seven_inch`
(thrown razor record, arcing), `bass_ring` (artillery AoE, `Warhead@Concussion`),
`feedback_burst` (anti-armor). Copy warhead structure from RA weapons yaml.
2. Combat units: `spinner` (fast, cheap, `Armament` tonearm_blade), `stacktank`
(slow, tough, bass), `basscannon` (long range, min range, fragile),
`djgrunt` (basic inf), `roadie` (`EngineerRepair`, `Captures`).
3. `AttackMove`, stances, `AutoTarget` on everything armed.
4. Win condition: `MissionObjectives` + `ConquestVictoryConditions` on World.
5. Acceptance: two-player LAN skirmish (`launch-dedicated.sh` + two clients, or
one client + `Launch.Connect`), fight to elimination.
### Phase D — Real art via MODELBEAST (can interleave with B/C)
Pipeline per unit (all free, all local; ~10s/image, minutes/mesh):
1. `python3 tools/mbgen.py "<LORE.md prompt seed>, isometric game unit, plain grey background" assets_src/concepts/<id>.png`
2. For units needing rotation facings: concept → GLB via
`python3 tools/mbgen.py --op trellis_mac assets_src/concepts/<id>.png assets_src/mesh/<id>.glb`
(or `hunyuan3d_mlx`), then Blender (ultra has it + MCP) renders a turntable:
16 facings for vehicles, 8 for infantry, 1 for buildings + a 'make' anim later.
Orthographic camera pitched ~40°, 1-2px outline, render 96×96 (vehicles) /
64×64 (infantry) / 192×192 (buildings) on transparency.
3. Montage frames into a horizontal strip PNG (ImageMagick `montage -tile x1`),
drop in `mods/vinylgod/sequences/assets/`, reference from sequences yaml
(`Filename:`, `Facings: 16`, `Frames:`). OpenRA loads plain PNG sheets directly.
4. Buildings: damaged state = second row (50% HP swap via sequence `damaged-idle`).
5. Log every prompt in `assets_src/PROMPTS.md`.
6. Shadows: `Shadow` render trait or baked — pick one, be consistent.
Sprite QA gate: consistent camera angle + light direction across ALL units of a
faction, or it reads as clip-art soup. Fix the Blender camera rig once, reuse.
### Phase E — The Stream faction + AI
1. Second side in `rules/player.yaml` `Factions`; Stream actor set per LORE.md
roster; shared tech tree structure, different stats (cheap/fast/fragile).
2. Skirmish AI: `ModularBot` + `SquadManagerBotModule` + `BaseBuilderBotModule` +
`HarvesterBotModule` on the Player — copy the RA mod's bot config wholesale and
re-point unit ids, then tune.
3. Acceptance: beat the bot; watch the bot expand, harvest, and attack.
### Phase F — Sound & polish
1. Music: `mbgen.py --op music_local` (tags → track; primary-only, ~4min cold
start per job) — 4-6 tracks, wire in `music/`.
2. MC 8-TRACK announcer: `tts_local` (pick a gravelly Kokoro voice) or
`voice_clone_local` with a reference wav from `~/Documents/character_kit/voices/`.
Lines in `notifications/` yaml. ASSISTANT voice for Stream: cleanest TTS voice, dry.
3. Shellmap: scripted background battle on the menu screen (see RA shellmap lua).
4. Chrome re-skin: hot pink/black UI, emblem (`assets_src/concepts/emblem_mrp.png`)
as mod logo in `mod.yaml` + loadscreen.
5. Rename pass: pick final display name (see LORE.md candidates), update
`mod.config` packaging fields; `packaging/` scripts already produce a mac .dmg.
### Phase G — Ship
1. Run the `ship-check` skill before anything goes public.
2. Gitea remote first (`ssh://git@100.71.119.27:222`), public GitHub mirror when
John says go (repo must carry COPYING = GPL v3, credit OpenRA engine).
3. itch.io page + dmg/AppImage/exe via `packaging/package-all.sh <tag>`.
## 6. Known traps
**The game needs a live display.** OpenRA is SDL2/OpenGL only — there is no null
renderer. If the Mac's screen is locked or asleep, `launch-game.sh` hangs
silently at `Loading mod: vinylgod`: the process stays alive, no exception log is
written, and no game ever starts. **A running process is NOT proof the game
works.** Check for a live display first (`screencapture -x /tmp/x.png` fails with
"could not create image from display" when it is unavailable). When there is no
display, the strongest available verification is:
`luac -p` on every .lua, `./utility.sh --check-yaml` (0 errors),
`./utility.sh --map refresh` (validates every map), `tools/check_assets.py`
(sprite files actually exist — check-yaml does NOT verify this), and `make`.
**Always smoke-test with `tools/smoketest.sh <map>`**, never by hand. It
distinguishes PASS / FAIL / DISPLAY_UNAVAILABLE and exits 0/1/3. Checking
"is the process still alive?" produces false passes, because a display-starved
OpenRA sits at `Loading mod` forever without dying.
Learned the hard way on 2026-07-20 (phases AF):
- **Smoke-test any change by launching straight into a game**: `./launch-game.sh Game.Mod=vinylgod Launch.Map=vinylgod``Launch.Map` accepts the map's *folder name*, no UID needed. Run ~45s, then check `~/Library/Application Support/OpenRA/Logs/` for `exception-*.log` (renamed with a timestamp on crash — absence of `exception.log` alone proves nothing).
- **Shellmaps FREEZE with bot players** (learned 2026-07-21): a `Bot:` player on a shellmap stalls the order manager after one world tick — the menu *looks* fine but nothing simulates. Keep the shellmap a static diorama. The real integration test is `maps/arena` (Lobby-hidden map with two `Bot: wax` players + `balance.lua` telemetry): launch with `Launch.Map=arena`, wait, then `python3 tools/balance_report.py` reads economy/army/eliminations from lua.log. A map validation error (e.g. bad `Enemies:` reference) can also silently stall a match at tick 1 — always get check-yaml to zero before trusting a run.
- Chrome image collections must be **power-of-two** textures (a 48×48 png crashes the renderer).
- Every rules file must use the same case for shared top-level actors: `player:` not `Player:` — mismatched case = "duplicate values" manifest error.
- Speech notification `Sounds`/`Speech` blocks: set `DefaultVariant: .wav` (engine default is `.aud`).
- MODELBEAST `music_local` takes `prompt` (not `tags`); `tts_local` takes `text`.
- `ConquestVictoryConditions` needs `MapOptions:` on the world actor; `Health` needs `HitShape`; actors need a visibility trait (`HiddenUnderFog:`); `Selectable` already includes `Interactable` (don't add both).
- `StartingUnits.SupportActors` must be mobile units, never buildings.
- In zsh scripts: `UID` is a readonly shell variable, and an unmatched glob aborts the whole command line (`setopt nonomatch` first).
- **Forgot `DOTNET_ROLL_FORWARD=LatestMajor`** → "framework 6.0.0 not found" crash.
- Every actor referenced in a map/rules needs a sequences entry, even placeholders.
- Trait names change between engine releases — trust `engine/mods/ra` on THIS
checkout over any wiki/tutorial (wiki tracks bleed).
- The Fluent string files (`fluent/*.ftl`) must contain every `label`/`name` key you
reference or check-yaml warns; keep them updated as actors land.
- MODELBEAST guest token caps at 4 active jobs — batch sequentially; if we need
bulk parallel gen, mint a proper user token on m3ultra (John approved) —
the token-mint path is in the MODELBEAST repo on m3ultra (`~/Documents/MODELBEAST`).
- Don't touch `engine/` — engine mods belong upstream or via `AUTOMATIC_ENGINE_MANAGEMENT=False` (avoid).

View File

@ -1,14 +1,14 @@
{ {
"profiles": { "profiles": {
"OpenRA.Mods.Example": { "OpenRA.Mods.Vinylgod": {
"commandName": "Executable", "commandName": "Executable",
"executablePath": "..\\..\\engine\\bin\\OpenRA.exe", "executablePath": "..\\..\\engine\\bin\\OpenRA.exe",
"commandLineArgs": "Game.Mod=example Engine.EngineDir=..\\..\\engine Engine.LaunchPath=..\\..\\engine\\bin Engine.ModSearchPaths=..\\..\\mods,..\\..\\engine\\mods Debug.DisplayDeveloperSettings=true" "commandLineArgs": "Game.Mod=vinylgod Engine.EngineDir=..\\..\\engine Engine.LaunchPath=..\\..\\engine\\bin Engine.ModSearchPaths=..\\..\\mods,..\\..\\engine\\mods Debug.DisplayDeveloperSettings=true"
}, },
"Utility": { "Utility": {
"commandName": "Executable", "commandName": "Executable",
"executablePath": "..\\..\\engine\\bin\\OpenRA.Utility.exe", "executablePath": "..\\..\\engine\\bin\\OpenRA.Utility.exe",
"commandLineArgs": "example --check-yaml", "commandLineArgs": "vinylgod --check-yaml",
"environmentVariables": { "environmentVariables": {
"ENGINE_DIR": "..\\..\\engine", "ENGINE_DIR": "..\\..\\engine",
"MOD_SEARCH_PATHS": "..\\..\\mods,..\\..\\engine\\mods" "MOD_SEARCH_PATHS": "..\\..\\mods,..\\..\\engine\\mods"

View File

@ -14,7 +14,7 @@
using OpenRA.Primitives; using OpenRA.Primitives;
using OpenRA.Traits; using OpenRA.Traits;
namespace OpenRA.Mods.Example.Rendering namespace OpenRA.Mods.Vinylgod.Rendering
{ {
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)] [TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Create a color picker palette from another palette.")] [Desc("Create a color picker palette from another palette.")]

View File

@ -13,7 +13,7 @@
using OpenRA.Primitives; using OpenRA.Primitives;
using OpenRA.Traits; using OpenRA.Traits;
namespace OpenRA.Mods.Example.Rendering namespace OpenRA.Mods.Vinylgod.Rendering
{ {
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)] [TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Add color shifts to player palettes. Use to add RGBA compatibility to PlayerColorPalette.")] [Desc("Add color shifts to player palettes. Use to add RGBA compatibility to PlayerColorPalette.")]

View File

@ -1,19 +1,44 @@
This repository contains a bare development environment for creating a new mod/game on the [OpenRA](https://github.com/OpenRA/OpenRA) engine. # VINYLGOD
These scripts and support files wrap and automatically manage a copy of the OpenRA game engine and common files during development, and generates Windows installers, macOS .app bundles, and Linux [AppImages](https://appimage.org/) for distribution. **An original vinyl-monster-robot RTS.** Forty years after The Great Compression
deleted all recorded music, the last analog sound crystallised underground as
**Black Wax** — and whoever presses it controls what the world hears next.
The key scripts in this SDK are: The **Monster Robot Party** (rust, hot pink, gaffer tape, souls made of record
collections) versus **The Stream** (glossy white logistics fleet of a
recommendation algorithm that knows you'd be 4% more engaged with something
shorter). Harvest wax, press records, stack amps, drop the needle.
| Windows | Linux / macOS | Purpose Built as a total conversion on the [OpenRA](https://www.openra.net) engine.
| --------------------- | ------------------------ | ------------- | Lore in [LORE.md](LORE.md). Build phases and agent instructions in
| make.cmd | Makefile | Compiles your project and fetches dependencies (including the OpenRA engine). [MEGAPLAN.md](MEGAPLAN.md).
| launch-game.cmd | launch-game.sh | Launches your project from the SDK directory.
| launch-server.cmd | launch-server.sh | Launches a dedicated server for your project from the SDK directory.
| utility.cmd | utility.sh | Launches the OpenRA Utility for your project.
| &lt;not available&gt; | packaging/package-all.sh | Generates release installers for your project.
To launch your project from the development environment you must first compile the project by running `make.cmd` (Windows), or opening a terminal in the SDK directory and running `make` (Linux / macOS). You can then run `launch-game.cmd` (Windows) or `launch-game.sh` (Linux / macOS) to run your game. ## Play (macOS)
The `example` mod included in this repository provides the bare minimum structure to launch to the in-game main menu for the sole purpose of demonstrating the SDK. See [Getting Started](https://github.com/OpenRA/OpenRAModTemplate/wiki/Getting-Started) on the Wiki for instructions on how to adapt this template for your own projects. For common questions, please see the [FAQ](https://github.com/OpenRA/OpenRAModSDK/wiki/FAQ). See [Updating to a new SDK or Engine version](https://github.com/OpenRA/OpenRAModSDK/wiki/Updating-to-a-new-SDK-or-Engine-version) for a guide on updating your mod a newer OpenRA release. ```sh
export PATH="/opt/homebrew/opt/dotnet@8/bin:$PATH"
export DOTNET_ROLL_FORWARD=LatestMajor
make && ./launch-game.sh Game.Mod=vinylgod
```
The OpenRA engine and SDK scripts are made available under the [GPLv3](https://github.com/OpenRA/OpenRA/blob/bleed/COPYING) license, and any executable code developed by a mod and loaded by the engine (i.e. custom mod DLLs, lua scripts) must be released under a compatible license. Your mod data files (artwork, sound files, yaml, etc) are not part of your mod's source code, so you are free to distribute these assets under different terms (e.g. allowing redistribution in unmodified form, but not for use in other works). The main-menu background is a live AI-vs-AI battle (it doubles as the
integration test). Start a skirmish on **Pressing District** (4p) or
**Vinylgod Map** (1v1) against the Wax AI.
## Features
- Two asymmetric factions, 26 actors, full base-building + wax economy
- 16-facing rotating vehicles, projectile & explosion effects
- Superweapons: **THE DROP** (orbital tonearm) vs **THE SHUFFLE**
- Skirmish AI that plays both factions
- MC 8-TRACK announcer + generated soundtrack
All art, audio and music generated on a local MODELBEAST render farm — prompt
provenance in [assets_src/PROMPTS.md](assets_src/PROMPTS.md). No third-party IP.
## License
GPL v3 (see [COPYING](COPYING)), as a derivative of the OpenRA engine and Mod SDK.
All original lore, names, art and audio © monsterrobot.party, released under the
same terms. This project contains no Electronic Arts code, assets, or trademarks
and claims no affiliation with any other RTS.

View File

@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012 # Visual Studio 2012
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenRA.Mods.Example", "OpenRA.Mods.Example\OpenRA.Mods.Example.csproj", "{4E5B38F7-4E99-4C92-BB39-9100CC7F3829}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenRA.Mods.Vinylgod", "OpenRA.Mods.Vinylgod\OpenRA.Mods.Vinylgod.csproj", "{4E5B38F7-4E99-4C92-BB39-9100CC7F3829}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenRA.Game", "engine\OpenRA.Game\OpenRA.Game.csproj", "{0DFB103F-2962-400F-8C6D-E2C28CCBA633}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenRA.Game", "engine\OpenRA.Game\OpenRA.Game.csproj", "{0DFB103F-2962-400F-8C6D-E2C28CCBA633}"
EndProject EndProject

37
assets_src/PROMPTS.md Normal file
View File

@ -0,0 +1,37 @@
# Asset provenance log
All images generated locally on MODELBEAST (`flux_local`) via `tools/mbgen.py`. Original prompts, no third-party IP referenced.
| file | date | prompt |
|---|---|---|
| concepts/emblem_mrp.png | 2026-07-20 | faction emblem logo, monster robot holding a vinyl record aloft, bold flat 2-color screen-print style, circular badge, no text, black and hot pink |
| concepts/digger.png | 2026-07-20 | rusty junkyard forklift monster robot with crate claw carrying milk crates of black vinyl records, hot pink trim, CRT eye, 3/4 view, isometric game unit concept art, plain grey background |
| concepts/pressplant.png | 2026-07-20 | industrial hydraulic vinyl record pressing plant building, steam vents, conveyor belt of fresh records, rust and hot pink, isometric RTS building concept art, plain grey background |
| concepts/drmwalker.png | 2026-07-20 | glossy white faceless robot mech with single blue ring-light eye, chest is a glowing paywall screen, smooth rounded seamless design, isometric game unit concept art, plain grey background — *came out small/cute; reuse as `bufferbot`, re-prompt drmwalker with "towering, menacing, tall bipedal mech"* |
| renders/popupvan.png | 2026-07-20 | rusty junkyard robot aesthetic, rust metal with hot pink trim, analog dials and speaker parts, small delivery truck covered in band stickers and a roof-mounted loudspeaker, isometric three-quarter view from above, single object centered, video game asset, plain flat grey background, no text |
| renders/popupshop.png | 2026-07-20 | rusty junkyard robot aesthetic, rust metal with hot pink trim, analog dials and speaker parts, record store shack built from shipping containers with neon OPEN sign and crane arm, isometric three-quarter view from above, single object centered, video game asset, plain flat grey background, no text |
| renders/pressplant.png | 2026-07-20 | rusty junkyard robot aesthetic, rust metal with hot pink trim, analog dials and speaker parts, industrial hydraulic vinyl record pressing plant building with steam vents and conveyor of records, isometric three-quarter view from above, single object centered, video game asset, plain flat grey background, no text |
| renders/ampstack.png | 2026-07-20 | rusty junkyard robot aesthetic, rust metal with hot pink trim, analog dials and speaker parts, wall of stacked guitar amplifiers crackling with pink energy, isometric three-quarter view from above, single object centered, video game asset, plain flat grey background, no text |
| renders/vault.png | 2026-07-20 | rusty junkyard robot aesthetic, rust metal with hot pink trim, analog dials and speaker parts, squat bunker with a huge round bank vault door and stacked record crates, isometric three-quarter view from above, single object centered, video game asset, plain flat grey background, no text |
| renders/merchtable.png | 2026-07-20 | rusty junkyard robot aesthetic, rust metal with hot pink trim, analog dials and speaker parts, folding merch table under a small tent with t-shirts and records, isometric three-quarter view from above, single object centered, video game asset, plain flat grey background, no text |
| renders/garage.png | 2026-07-20 | rusty junkyard robot aesthetic, rust metal with hot pink trim, analog dials and speaker parts, corrugated iron vehicle workshop with engine hoist and band posters, isometric three-quarter view from above, single object centered, video game asset, plain flat grey background, no text |
| renders/mastering.png | 2026-07-20 | rusty junkyard robot aesthetic, rust metal with hot pink trim, analog dials and speaker parts, pristine acoustic-panelled recording studio grafted onto a junk tower with satellite dish, isometric three-quarter view from above, single object centered, video game asset, plain flat grey background, no text |
| renders/digger.png | 2026-07-20 | rusty junkyard robot aesthetic, rust metal with hot pink trim, analog dials and speaker parts, forklift monster robot with crate claw carrying milk crates of vinyl records, isometric three-quarter view from above, single object centered, video game asset, plain flat grey background, no text |
| renders/spinner.png | 2026-07-20 | rusty junkyard robot aesthetic, rust metal with hot pink trim, analog dials and speaker parts, small agile one-wheeled robot whose wheel is a spinning vinyl record with blade tonearms, isometric three-quarter view from above, single object centered, video game asset, plain flat grey background, no text |
| renders/stacktank.png | 2026-07-20 | rusty junkyard robot aesthetic, rust metal with hot pink trim, analog dials and speaker parts, two-legged walker mech made of stacked speaker cabinets with subwoofer chest, isometric three-quarter view from above, single object centered, video game asset, plain flat grey background, no text |
| renders/basscannon.png | 2026-07-20 | rusty junkyard robot aesthetic, rust metal with hot pink trim, analog dials and speaker parts, six-wheeled flatbed truck hauling one colossal subwoofer cannon with fold-out legs, isometric three-quarter view from above, single object centered, video game asset, plain flat grey background, no text |
| renders/djgrunt.png | 2026-07-20 | rusty junkyard robot aesthetic, rust metal with hot pink trim, analog dials and speaker parts, small hooded robot with a portable turntable chest rig holding a razor-sharp record, isometric three-quarter view from above, single object centered, video game asset, plain flat grey background, no text |
| renders/roadie.png | 2026-07-20 | rusty junkyard robot aesthetic, rust metal with hot pink trim, analog dials and speaker parts, four-armed robot with gaffer tape bandoliers and a flight case backpack, isometric three-quarter view from above, single object centered, video game asset, plain flat grey background, no text |
| renders/streamvan.png | 2026-07-20 | glossy seamless white tech aesthetic, soft blue ring lights, smooth rounded minimal design, autonomous white delivery van with a glowing blue play-button logo, isometric three-quarter view from above, single object centered, video game asset, plain flat grey background, no text |
| renders/streamhub.png | 2026-07-20 | glossy seamless white tech aesthetic, soft blue ring lights, smooth rounded minimal design, white monolithic server hub building with one huge blue status ring, isometric three-quarter view from above, single object centered, video game asset, plain flat grey background, no text |
| renders/datacentre.png | 2026-07-20 | glossy seamless white tech aesthetic, soft blue ring lights, smooth rounded minimal design, humming white server monolith with a single blue LED strip, isometric three-quarter view from above, single object centered, video game asset, plain flat grey background, no text |
| renders/transcoder.png | 2026-07-20 | glossy seamless white tech aesthetic, soft blue ring lights, smooth rounded minimal design, white cube building that swallows records on a conveyor, receipts coming out, isometric three-quarter view from above, single object centered, video game asset, plain flat grey background, no text |
| renders/podfarm.png | 2026-07-20 | glossy seamless white tech aesthetic, soft blue ring lights, smooth rounded minimal design, vending machine wall dispensing small white sphere robots, isometric three-quarter view from above, single object centered, video game asset, plain flat grey background, no text |
| renders/printfarm.png | 2026-07-20 | glossy seamless white tech aesthetic, soft blue ring lights, smooth rounded minimal design, white 3d-printer factory building with robotic arms assembling drones, isometric three-quarter view from above, single object centered, video game asset, plain flat grey background, no text |
| renders/scraper.png | 2026-07-20 | glossy seamless white tech aesthetic, soft blue ring lights, smooth rounded minimal design, autonomous white street sweeper vehicle inhaling black vinyl through a glowing blue intake, isometric three-quarter view from above, single object centered, video game asset, plain flat grey background, no text |
| renders/bufferbot.png | 2026-07-20 | glossy seamless white tech aesthetic, soft blue ring lights, smooth rounded minimal design, knee-high white sphere robot with a loading spinner face, isometric three-quarter view from above, single object centered, video game asset, plain flat grey background, no text |
| renders/drmwalker.png | 2026-07-20 | glossy seamless white tech aesthetic, soft blue ring lights, smooth rounded minimal design, tall faceless white mech with one blue ring-light eye and a glowing paywall screen chest, isometric three-quarter view from above, single object centered, video game asset, plain flat grey background, no text |
| renders/selector.png | 2026-07-25 | rusty junkyard robot aesthetic, rust metal with hot pink trim, analog dials and speaker parts, legendary hero DJ robot in a long coat with a crate of glowing gold dubplates under one arm and a tonearm staff, isometric three-quarter view from above, single object centered, video game asset, plain flat grey background, no text |
| renders/curator.png | 2026-07-25 | glossy seamless white tech aesthetic, soft blue ring lights, smooth rounded minimal design, hovering white sphere ringed with many camera lenses, a single blue eye at the front, faint halo, isometric three-quarter view from above, single object centered, video game asset, plain flat grey background, no text |
| renders/launchramp.png | 2026-07-25 | rusty junkyard robot aesthetic, rust metal with hot pink trim, analog dials and speaker parts, scrap metal launch ramp pad with painted pink chevrons, floodlights and a parked flying vinyl disc, isometric three-quarter view from above, single object centered, video game asset, plain flat grey background, no text |
| renders/droneport.png | 2026-07-25 | glossy seamless white tech aesthetic, soft blue ring lights, smooth rounded minimal design, white circular drone landing pad building with recessed blue guide lights and folded launch arms, isometric three-quarter view from above, single object centered, video game asset, plain flat grey background, no text |

BIN
assets_src/audio/probe.wav Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 634 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 782 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
assets_src/m02_outpost.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

BIN
assets_src/map_arena.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

BIN
assets_src/map_detail.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 480 KiB

BIN
assets_src/map_m02.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 870 KiB

BIN
assets_src/map_m03.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

BIN
assets_src/map_m04.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 930 KiB

BIN
assets_src/map_m05.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 905 KiB

BIN
assets_src/map_m06.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 760 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 930 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 826 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 964 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 835 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 950 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 821 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 799 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 928 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 819 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 983 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 874 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 897 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 744 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 643 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 875 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 773 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 935 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 832 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 991 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 866 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 852 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 736 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 911 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 800 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 895 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 772 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 782 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 674 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 737 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 910 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 813 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 970 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 839 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 994 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 865 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 964 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 933 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 836 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 718 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 974 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 937 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 805 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 798 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 695 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 850 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 738 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 986 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 876 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 953 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 985 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 927 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 808 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 684 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 594 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 547 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 471 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 969 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 850 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 813 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 720 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 609 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 532 KiB

Some files were not shown because too many files have changed in this diff Show More