"""Speech lines across languages (ackit/lines.py) on a small two-language game built like the real one: one localized AkBank export holds, per declared language, the BKPK table of the speech entry and a bank whose Sound objects (same IDs in every language) name that language's recordings.""" import hashlib import os import struct from ackit import banks from ackit.bnk import fnv1 from ackit.catalog import build_lines from ackit.game import Game from ackit.wem import fill from ackit.workspace import ORIGINAL, MODIFIED, Workspace import synth ENTRY, COPY_ENTRY = 0x51000001, 0x52000001 EV_A, EV_B = "Speech_Lines_A", "Speech_Lines_B" # media: line A has its own ID per language; line B uses one ID in both languages (as cinematics do) A = {"INT": 0x10, "ITA": 0x20} B = 0x77 def _table(entry, rows): """BKPK table: rows [(media, wem bytes, offset in the entry)].""" t = bytearray(0x48) struct.pack_into("<4sII", t, 0, b"BKPK", 0x01020000, entry) end = max(o + len(w) for _, w, o in rows) struct.pack_into(" here INT puts A first, # ITA is written the other way round to show that positions do not matter order = {"INT": [a["INT"], b["INT"]], "ITA": [b["ITA"], a["ITA"]]} rows = {} for L, ws in order.items(): offs = _offsets(ws) media = [A[L], B] if L == "INT" else [B, A[L]] rows[L] = list(zip(media, ws, offs)) wads = {"INT": ("English(US)", "28CCF006_LOC_INT.wad"), "ITA": ("Italian", "49D84887_LOC_ITA.wad")} for L, (folder, name) in wads.items(): payloads = {ENTRY: synth.grouped(order[L])} if L == "INT": payloads[COPY_ENTRY] = a["INT"] # the same recording stored a second time synth.write_wad(os.path.join(cooked, folder, name), payloads) # the localized export: language list, then per language its BKPK table(s) and its bank lst = struct.pack("