diff --git a/assets_src/renders_topdown/basscannon.png b/assets_src/renders_topdown/basscannon.png new file mode 100644 index 0000000..0f88ed2 Binary files /dev/null and b/assets_src/renders_topdown/basscannon.png differ diff --git a/assets_src/renders_topdown/basscannon_raw.png b/assets_src/renders_topdown/basscannon_raw.png new file mode 100644 index 0000000..47e022b Binary files /dev/null and b/assets_src/renders_topdown/basscannon_raw.png differ diff --git a/assets_src/renders_topdown/digger.png b/assets_src/renders_topdown/digger.png new file mode 100644 index 0000000..1411022 Binary files /dev/null and b/assets_src/renders_topdown/digger.png differ diff --git a/assets_src/renders_topdown/digger_raw.png b/assets_src/renders_topdown/digger_raw.png new file mode 100644 index 0000000..ac68193 Binary files /dev/null and b/assets_src/renders_topdown/digger_raw.png differ diff --git a/assets_src/renders_topdown/drmwalker.png b/assets_src/renders_topdown/drmwalker.png new file mode 100644 index 0000000..ad6e276 Binary files /dev/null and b/assets_src/renders_topdown/drmwalker.png differ diff --git a/assets_src/renders_topdown/drmwalker_raw.png b/assets_src/renders_topdown/drmwalker_raw.png new file mode 100644 index 0000000..627dbfa Binary files /dev/null and b/assets_src/renders_topdown/drmwalker_raw.png differ diff --git a/assets_src/renders_topdown/popupvan.png b/assets_src/renders_topdown/popupvan.png new file mode 100644 index 0000000..873af66 Binary files /dev/null and b/assets_src/renders_topdown/popupvan.png differ diff --git a/assets_src/renders_topdown/popupvan_raw.png b/assets_src/renders_topdown/popupvan_raw.png new file mode 100644 index 0000000..e3543a4 Binary files /dev/null and b/assets_src/renders_topdown/popupvan_raw.png differ diff --git a/assets_src/renders_topdown/scraper.png b/assets_src/renders_topdown/scraper.png new file mode 100644 index 0000000..d652f04 Binary files /dev/null and b/assets_src/renders_topdown/scraper.png differ diff --git a/assets_src/renders_topdown/scraper_raw.png b/assets_src/renders_topdown/scraper_raw.png new file mode 100644 index 0000000..4f5e7f0 Binary files /dev/null and b/assets_src/renders_topdown/scraper_raw.png differ diff --git a/assets_src/renders_topdown/spinner.png b/assets_src/renders_topdown/spinner.png new file mode 100644 index 0000000..76c710b Binary files /dev/null and b/assets_src/renders_topdown/spinner.png differ diff --git a/assets_src/renders_topdown/spinner_raw.png b/assets_src/renders_topdown/spinner_raw.png new file mode 100644 index 0000000..95cb682 Binary files /dev/null and b/assets_src/renders_topdown/spinner_raw.png differ diff --git a/assets_src/renders_topdown/stacktank.png b/assets_src/renders_topdown/stacktank.png new file mode 100644 index 0000000..188be56 Binary files /dev/null and b/assets_src/renders_topdown/stacktank.png differ diff --git a/assets_src/renders_topdown/stacktank_raw.png b/assets_src/renders_topdown/stacktank_raw.png new file mode 100644 index 0000000..6659f82 Binary files /dev/null and b/assets_src/renders_topdown/stacktank_raw.png differ diff --git a/assets_src/renders_topdown/streamvan.png b/assets_src/renders_topdown/streamvan.png new file mode 100644 index 0000000..2349b99 Binary files /dev/null and b/assets_src/renders_topdown/streamvan.png differ diff --git a/assets_src/renders_topdown/streamvan_raw.png b/assets_src/renders_topdown/streamvan_raw.png new file mode 100644 index 0000000..a35cb80 Binary files /dev/null and b/assets_src/renders_topdown/streamvan_raw.png differ diff --git a/assets_src/renders_topdown/terrain_raw.png b/assets_src/renders_topdown/terrain_raw.png new file mode 100644 index 0000000..e8f9e85 Binary files /dev/null and b/assets_src/renders_topdown/terrain_raw.png differ diff --git a/assets_src/renders_topdown/wax.png b/assets_src/renders_topdown/wax.png new file mode 100644 index 0000000..46ce62b Binary files /dev/null and b/assets_src/renders_topdown/wax.png differ diff --git a/assets_src/renders_topdown/wax_raw.png b/assets_src/renders_topdown/wax_raw.png new file mode 100644 index 0000000..f17ba16 Binary files /dev/null and b/assets_src/renders_topdown/wax_raw.png differ diff --git a/mods/vinylgod/maps/district/map.bin b/mods/vinylgod/maps/district/map.bin new file mode 100644 index 0000000..0dac3cd Binary files /dev/null and b/mods/vinylgod/maps/district/map.bin differ diff --git a/mods/vinylgod/maps/district/map.png b/mods/vinylgod/maps/district/map.png new file mode 100644 index 0000000..21276e9 Binary files /dev/null and b/mods/vinylgod/maps/district/map.png differ diff --git a/mods/vinylgod/maps/district/map.yaml b/mods/vinylgod/maps/district/map.yaml new file mode 100644 index 0000000..95fb87a --- /dev/null +++ b/mods/vinylgod/maps/district/map.yaml @@ -0,0 +1,62 @@ +MapFormat: 12 + +RequiresMod: vinylgod + +Title: Pressing District + +Author: Monster Robot Party + +Tileset: VINYLGOD + +MapSize: 66,66 + +Bounds: 1,1,64,64 + +Visibility: Lobby + +Categories: Maps + +Players: + PlayerReference@Neutral: + Name: Neutral + OwnsWorld: True + NonCombatant: True + Faction: Random + PlayerReference@Creeps: + Name: Creeps + NonCombatant: True + Faction: Random + PlayerReference@Multi0: + Name: Multi0 + Playable: True + Faction: Random + Enemies: Creeps + PlayerReference@Multi1: + Name: Multi1 + Playable: True + Faction: Random + Enemies: Creeps + PlayerReference@Multi2: + Name: Multi2 + Playable: True + Faction: Random + Enemies: Creeps + PlayerReference@Multi3: + Name: Multi3 + Playable: True + Faction: Random + Enemies: Creeps + +Actors: + Actor0: mpspawn + Owner: Multi0 + Location: 8,8 + Actor1: mpspawn + Owner: Multi1 + Location: 57,8 + Actor2: mpspawn + Owner: Multi2 + Location: 8,57 + Actor3: mpspawn + Owner: Multi3 + Location: 57,57 diff --git a/mods/vinylgod/rules/combat.yaml b/mods/vinylgod/rules/combat.yaml index 9006851..201d2de 100644 --- a/mods/vinylgod/rules/combat.yaml +++ b/mods/vinylgod/rules/combat.yaml @@ -9,6 +9,8 @@ spinner: Inherits: ^ArmedUnit + -WithSpriteBody: + WithFacingSpriteBody: Buildable: Queue: Vehicle BuildPaletteOrder: 40 @@ -29,6 +31,8 @@ spinner: stacktank: Inherits: ^ArmedUnit + -WithSpriteBody: + WithFacingSpriteBody: Buildable: Queue: Vehicle BuildPaletteOrder: 50 @@ -49,6 +53,8 @@ stacktank: basscannon: Inherits: ^ArmedUnit + -WithSpriteBody: + WithFacingSpriteBody: Buildable: Queue: Vehicle BuildPaletteOrder: 60 diff --git a/mods/vinylgod/rules/economy.yaml b/mods/vinylgod/rules/economy.yaml index 8086fee..f947977 100644 --- a/mods/vinylgod/rules/economy.yaml +++ b/mods/vinylgod/rules/economy.yaml @@ -10,6 +10,8 @@ ^Unit: Inherits: ^EconSprite + FireWarheadsOnDeath: + Weapon: UnitExplode Targetable: TargetTypes: GroundActor MustBeDestroyed: @@ -22,6 +24,8 @@ digger: Inherits: ^Unit + -WithSpriteBody: + WithFacingSpriteBody: Buildable: Queue: Vehicle BuildPaletteOrder: 20 @@ -49,6 +53,8 @@ digger: popupvan: Inherits: ^Unit + -WithSpriteBody: + WithFacingSpriteBody: Buildable: Queue: Vehicle BuildPaletteOrder: 30 @@ -91,6 +97,8 @@ djgrunt: ^EconBuilding: Inherits: ^EconSprite + FireWarheadsOnDeath: + Weapon: BuildingExplode Targetable: TargetTypes: GroundActor, Structure MustBeDestroyed: diff --git a/mods/vinylgod/rules/stream.yaml b/mods/vinylgod/rules/stream.yaml index 157c7e1..e8b825d 100644 --- a/mods/vinylgod/rules/stream.yaml +++ b/mods/vinylgod/rules/stream.yaml @@ -2,6 +2,8 @@ streamvan: Inherits: ^Unit + -WithSpriteBody: + WithFacingSpriteBody: Buildable: Queue: Vehicle BuildPaletteOrder: 31 @@ -121,6 +123,8 @@ printfarm: scraper: Inherits: ^Unit + -WithSpriteBody: + WithFacingSpriteBody: Buildable: Queue: Vehicle BuildPaletteOrder: 21 @@ -168,6 +172,8 @@ bufferbot: drmwalker: Inherits: ^ArmedUnit + -WithSpriteBody: + WithFacingSpriteBody: Buildable: Queue: Vehicle BuildPaletteOrder: 51 diff --git a/mods/vinylgod/sequences/assets/basscannon.png b/mods/vinylgod/sequences/assets/basscannon.png index f00efa4..93952ce 100644 Binary files a/mods/vinylgod/sequences/assets/basscannon.png and b/mods/vinylgod/sequences/assets/basscannon.png differ diff --git a/mods/vinylgod/sequences/assets/bigboom.png b/mods/vinylgod/sequences/assets/bigboom.png new file mode 100644 index 0000000..e3bf748 Binary files /dev/null and b/mods/vinylgod/sequences/assets/bigboom.png differ diff --git a/mods/vinylgod/sequences/assets/digger.png b/mods/vinylgod/sequences/assets/digger.png index dbb3cd9..4169eb2 100644 Binary files a/mods/vinylgod/sequences/assets/digger.png and b/mods/vinylgod/sequences/assets/digger.png differ diff --git a/mods/vinylgod/sequences/assets/drmwalker.png b/mods/vinylgod/sequences/assets/drmwalker.png index 512f9a6..41dc9c6 100644 Binary files a/mods/vinylgod/sequences/assets/drmwalker.png and b/mods/vinylgod/sequences/assets/drmwalker.png differ diff --git a/mods/vinylgod/sequences/assets/pop.png b/mods/vinylgod/sequences/assets/pop.png new file mode 100644 index 0000000..377c319 Binary files /dev/null and b/mods/vinylgod/sequences/assets/pop.png differ diff --git a/mods/vinylgod/sequences/assets/popupvan.png b/mods/vinylgod/sequences/assets/popupvan.png index e362894..c57ec1e 100644 Binary files a/mods/vinylgod/sequences/assets/popupvan.png and b/mods/vinylgod/sequences/assets/popupvan.png differ diff --git a/mods/vinylgod/sequences/assets/scraper.png b/mods/vinylgod/sequences/assets/scraper.png index 6d7b861..eba1483 100644 Binary files a/mods/vinylgod/sequences/assets/scraper.png and b/mods/vinylgod/sequences/assets/scraper.png differ diff --git a/mods/vinylgod/sequences/assets/seven_inch_proj.png b/mods/vinylgod/sequences/assets/seven_inch_proj.png new file mode 100644 index 0000000..6f92cfc Binary files /dev/null and b/mods/vinylgod/sequences/assets/seven_inch_proj.png differ diff --git a/mods/vinylgod/sequences/assets/spinner.png b/mods/vinylgod/sequences/assets/spinner.png index 606d89a..58f2253 100644 Binary files a/mods/vinylgod/sequences/assets/spinner.png and b/mods/vinylgod/sequences/assets/spinner.png differ diff --git a/mods/vinylgod/sequences/assets/stacktank.png b/mods/vinylgod/sequences/assets/stacktank.png index daae591..33c294f 100644 Binary files a/mods/vinylgod/sequences/assets/stacktank.png and b/mods/vinylgod/sequences/assets/stacktank.png differ diff --git a/mods/vinylgod/sequences/assets/streamvan.png b/mods/vinylgod/sequences/assets/streamvan.png index 9d710b5..131f84d 100644 Binary files a/mods/vinylgod/sequences/assets/streamvan.png and b/mods/vinylgod/sequences/assets/streamvan.png differ diff --git a/mods/vinylgod/sequences/assets/wax.png b/mods/vinylgod/sequences/assets/wax.png index 5be7c5e..af7e20f 100644 Binary files a/mods/vinylgod/sequences/assets/wax.png and b/mods/vinylgod/sequences/assets/wax.png differ diff --git a/mods/vinylgod/sequences/economy.yaml b/mods/vinylgod/sequences/economy.yaml index ff2cef5..f46c094 100644 --- a/mods/vinylgod/sequences/economy.yaml +++ b/mods/vinylgod/sequences/economy.yaml @@ -9,12 +9,14 @@ clock: digger: idle: Filename: sequences/assets/digger.png + Facings: 16 icon: Filename: sequences/assets/icon_digger.png popupvan: idle: Filename: sequences/assets/popupvan.png + Facings: 16 icon: Filename: sequences/assets/icon_popupvan.png @@ -63,18 +65,21 @@ garage: spinner: idle: Filename: sequences/assets/spinner.png + Facings: 16 icon: Filename: sequences/assets/icon_spinner.png stacktank: idle: Filename: sequences/assets/stacktank.png + Facings: 16 icon: Filename: sequences/assets/icon_stacktank.png basscannon: idle: Filename: sequences/assets/basscannon.png + Facings: 16 icon: Filename: sequences/assets/icon_basscannon.png @@ -93,6 +98,7 @@ mastering: streamvan: idle: Filename: sequences/assets/streamvan.png + Facings: 16 icon: Filename: sequences/assets/icon_streamvan.png @@ -129,6 +135,7 @@ printfarm: scraper: idle: Filename: sequences/assets/scraper.png + Facings: 16 icon: Filename: sequences/assets/icon_scraper.png @@ -141,5 +148,19 @@ bufferbot: drmwalker: idle: Filename: sequences/assets/drmwalker.png + Facings: 16 icon: Filename: sequences/assets/icon_drmwalker.png + +seven_inch_proj: + idle: + Filename: sequences/assets/seven_inch_proj.png + Length: 4 + +explosion: + pop: + Filename: sequences/assets/pop.png + Length: 8 + bigboom: + Filename: sequences/assets/bigboom.png + Length: 12 diff --git a/mods/vinylgod/tilesets/vinylgod/vinylgod.png b/mods/vinylgod/tilesets/vinylgod/vinylgod.png index dfc2ebf..f8b0bf4 100644 Binary files a/mods/vinylgod/tilesets/vinylgod/vinylgod.png and b/mods/vinylgod/tilesets/vinylgod/vinylgod.png differ diff --git a/mods/vinylgod/weapons/vinylgod.yaml b/mods/vinylgod/weapons/vinylgod.yaml index 79d8959..77e1789 100644 --- a/mods/vinylgod/weapons/vinylgod.yaml +++ b/mods/vinylgod/weapons/vinylgod.yaml @@ -7,6 +7,9 @@ tonearm_blade: Inherits: ^GroundWeapon + Warhead@2Eff: CreateEffect + Explosions: pop + ValidTargets: Ground, GroundActor ReloadDelay: 12 Range: 1c512 Warhead@1Dam: SpreadDamage @@ -21,11 +24,16 @@ tonearm_blade: seven_inch: Inherits: ^GroundWeapon + Warhead@2Eff: CreateEffect + Explosions: pop + ValidTargets: Ground, GroundActor ReloadDelay: 30 Range: 4c0 Projectile: Bullet Speed: 512 LaunchAngle: 30 + Image: seven_inch_proj + Sequences: idle Warhead@1Dam: SpreadDamage Spread: 96 Damage: 3000 @@ -38,6 +46,9 @@ seven_inch: feedback_burst: Inherits: ^GroundWeapon + Warhead@2Eff: CreateEffect + Explosions: pop + ValidTargets: Ground, GroundActor ReloadDelay: 50 Range: 5c0 Warhead@1Dam: SpreadDamage @@ -52,6 +63,9 @@ feedback_burst: bass_ring: Inherits: ^GroundWeapon + Warhead@2Eff: CreateEffect + Explosions: bigboom + ValidTargets: Ground, GroundActor ReloadDelay: 120 Range: 9c0 MinRange: 2c0 @@ -71,6 +85,9 @@ bass_ring: ping: Inherits: ^GroundWeapon + Warhead@2Eff: CreateEffect + Explosions: pop + ValidTargets: Ground, GroundActor ReloadDelay: 15 Range: 3c512 Warhead@1Dam: SpreadDamage @@ -82,3 +99,13 @@ ping: Wood: 35 Light: 45 Heavy: 15 + +UnitExplode: + Warhead@Eff: CreateEffect + Explosions: pop + ValidTargets: Ground, GroundActor + +BuildingExplode: + Warhead@Eff: CreateEffect + Explosions: bigboom + ValidTargets: Ground, GroundActor diff --git a/tools/__pycache__/mbgen.cpython-314.pyc b/tools/__pycache__/mbgen.cpython-314.pyc index 5ec0c8d..665fbdc 100644 Binary files a/tools/__pycache__/mbgen.cpython-314.pyc and b/tools/__pycache__/mbgen.cpython-314.pyc differ diff --git a/tools/gen_map.py b/tools/gen_map.py new file mode 100644 index 0000000..98bc48e --- /dev/null +++ b/tools/gen_map.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python3 +"""Generate 'Pressing District' — 64x64 4-player skirmish map (yaml + bin + preview).""" +import os, struct +from PIL import Image + +W = H = 66 # 64 playable + 1 border each side +MAP = os.path.join(os.path.dirname(__file__), '..', 'mods', 'vinylgod', 'maps', 'district') +os.makedirs(MAP, exist_ok=True) + +SPAWNS = [(8, 8), (57, 8), (8, 57), (57, 57)] +WAX = [(16, 16, 5), (49, 16, 5), (16, 49, 5), (49, 49, 5), (32, 32, 7), (32, 10, 3), (32, 55, 3), (10, 32, 3), (55, 32, 3)] + +# map.bin: fmt2 header, tiles (template 255 idx 0), resources +data = bytearray() +data += struct.pack(' 16-facing rotation sheets. + +flux renders each vehicle facing NORTH from directly above; PIL rotates into 16 +frames (OpenRA facing order: north first, counter-clockwise), packed into one +horizontal strip with FrameSize metadata. Geometrically correct, unlike rotating +a 3/4-view sprite. Also: terrain tile + wax crystal density sheet. +""" +import os, sys +sys.path.insert(0, os.path.dirname(__file__)) +from mbgen import run, upload # noqa: E402 +from PIL import Image # noqa: E402 +from PIL.PngImagePlugin import PngInfo # noqa: E402 + +ROOT = os.path.join(os.path.dirname(__file__), '..') +RENDERS = os.path.join(ROOT, 'assets_src', 'renders_topdown') +ASSETS = os.path.join(ROOT, 'mods', 'vinylgod', 'sequences', 'assets') +os.makedirs(RENDERS, exist_ok=True) + +MRP = 'rusty junkyard robot aesthetic, rust metal with hot pink trim, ' +STR = 'glossy seamless white tech aesthetic, soft blue ring lights, ' +SUF = ', viewed from directly above, top-down aerial view, vehicle pointing straight up toward the top of the image, single object centered, video game sprite, plain flat grey background, no text, no shadow' + +VEHICLES = [ + ('digger', 26, MRP + 'forklift harvester truck carrying crates of vinyl records'), + ('popupvan', 26, MRP + 'delivery truck covered in band stickers with roof loudspeaker'), + ('spinner', 20, MRP + 'small round robot riding a single vinyl record wheel with blade arms'), + ('stacktank', 30, MRP + 'heavy tracked tank made of stacked speaker cabinets with subwoofer turret'), + ('basscannon', 30, MRP + 'long six-wheeled flatbed truck with one colossal subwoofer cannon'), + ('streamvan', 26, STR + 'sleek white autonomous delivery van with blue play-button roof logo'), + ('scraper', 24, STR + 'white autonomous street sweeper vehicle with glowing blue front intake'), + ('drmwalker', 30, STR + 'white quad-legged mech with one blue ring light, seen from above'), +] + + +def sheet16(im, size, out): + im = im.crop(im.getbbox() or (0, 0, im.width, im.height)) + im.thumbnail((size * 4, size * 4), Image.LANCZOS) # rotate at 4x, downscale after + strip = Image.new('RGBA', (size * 16, size), (0, 0, 0, 0)) + for i in range(16): + fr = im.rotate(i * 22.5, expand=False, resample=Image.BICUBIC) + fr.thumbnail((size, size), Image.LANCZOS) + strip.paste(fr, (i * size + (size - fr.width) // 2, (size - fr.height) // 2), fr) + meta = PngInfo() + meta.add_text('FrameSize', f'{size},{size}') + strip.save(out, pnginfo=meta) + print(f'[facings] {out}', flush=True) + + +for name, size, prompt in VEHICLES: + raw = os.path.join(RENDERS, f'{name}_raw.png') + cut = os.path.join(RENDERS, f'{name}.png') + if not os.path.exists(cut): + run('flux_local', {'prompt': prompt + SUF}, raw) + run('bg_remove_local', {}, cut, asset_id=upload(raw)) + sheet16(Image.open(cut).convert('RGBA'), size, os.path.join(ASSETS, f'{name}.png')) + +# terrain tile: seamless ground texture -> 32x32 +traw = os.path.join(RENDERS, 'terrain_raw.png') +if not os.path.exists(traw): + run('flux_local', {'prompt': 'seamless tileable texture, cracked dark asphalt with faint dust and tiny speckles, muted grey brown, flat even lighting, top down, no objects'}, traw) +t = Image.open(traw).convert('RGBA').resize((64, 64), Image.LANCZOS).crop((16, 16, 48, 48)) +t.save(os.path.join(ROOT, 'mods', 'vinylgod', 'tilesets', 'vinylgod', 'vinylgod.png')) +print('[terrain] tile written', flush=True) + +# wax crystals: one cluster render -> 12 density frames +wraw = os.path.join(RENDERS, 'wax_raw.png') +wcut = os.path.join(RENDERS, 'wax.png') +if not os.path.exists(wcut): + run('flux_local', {'prompt': 'cluster of jagged black vinyl crystal shards glowing hot pink from the cracks, viewed from directly above, top down, video game resource sprite, single cluster centered, plain flat grey background'}, wraw) + run('bg_remove_local', {}, wcut, asset_id=upload(wraw)) +w = Image.open(wcut).convert('RGBA') +w = w.crop(w.getbbox() or (0, 0, w.width, w.height)) +strip = Image.new('RGBA', (32 * 12, 32), (0, 0, 0, 0)) +spots = [(16, 16), (7, 9), (24, 10), (9, 24), (24, 24), (16, 6), (5, 17), (27, 18), (16, 26), (11, 13), (21, 15), (16, 20)] +for f in range(12): + for i in range(f + 1): + s = 10 + (6 if i == 0 else 0) + c = w.copy() + c.thumbnail((s, s), Image.LANCZOS) + c = c.rotate(i * 47, expand=False) + x, y = spots[i] + strip.paste(c, (f * 32 + x - c.width // 2, y - c.height // 2), c) +meta = PngInfo() +meta.add_text('FrameSize', '32,32') +strip.save(os.path.join(ASSETS, 'wax.png'), pnginfo=meta) +print('[wax] density sheet written', flush=True) +print('ALL DONE')