import struct
data = open(r'C:/git/bt411/content/BTL4.RES','rb').read()
n = len(data)

def cstr(off, maxlen=32):
    s = data[off:off+maxlen].split(b'\0')[0]
    try: return s.decode('ascii')
    except: return None

def f32(off): return struct.unpack_from('<f', data, off)[0]
def i32(off): return struct.unpack_from('<i', data, off)[0]

# find ALL subsystem records (same heuristic as scan_weapsub.py)
recs = []
i = 0
while i < n - 0x28:
    cid = struct.unpack_from('<I', data, i+0x20)[0]
    if 0xBB0 <= cid <= 0xBE5:
        sz = struct.unpack_from('<I', data, i+0x24)[0]
        if 0xE0 <= sz <= 0x300:
            name = cstr(i)
            if name and 2 <= len(name) <= 31 and all(32 < ord(c) < 127 for c in name):
                pad = data[i+len(name):i+0x20]
                if pad.count(0) >= len(pad) - 2:
                    recs.append((i, name, cid, sz))
                    i += 0x28
                    continue
    i += 1

# group into chains (consecutive: next record at p+sz)
chains = []
cur = []
for k,(p,name,cid,sz) in enumerate(recs):
    if cur and cur[-1][0] + cur[-1][3] == p:
        cur.append(recs[k])
    else:
        if cur: chains.append(cur)
        cur = [recs[k]]
if cur: chains.append(cur)

mechnames = [b'madcat', b'bhk', b'vulture', b'thor', b'blackhawk', b'blh', b'owens', b'strider', b'sunder', b'cauldron', b'avatar', b'mdc']
low = data.lower()
namepos = []
for m in mechnames:
    j = 0
    while True:
        j = low.find(m, j)
        if j < 0: break
        namepos.append((j, m.decode()))
        j += 1
namepos.sort()

def nearest_label(p):
    best = None
    for pos, name in namepos:
        if pos < p: best = (pos, name)
        else: break
    return best

HEAT = {0xBBD:'Condenser', 0xBBE:'AggregateHeatSink', 0xBC0:'Reservoir', 0xBBB:'HeatSink?', 0xBBC:'?'}
WEAP = {0xBC8:'Emitter', 0xBD4:'PPC', 0xBCD:'ProjWeapon', 0xBCE:'GaussRifle', 0xBD0:'MissileLauncher'}

for ci, ch in enumerate(chains):
    lbl = nearest_label(ch[0][0])
    names = [c[1] for c in ch]
    print(f'--- chain {ci} @0x{ch[0][0]:x} n={len(ch)} nearest-name={lbl}')
    for idx,(p,name,cid,sz) in enumerate(ch):
        tag = HEAT.get(cid) or WEAP.get(cid)
        if cid in HEAT:
            st, dg, ft = f32(p+0xE4), f32(p+0xE8), f32(p+0xEC)
            tc, tm = f32(p+0xF0), f32(p+0xF4)
            hsi = i32(p+0xF8)
            line = (f'  [{idx:2d}] {name:20s} cid=0x{cid:X}({tag}) sz=0x{sz:X} '
                    f'StartT={st:g} DegT={dg:g} FailT={ft:g} Conduct={tc:g} ThermMass={tm:g} HeatSinkIdx={hsi}')
            if cid == 0xBBD:
                line += f' RefrigFactor={f32(p+0xFC):g}'
            elif cid == 0xBBE:
                line += f' HeatSinkCount={i32(p+0xFC)}'
            elif cid == 0xBC0:
                line += f' CoolantCap={f32(p+0xFC):g} SquirtMass={f32(p+0x100):g}'
            print(line)
        elif cid in WEAP:
            heat = f32(p+0x1A4)
            print(f'  [{idx:2d}] {name:20s} cid=0x{cid:X}({tag}) Heat={heat:g}')
        else:
            print(f'  [{idx:2d}] {name:20s} cid=0x{cid:X} sz=0x{sz:X}')
