KAZIK/tools/generators/pack_cabaret_musicians.py
Artvasil09 797ee366dc feat: implement upper lounge, manual stairs, cabaret, and casino terminals
- Native player-controlled stairs, upper lounge bar, and Hell Tower infernal portal
- Cabaret stage with musical acts, audience seating, and interaction
- Dedicated cash/trophy wall terminals with native balance and achievement screens
- Projecting 3D wall lanterns with ray/plane intersection
- Six roaming guests with seated poses and card rank rendering updates
- Synchronized launcher hash and updated binaries
2026-10-18 21:36:12 +03:00

47 lines
2.1 KiB
Python

"""Pack the approved piano/pianist and guitarist cutouts for the MASM stage."""
from pathlib import Path
import struct
from PIL import Image
ROOT = Path(__file__).resolve().parents[2]
def pack(sheet, left, right, width, name):
cells = [sheet.crop((left, row * 384, right, (row + 1) * 384))
for row in range(4)]
bounds = [cell.getchannel("A").point(lambda a: 255 if a >= 128 else 0).getbbox()
for cell in cells]
assert all(bounds), "each playing pose must contain opaque pixels"
box = (min(b[0] for b in bounds), min(b[1] for b in bounds),
max(b[2] for b in bounds), max(b[3] for b in bounds))
scale = min((width - 12) / (box[2] - box[0]), 244 / (box[3] - box[1]))
size = (round((box[2] - box[0]) * scale), round((box[3] - box[1]) * scale))
frames = []
for cell in cells:
sprite = cell.crop(box).resize(size, Image.Resampling.LANCZOS)
# The native sprite rasterizer uses a binary alpha test.
sprite.putalpha(sprite.getchannel("A").point(lambda a: 255 if a >= 128 else 0))
canvas = Image.new("RGBA", (width, 256))
canvas.alpha_composite(sprite, ((width - size[0]) // 2, 250 - size[1]))
frames.append(canvas)
raw = b"".join(frame.tobytes("raw", "BGRA") for frame in frames)
(ROOT / f"assets/animations/hall/{name}-v1.bin").write_bytes(
struct.pack("<4s4I", b"ANM1", width, 256, 4, len(raw)) + raw)
return frames
def main():
sheet = Image.open(ROOT / "assets/sprites/hall/cabaret-musicians-v1.png").convert("RGBA")
assert sheet.size == (1024, 1536)
piano = pack(sheet, 0, 640, 384, "cabaret-piano")
guitar = pack(sheet, 640, 1024, 160, "cabaret-guitar")
preview = Image.new("RGBA", (544, 1024), (24, 28, 29, 255))
for row in range(4):
preview.alpha_composite(piano[row], (0, row * 256))
preview.alpha_composite(guitar[row], (384, row * 256))
preview.save(ROOT / "build/cabaret-musicians-preview.png")
print("Packed coherent grand piano/pianist and guitarist: four anchored poses each")
if __name__ == "__main__":
main()