"""Gitea #46 -- verify the ammo bay fire detonates and applies real damage. Before this fix, three stacked defects made an armed bay fire permanently inert: the clock stub (`0 < 0` never fired), the InjectHeat no-op (nothing applied), and the never-stamped Damage record (0 damage of type 0 even if it had). Rig: BT_BAYTEST= sends message 1 (the crit-induced "begin cook-off countdown", @004bdb94) to the first AmmoBin. The authentic fuse is a FIXED 10.0 seconds (raw disasm @004bd450: 10.0 x ticksPerSecond + 0.5, __ftol -- the old "RandomDelay" was a Ghidra artifact). PASS = [ammo] ... BAY FIRE (message): cook-off armed, N rounds, detonation in 10s ...~10 wall seconds later... [ammo] ... BAY FIRE DETONATION: N rounds x D = total (type T) ammo explosion damaging (the binary's exact @0050df61 print) ...and the mech takes real zone damage (BT_MP_NET handler line / DAMAGE state). Kills only the PID it spawns. """ import os import re import subprocess import sys import time REPO = r"C:\git\bt411" LOG = os.path.join(REPO, "scratchpad_lampflash.log") if os.path.exists(LOG): os.remove(LOG) env = dict(os.environ) env.update({ "BT_START_INSIDE": "1", "BT_DEV_GAUGES": "1", "BT_BAYTEST": "400", # arm at sim frame 400 "BT_AMMO_LOG": "1", "BT_MP_NET": "1", "BT_LAMP_LOG": "1", # [techstat]/[galarm]/[lamp] -- the #47 flash chain # [mp-hdlr] TakeDamageHandler lines (zone + amount) "BT_DEATH_LOG": "1", # crit cascade / zone destruction "BT_LOG": LOG, }) proc = subprocess.Popen( [os.path.join(REPO, "build", "Release", "btl4.exe"), "-egg", "LAST.EGG"], cwd=os.path.join(REPO, "content"), env=env, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) print("pid", proc.pid) try: deadline = time.time() + 240 armed = False while time.time() < deadline: if os.path.exists(LOG): t = open(LOG, errors="replace").read() if "BAY FIRE (message)" in t: armed = True break time.sleep(2) if not armed: print("FAIL: never armed") # wait through the 10s fuse + margin for the fan-out and damage time.sleep(25) finally: proc.terminate() time.sleep(1) t = open(LOG, errors="replace").read() if os.path.exists(LOG) else "" arm = re.findall(r"^\[ammo\].*BAY FIRE.*armed.*$", t, re.M) boom = re.findall(r"^\[ammo\].*DETONATION.*$", t, re.M) zones = re.findall(r"^ammo explosion damaging.*$", t, re.M) hdlr = re.findall(r"^\[mp-hdlr\] TakeDamageHandler.*$", t, re.M) dfx = re.findall(r"^\[deathfx\].*$", t, re.M) ext = re.findall(r"^\[ammo\].*EXTINGUISHED.*$", t, re.M) print("\n=============== RESULT ===============") print("armed:", len(arm)) for l in arm[:2]: print(" ", l[:120]) print("\ndetonation:", len(boom)) for l in boom[:2]: print(" ", l[:130]) print("\n'ammo explosion damaging' zone prints:", len(zones)) for l in zones[:6]: print(" ", l[:100]) print("\nTakeDamage handler runs:", len(hdlr)) for l in hdlr[:4]: print(" ", l[:150]) print("\n[deathfx] zone/crit lines:", len(dfx)) for l in dfx[:8]: print(" ", l[:120]) if ext: print("\nextinguished (unexpected in this rig):", ext[:2]) ok = arm and boom and zones and hdlr print("\nVERDICT:", "PASS -- bay fire armed, detonated on the 10s fuse, and applied real zone damage" if ok else "FAIL -- see which stage is missing above") sys.exit(0 if ok else 2)