From 86ca71b9a2d0367342447792edaedf18d206f823 Mon Sep 17 00:00:00 2001 From: type-two Date: Mon, 20 Jul 2026 01:30:20 +1000 Subject: [PATCH] =?UTF-8?q?Phase=20A:=20Black=20Wax=20economy=20=E2=80=94?= =?UTF-8?q?=20resource=20layer,=20digger=20harvester,=20pressing=20plant,?= =?UTF-8?q?=20amp=20stack,=20vault,=20seeded=20maps,=20cash=20HUD,=20place?= =?UTF-8?q?holder=20sprites?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- .../chrome/layouts/ingame-player.yaml | 12 +++ mods/vinylgod/cursors/default.yaml | 10 ++ mods/vinylgod/fluent/rules.ftl | 13 +++ mods/vinylgod/maps/shellmap/map.bin | Bin 5797 -> 5797 bytes mods/vinylgod/maps/shellmap/map.yaml | 9 ++ mods/vinylgod/maps/vinylgod/map.bin | Bin 5797 -> 5797 bytes mods/vinylgod/mod.content.yaml | 2 + mods/vinylgod/rules/economy.yaml | 100 ++++++++++++++++++ mods/vinylgod/rules/palettes.yaml | 2 + mods/vinylgod/rules/player.yaml | 5 + mods/vinylgod/rules/world.yaml | 37 ++++++- mods/vinylgod/sequences/assets/ampstack.png | Bin 0 -> 157 bytes mods/vinylgod/sequences/assets/digger.png | Bin 0 -> 129 bytes mods/vinylgod/sequences/assets/pressplant.png | Bin 0 -> 251 bytes mods/vinylgod/sequences/assets/vault.png | Bin 0 -> 157 bytes mods/vinylgod/sequences/assets/wax.png | Bin 0 -> 582 bytes mods/vinylgod/sequences/economy.yaml | 19 ++++ mods/vinylgod/tilesets/vinylgod.yaml | 2 + tools/gen_placeholders.py | 77 ++++++++++++++ tools/seed_wax.py | 30 ++++++ 20 files changed, 317 insertions(+), 1 deletion(-) create mode 100644 mods/vinylgod/rules/economy.yaml create mode 100644 mods/vinylgod/sequences/assets/ampstack.png create mode 100644 mods/vinylgod/sequences/assets/digger.png create mode 100644 mods/vinylgod/sequences/assets/pressplant.png create mode 100644 mods/vinylgod/sequences/assets/vault.png create mode 100644 mods/vinylgod/sequences/assets/wax.png create mode 100644 mods/vinylgod/sequences/economy.yaml create mode 100644 tools/gen_placeholders.py create mode 100644 tools/seed_wax.py diff --git a/mods/vinylgod/chrome/layouts/ingame-player.yaml b/mods/vinylgod/chrome/layouts/ingame-player.yaml index 54e5ca6..c5bee17 100644 --- a/mods/vinylgod/chrome/layouts/ingame-player.yaml +++ b/mods/vinylgod/chrome/layouts/ingame-player.yaml @@ -4,3 +4,15 @@ Container@PLAYER_WIDGETS: LogicTicker@SIDEBAR_TICKER: MenuButton@OPTIONS_BUTTON: Key: escape + Container@CASH_COUNTER: + Logic: IngameCashCounterLogic + X: PARENT_WIDTH - WIDTH - 10 + Y: 10 + Width: 120 + Height: 23 + Children: + LabelWithTooltip@CASH: + Width: PARENT_WIDTH + Height: 23 + Align: Right + Font: TinyBold diff --git a/mods/vinylgod/cursors/default.yaml b/mods/vinylgod/cursors/default.yaml index f7bd988..fbbad5c 100644 --- a/mods/vinylgod/cursors/default.yaml +++ b/mods/vinylgod/cursors/default.yaml @@ -2,3 +2,13 @@ Cursors: cursors/assets/default.png: default: Start: 0 + harvest: + Start: 0 + enter: + Start: 0 + enter-blocked: + Start: 0 + move: + Start: 0 + move-blocked: + Start: 0 diff --git a/mods/vinylgod/fluent/rules.ftl b/mods/vinylgod/fluent/rules.ftl index 57d365c..b365006 100644 --- a/mods/vinylgod/fluent/rules.ftl +++ b/mods/vinylgod/fluent/rules.ftl @@ -8,3 +8,16 @@ faction-vinylgod = .name = Vinylgod .description = Vinylgod Faction Provide your own faction description here. + +## economy.yaml +actor-digger = + .name = Crate Digger +actor-pressplant = + .name = Pressing Plant +actor-ampstack = + .name = Amp Stack +actor-vault = + .name = Record Vault + +## world.yaml (resources) +resource-wax = Black Wax diff --git a/mods/vinylgod/maps/shellmap/map.bin b/mods/vinylgod/maps/shellmap/map.bin index 58c11194c20655f5403200b9c0e9f394f0beb497..4c216334b6b2e583993ac60f7c088d73d598b536 100644 GIT binary patch literal 5797 zcmeH~Q4Yf(3`1i|%8Is+U7`2xSvNy>f~49s$w0(coaEsj%5J+o?Oeyh?4=_DA|L`H zAOa#F0wN#+A|L`H@O1*8Z<($i5WtcviVDZdsBs-;->@+}s)2<)Y`8Pl_(b_W%&y=u zD8#3TGQ1`aC8xue9FD5-`KjP&b9+>U^&7p^87<~)l-Wh6Cp$Gf#wFj!a8jPfR7t+e Q>5CYLoTrp60{=kZ4JC(0G!mP|NqKOdzT4D!6 diff --git a/mods/vinylgod/maps/shellmap/map.yaml b/mods/vinylgod/maps/shellmap/map.yaml index 6438817..476081c 100644 --- a/mods/vinylgod/maps/shellmap/map.yaml +++ b/mods/vinylgod/maps/shellmap/map.yaml @@ -28,3 +28,12 @@ Players: Faction: Random Actors: + Actor1: pressplant + Owner: Creeps + Location: 12,12 + Actor2: digger + Owner: Creeps + Location: 15,14 + Actor3: ampstack + Owner: Creeps + Location: 10,14 diff --git a/mods/vinylgod/maps/vinylgod/map.bin b/mods/vinylgod/maps/vinylgod/map.bin index 58c11194c20655f5403200b9c0e9f394f0beb497..68e43bd71e2abc24eee85c16d22ef67f81df46af 100644 GIT binary patch literal 5797 zcmeI#K?;B%5QX7+mPk>HuF$Qk{BbpItP^6S7JjIhx|<7Y!PH7WI)zlxh{DCQm88 n54p70VfKbcO=;}QsTgyJbbxQ(5oqlgH~QWOZuDJ){S$!$uj7M6 delta 31 ZcmZ3gyHt0BC;#RK!P$&x#N-XU9{|I+3~c}a diff --git a/mods/vinylgod/mod.content.yaml b/mods/vinylgod/mod.content.yaml index 5b52c3c..88d8c10 100644 --- a/mods/vinylgod/mod.content.yaml +++ b/mods/vinylgod/mod.content.yaml @@ -12,6 +12,7 @@ Notifications: Rules: vinylgod|rules/vinylgod.yaml + vinylgod|rules/economy.yaml vinylgod|rules/mpspawn.yaml vinylgod|rules/palettes.yaml vinylgod|rules/player.yaml @@ -19,6 +20,7 @@ Rules: Sequences: vinylgod|sequences/vinylgod.yaml + vinylgod|sequences/economy.yaml vinylgod|sequences/mapeditor.yaml vinylgod|sequences/mpspawn.yaml diff --git a/mods/vinylgod/rules/economy.yaml b/mods/vinylgod/rules/economy.yaml new file mode 100644 index 0000000..4c40bc9 --- /dev/null +++ b/mods/vinylgod/rules/economy.yaml @@ -0,0 +1,100 @@ +^EconSprite: + BodyOrientation: + QuantizeFacingsFromSequence: + RenderSprites: + WithSpriteBody: + SelectionDecorations: + AppearsOnRadar: + HitShape: + HiddenUnderFog: + +digger: + Inherits: ^EconSprite + Tooltip: + Name: actor-digger.name + Selectable: + Bounds: 1024, 1024 + Health: + HP: 60000 + Armor: + Type: Heavy + Mobile: + Locomotor: wheeled + Speed: 72 + Harvester: + Resources: Wax + BaleUnloadDelay: 1 + SearchFromProcRadius: 15 + SearchFromHarvesterRadius: 8 + StoresResources: + Capacity: 20 + Resources: Wax + DockClientManager: + RevealsShroud: + Range: 5c0 + MapEditorData: + Categories: Units + +^EconBuilding: + Inherits: ^EconSprite + Tooltip: + Health: + HP: 90000 + Armor: + Type: Wood + RevealsShroud: + Range: 5c0 + MapEditorData: + Categories: Buildings + +pressplant: + Inherits: ^EconBuilding + Tooltip: + Name: actor-pressplant.name + Selectable: + Bounds: 2048, 2048 + Building: + Footprint: xx == + Dimensions: 2,2 + TerrainTypes: Clear + Refinery: + DockHost: + Type: Unload + DockOffset: 0, 512, 0 + StoresPlayerResources: + Capacity: 2000 + Power: + Amount: -30 + FreeActor: + Actor: digger + SpawnOffset: 0, 2 + +ampstack: + Inherits: ^EconBuilding + Tooltip: + Name: actor-ampstack.name + Selectable: + Bounds: 1024, 1024 + Health: + HP: 40000 + Building: + Footprint: x + Dimensions: 1,1 + TerrainTypes: Clear + Power: + Amount: 100 + +vault: + Inherits: ^EconBuilding + Tooltip: + Name: actor-vault.name + Selectable: + Bounds: 1024, 1024 + Health: + HP: 30000 + Building: + Footprint: x + Dimensions: 1,1 + TerrainTypes: Clear + StoresPlayerResources: + Capacity: 3000 diff --git a/mods/vinylgod/rules/palettes.yaml b/mods/vinylgod/rules/palettes.yaml index 3e1f58c..07b2fb6 100644 --- a/mods/vinylgod/rules/palettes.yaml +++ b/mods/vinylgod/rules/palettes.yaml @@ -1,6 +1,8 @@ ^palettes: PaletteFromGrayscale@greyscale: Name: greyscale + PaletteFromGrayscale@terrain: + Name: terrain PlayerColorPalette@player: BasePalette: greyscale PlayerColorShift: diff --git a/mods/vinylgod/rules/player.yaml b/mods/vinylgod/rules/player.yaml index 11ef94c..005961d 100644 --- a/mods/vinylgod/rules/player.yaml +++ b/mods/vinylgod/rules/player.yaml @@ -5,6 +5,11 @@ player: Inherits: ^baseplayer DeveloperMode: + PlayerResources: + DefaultCash: 5000 + ResourceValues: + Wax: 25 + PowerManager: editorplayer: Inherits: ^baseplayer diff --git a/mods/vinylgod/rules/world.yaml b/mods/vinylgod/rules/world.yaml index af87013..20dcb05 100644 --- a/mods/vinylgod/rules/world.yaml +++ b/mods/vinylgod/rules/world.yaml @@ -29,12 +29,47 @@ world: SpawnMapActors: SpawnStartingUnits: StartingUnits@Vinylgod: - BaseActor: vinylgod + BaseActor: pressplant + SupportActors: ampstack Factions: vinylgod ClassName: options-starting-units.unlabeled + BuildingInfluence: + PathFinder: + Locomotor@WHEELED: + Name: wheeled + TerrainSpeeds: + Clear: 100 + Wax: 80 + ResourceLayer: + RecalculateResourceDensity: true + ResourceTypes: + Wax: + ResourceIndex: 1 + TerrainType: Wax + AllowedTerrainTypes: Clear + MaxDensity: 12 + ResourceRenderer: + ResourceTypes: + Wax: + Sequences: wax01 + Name: resource-wax + ResourceClaimLayer: editorworld: Inherits: ^baseworld + EditorResourceLayer: + RecalculateResourceDensity: true + ResourceTypes: + Wax: + ResourceIndex: 1 + TerrainType: Wax + AllowedTerrainTypes: Clear + MaxDensity: 12 + ResourceRenderer: + ResourceTypes: + Wax: + Sequences: wax01 + Name: resource-wax BuildableTerrainOverlay: AllowedTerrainTypes: Palette: diff --git a/mods/vinylgod/sequences/assets/ampstack.png b/mods/vinylgod/sequences/assets/ampstack.png new file mode 100644 index 0000000000000000000000000000000000000000..936737321f4ddbea2bb7f7aa99086fa2c80d21a7 GIT binary patch literal 157 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJ6i*k&kcv6U2@F(pZjh8 zw2BYb3R))r>~%k`U~Zew?7-Rmj_<(qQu< c4AKk?T)Hd{&s2ZC2Aav>>FVdQ&MBb@0G;kCJpcdz literal 0 HcmV?d00001 diff --git a/mods/vinylgod/sequences/assets/pressplant.png b/mods/vinylgod/sequences/assets/pressplant.png new file mode 100644 index 0000000000000000000000000000000000000000..064d81c55b65abd18752fe5e3943aca4e846b04d GIT binary patch literal 251 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=hdf;zLn`LHz2V4rNI}5i;=IGH zADQB=zrM7?YgVyW{fKeqsXZhJX!P2R`rk z70z&f&V7GQft@Gjuq}9Q7A}`?Wa>7Z11G9$EgO2~OEauuNZC^(!U)uIoGE2r4a-4s zAhY2x<0b*6-wX!a2_{Y@{K1TFieJvm=ey8-!Md8WLE})z&eIHkm<)^V6*0VbFq*&L j#^D>nUIvFrDlfOnYR_l43EL`H1#*n1tDnm{r-UW|84g*8 literal 0 HcmV?d00001 diff --git a/mods/vinylgod/sequences/assets/vault.png b/mods/vinylgod/sequences/assets/vault.png new file mode 100644 index 0000000000000000000000000000000000000000..14bf9c0f31fbeaca2dfc5bff9dff5e600b70525b GIT binary patch literal 157 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJ6i*k&kcv6U2@t{jF-@m3i44)tR z{ap)?&mY;(zMpS+dntGv$?^Gne&|hIdlB;aGx#TkG-k+eE#wElJ7*xgGw#OuemGp$MCDX+4=lQeH#Fu&*v}hXWy5*2Y;?#yyNlt z9s5Ve;q$NXhpP31=ksg(DaYiO``g>B<_}%#CxFin`6ZvCYYYH>{=ZLF@u#Zw&d2A! zf0lla7Fy6}Ha32`AG22QB~`A*0xbDdbGN_!+bDjm;XA4?sdAykSL-aeH$QZp(fmDU z6<-OZoQ3h%^=mG^PqR0FZ%B>g9}U{seVr)xY>dCAUwZ-e=*KQ2`myJ91z(Xy8$kR% z{8|gISO4gK@#pZDF1FM5>eu?n&F80_dH&y)Kd!Gpt%iT9U-Ho}X7Kqj|8wy0$MhA+ z2Ega@XZCfXy9a-YAA0dqzJS`h@cBLYd&lGF`%q6WFG(7>7dN-1 U=T%6a1^@s607*qoM6N<$g3|>w<^TWy literal 0 HcmV?d00001 diff --git a/mods/vinylgod/sequences/economy.yaml b/mods/vinylgod/sequences/economy.yaml new file mode 100644 index 0000000..beb23cc --- /dev/null +++ b/mods/vinylgod/sequences/economy.yaml @@ -0,0 +1,19 @@ +resources: + wax01: + Filename: sequences/assets/wax.png + +digger: + idle: + Filename: sequences/assets/digger.png + +pressplant: + idle: + Filename: sequences/assets/pressplant.png + +ampstack: + idle: + Filename: sequences/assets/ampstack.png + +vault: + idle: + Filename: sequences/assets/vault.png diff --git a/mods/vinylgod/tilesets/vinylgod.yaml b/mods/vinylgod/tilesets/vinylgod.yaml index 0342006..1dccce1 100644 --- a/mods/vinylgod/tilesets/vinylgod.yaml +++ b/mods/vinylgod/tilesets/vinylgod.yaml @@ -7,6 +7,8 @@ General: Terrain: TerrainType@Clear: Type: Clear + TerrainType@Wax: + Type: Wax Templates: Template@255: diff --git a/tools/gen_placeholders.py b/tools/gen_placeholders.py new file mode 100644 index 0000000..9bb73a8 --- /dev/null +++ b/tools/gen_placeholders.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 +"""Generate placeholder sprite PNGs for Phase A (stdlib only). + +OpenRA PngSheet slices multi-frame sheets via an embedded tEXt chunk +"FrameSize: w,h" (see engine PngSheetLoader.cs). Real art replaces these in +Phase D — keep the filenames. +""" +import os, struct, zlib + +OUT = os.path.join(os.path.dirname(__file__), '..', 'mods', 'vinylgod', 'sequences', 'assets') + +PINK = (255, 45, 150, 255) +DARK = (30, 26, 32, 255) +GREY = (90, 85, 95, 255) +CLEAR = (0, 0, 0, 0) + + +def chunk(tag, data): + return struct.pack('>I', len(data)) + tag + data + struct.pack('>I', zlib.crc32(tag + data)) + + +def write_png(path, w, h, px, text=None): + raw = b''.join(b'\x00' + b''.join(bytes(px[y * w + x]) for x in range(w)) for y in range(h)) + out = b'\x89PNG\r\n\x1a\n' + chunk(b'IHDR', struct.pack('>IIBBBBB', w, h, 8, 6, 0, 0, 0)) + for k, v in (text or {}).items(): + out += chunk(b'tEXt', k.encode() + b'\x00' + v.encode()) + out += chunk(b'IDAT', zlib.compress(raw)) + chunk(b'IEND', b'') + open(path, 'wb').write(out) + print(f'wrote {path} {w}x{h}') + + +def canvas(w, h, fill=CLEAR): + return [fill] * (w * h) + + +def rect(px, w, x0, y0, x1, y1, c): + for y in range(y0, y1): + for x in range(x0, x1): + px[y * w + x] = c + + +def disc(px, w, cx, cy, r, c): + for y in range(int(cy - r), int(cy + r) + 1): + for x in range(int(cx - r), int(cx + r) + 1): + if (x - cx) ** 2 + (y - cy) ** 2 <= r * r: + px[y * w + x] = c + + +def box_sprite(path, size, body, accent): + px = canvas(size, size) + m = size // 8 + rect(px, size, m, m, size - m, size - m, body) + rect(px, size, m, m, size - m, m + 2, accent) # top trim + disc(px, size, size / 2, size / 2, size // 5, accent) # centre disc + write_png(path, size, size, px) + + +os.makedirs(OUT, exist_ok=True) + +# wax: 12 density frames, 32x32, horizontal strip +W, H, N = 32, 32, 12 +px = canvas(W * N, H) +blob = [(9, 9), (22, 12), (14, 21), (24, 24), (7, 24), (17, 7), (26, 17), (11, 15), + (20, 19), (15, 27), (5, 16), (27, 8)] +for f in range(N): + for i in range(f + 1): + cx, cy = blob[i] + for dx in range(W): # draw into frame f's slice + pass + gx = f * W + cx + disc(px, W * N, gx, cy, 3, PINK if i % 3 == 0 else DARK) +write_png(os.path.join(OUT, 'wax.png'), W * N, H, px, text={'FrameSize': '32,32'}) + +box_sprite(os.path.join(OUT, 'digger.png'), 24, PINK, DARK) +box_sprite(os.path.join(OUT, 'pressplant.png'), 64, DARK, PINK) +box_sprite(os.path.join(OUT, 'ampstack.png'), 32, GREY, PINK) +box_sprite(os.path.join(OUT, 'vault.png'), 32, DARK, GREY) diff --git a/tools/seed_wax.py b/tools/seed_wax.py new file mode 100644 index 0000000..98bbb2f --- /dev/null +++ b/tools/seed_wax.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 +"""Seed Wax resource cells into an OpenRA map.bin (format 2, no height data). + +Layout (engine Map.cs SaveBinaryData): u8 fmt, u16 w, u16 h, u32 tilesOff(17), +u32 heightsOff(0), u32 resOff; tiles = w*h*(u16,u8) column-major (i*h+j); +resources = w*h*(u8 type, u8 density), same order. + +Usage: seed_wax.py cx,cy,r [cx,cy,r ...] (circular blobs, density +scales down toward each blob's edge; type byte 1 = Wax ResourceIndex) +""" +import struct, sys + +path = sys.argv[1] +data = bytearray(open(path, 'rb').read()) +fmt, w, h = data[0], *struct.unpack_from('