import struct, sys
data = open(r'C:\git\bt411\content\BTL4.RES', 'rb').read()
labOnly, maxID = struct.unpack_from('<ii', data, 4)
offs = struct.unpack_from('<%dI' % maxID, data, 12)

# ResourcePhysicalFormat: id i32, type i32, name[32], prio i32, flags i32, offset i32, length i32
recs = []
for o in offs:
    if o == 0: continue
    rid, rt = struct.unpack_from('<ii', data, o)
    nm = data[o+8:o+40].split(b'\0')[0].decode('ascii','replace')
    prio, flags, roff, rlen = struct.unpack_from('<iiII', data, o+40)
    recs.append((rid, rt, nm, roff, rlen))

DZ = [r for r in recs if r[1] == 20]
print('type-0x14 DamageZoneStream resources:')
for r in DZ:
    print('  id=%d name=%r off=0x%x len=%d' % (r[0], r[2], r[3], r[4]))

def parse_zone_stream(buf, tag):
    p = 0
    def i32():
        nonlocal p
        v = struct.unpack_from('<i', buf, p)[0]; p += 4; return v
    def f32():
        nonlocal p
        v = struct.unpack_from('<f', buf, p)[0]; p += 4; return v
    def cstr():
        nonlocal p
        n = i32()
        s = buf[p:p+n].decode('ascii','replace'); p += n + 1
        return s
    count = i32()
    print('\n===== %s: zoneCount=%d streamLen=%d =====' % (tag, count, len(buf)))
    for z in range(count):
        name = cstr()
        sites = []
        for j in range(5):
            c = i32()
            sites.append([i32() for _ in range(c)])
        dap = f32()
        scales = [f32() for _ in range(5)]
        sklcount = i32()
        mats = []
        for s in range(sklcount):
            styp = i32()
            mc = i32()
            names = [cstr() for _ in range(mc)]
            mats.append((styp, names))
        descend = i32(); sibs = i32(); segidx = i32()
        lleg = i32(); rleg = i32(); vital = i32(); ncrit = i32()
        crits = []
        for c in range(ncrit):
            w = f32(); pct = f32(); sidx = i32()
            crits.append((w, pct, sidx))
        nred = i32()
        redirects = [i32() for _ in range(nred)]
        # implied per-type armor points: scale = 1/points  -> points = 1/scale
        pts = ['%g' % (1.0/s if s else 0) for s in scales]
        print('zone %2d %-24s armor(default)=%g scale=[%s] -> points=[%s]' %
              (z, name, dap, ' '.join('%.6g' % s for s in scales), ' '.join(pts)))
        print('        seg=%d vital=%d legs(L%d,R%d) descend=%d sibs=%d mats=%d crits=%s redirects=%s' %
              (segidx, vital, lleg, rleg, descend, sibs, sklcount,
               [(round(w,3), round(pc,3), si) for (w,pc,si) in crits], redirects))
    print('consumed %d of %d bytes' % (p, len(buf)))

want = [n.lower() for n in (sys.argv[1:] or ['madcat','bhk1'])]
for (rid, rt, nm, roff, rlen) in DZ:
    if any(w in nm.lower() for w in want):
        parse_zone_stream(data[roff:roff+rlen], 'id=%d %s' % (rid, nm))
