* All 17 buildings now RISE out of the ground behind a pink scan line when built (tools/make_anims.py generates 7-frame make sequences; WithMakeAnimation on the building template). * Boombox Crates: neutral pickups spawn on a timer (max 4). 500 records usually, 1500 jackpot sometimes, bass_ring feedback trap rarely. Locomotors crush crates to collect, classic style. * Lobby faction flags are real now: MRP record, Stream play button, split '?'. * MC 8-TRACK and ASSISTANT portraits generated for briefings/press kit. * Balance ledger updated: first aura-era match went to Stream (runaway flag); full ledger M M M | S S | M | S — boundary variance, no knee-jerk tune. Smoke-tested PASS on arena and m01 with everything live. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
62 lines
2.4 KiB
Python
62 lines
2.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Generate construction 'make' animations for every building.
|
|
|
|
7 frames per building: the structure rises out of the ground behind a hot pink
|
|
scan line, classic buildup feel without hand-drawn scaffolding. Source frames
|
|
are the static frame-0 backups maintained by animate_sprites.py.
|
|
|
|
Writes <name>_make.png sheets and appends `make:` sequences.
|
|
"""
|
|
import os
|
|
from PIL import Image, ImageDraw
|
|
from PIL.PngImagePlugin import PngInfo
|
|
|
|
ROOT = os.path.join(os.path.dirname(__file__), '..')
|
|
ASSETS = os.path.join(ROOT, 'mods', 'vinylgod', 'sequences', 'assets')
|
|
BACKUP = os.path.join(ROOT, 'assets_src', 'static_frames')
|
|
SEQ = os.path.join(ROOT, 'mods', 'vinylgod', 'sequences', 'economy.yaml')
|
|
|
|
FRAMES = 7
|
|
PINK = (255, 45, 150, 255)
|
|
|
|
BUILDINGS = ['popupshop', 'pressplant', 'ampstack', 'vault', 'merchtable', 'garage',
|
|
'mastering', 'hornpit', 'streamhub', 'datacentre', 'transcoder', 'podfarm',
|
|
'printfarm', 'adblocker', 'algorithm', 'launchramp', 'droneport']
|
|
|
|
seq = open(SEQ).read()
|
|
made = []
|
|
for name in BUILDINGS:
|
|
src = os.path.join(BACKUP, f'{name}.png')
|
|
if not os.path.exists(src):
|
|
continue
|
|
base = Image.open(src).convert('RGBA')
|
|
w, h = base.size
|
|
sheet = Image.new('RGBA', (w * FRAMES, h), (0, 0, 0, 0))
|
|
for i in range(FRAMES):
|
|
t = (i + 1) / FRAMES
|
|
reveal = int(h * t) # rows revealed, bottom-up
|
|
rise = int((1 - t) * h * 0.25) # slight rise from the ground
|
|
frame = Image.new('RGBA', (w, h), (0, 0, 0, 0))
|
|
part = base.crop((0, h - reveal, w, h))
|
|
frame.paste(part, (0, h - reveal + rise), part)
|
|
d = ImageDraw.Draw(frame)
|
|
if i < FRAMES - 1:
|
|
y = h - reveal + rise
|
|
if 0 <= y < h:
|
|
d.line([0, y, w, y], fill=PINK, width=2)
|
|
sheet.paste(frame, (i * w, 0))
|
|
meta = PngInfo()
|
|
meta.add_text('FrameSize', f'{w},{h}')
|
|
sheet.save(os.path.join(ASSETS, f'{name}_make.png'), pnginfo=meta)
|
|
|
|
block = f'{name}:\n\tidle:'
|
|
if block in seq and f'{name}:\n\tidle:' in seq and f'sequences/assets/{name}_make.png' not in seq:
|
|
seq = seq.replace(f'{name}:\n\tidle:',
|
|
f'{name}:\n\tmake:\n\t\tFilename: sequences/assets/{name}_make.png\n'
|
|
f'\t\tLength: {FRAMES}\n\t\tTick: 70\n\tidle:', 1)
|
|
made.append(name)
|
|
print(f'make anim: {name}')
|
|
|
|
open(SEQ, 'w').write(seq)
|
|
print(f'{len(made)} buildup animations written')
|