Commit Graph
4 Commits
Author SHA1 Message Date
arcattackandClaude Opus 5 ef0ec48f9a map dropdown = the AUTHENTIC console catalog; the relay names a phantom-map stall instead of holding silently
THE 40-MINUTE OUTAGE'S REAL FIX.  The GUI's map dropdown offered every RES
name passing the type-14+26 existence check -- which includes INTERNAL
FRAGMENTS: artrucks is an include-node of arena1 (PROGRESS_LOG map anatomy:
arena1 -> {arenall -> cavern, artrucks}), not a mission.  Picking it stalled
every pod's mission load forever with no error anywhere, and End/Re-arm kept
restoring the poisoned egg -- 22:02..22:49, three "different" failures, one
cause.

  * eggmodel.CONSOLE_MAPS: the Mac 4.10 operator console's own adventure-tree
    catalog (Console.ini; the same 8 the solo menu ships in btl4fe.cpp kMaps):
    cavern grass rav polar3 polar4 arena1 arena2 dbase.  ValueSets.maps now
    offers exactly that, catalog order, filtered to what the RES carries
    (permissive fallback only if the intersection is empty -- a foreign RES
    must not present zero maps).  artrucks is the one fragment the old filter
    let through; now hidden.
  * The relay WARNS at egg load/reload when the mission names a non-catalog
    map (the camo-color-warning precedent: hand-edited eggs still work, the
    operator just cannot miss it).
  * The launch hold gains the PHANTOM-MISSION SIGNATURE diagnostic: 0/N ready
    for 60s means every pod is stalled in shared mission content -- one line
    naming the egg's map and the recovery (End Mission -> fix map -> Re-arm),
    instead of the silent 10s HELD drumbeat the operator stared at for 40
    minutes.  Hint re-arms per launch.

VERIFIED: new suite scratchpad/test_map_guard.py (5 checks: catalog exact +
ordered, artrucks hidden, warning fires on a doctored egg, silent on a real
one, the 60s hint names the map); all five console suites pass.  Python-only.

(While placing the hint, a blind text-insert broke the launch-received block's
indentation -- caught by py_compile before anything ran, repaired, and the
whole area re-verified by the rearm suite.)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-27 00:19:20 -05:00
arcattackandClaude Fable 5 7e49fb2284 Vehicle sweep: ALL 18 mech ModelList names certified playable
The egg generator's known-good list was just bhk1+madcat (the only two
ever exercised as egg vehicles); the operator roster therefore leaned on
those.  Swept every ModelList candidate as a solo egg vehicle: 18/18
boot a mission, spawn, and animate with no crash -- avatar, blkhawk,
loki, owens, sunder, thor, vulture and all short variants (ava1, lok1/2,
mad1/2, own1, snd1, thr1, vul1) join bhk1/madcat as first-class picks.
eggmodel now lists the canonical 8 first for the operator dropdown.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 13:46:55 -05:00
arcattackandClaude Fable 5 5e993de99d Operator-set callsigns: the console's name-bitmap generator recreated
The 1995 console let the operator type player callsigns; the pods render
them from 1bpp BITMAPS streamed in the egg ([largebitmap]/[smallbitmap]
lists + hex raster pages, bitmapindex per pilot; large 128x32 on the
score/ranking display via DPLRenderer name textures, small 64x16 on the
kill-feed and radar/target labels). The textual name= pilot key is dead
in the shipped binary -- its pilot parse reads bitmapindex only (decomp
part_014). Historical bug surfaced by this work: every egg in the repo
listed only ONE name bitmap (Aeolus) while pilot 2 pointed at index 2,
so player 2+'s callsign has never rendered (null-checked, silently
blank).

eggmodel.py: EggDoc.set_callsigns rewrites the lists + one raster page
per callsign per size + per-pilot name=/bitmapindex= (duplicate names
get disambiguated page tags); get_callsign_rows decodes pages back
(exact inverse of the engine's nibble-stream parse, GRAPH2D.cpp:340,
MSB-first bit order :558); rasterize_callsign/make_callsigns render
text via Qt (auto-shrink to fit, NoAntialias, 1bpp threshold) -- the
only PySide6-dependent corner of the module. validate() now catches
dangling bitmapindexes and missing raster pages.

btoperator.py: Callsign column in the roster (free text, PLAYERn
default); every save rasterizes the column into the egg exactly like
the original console did.

MP_BHMC.EGG template repaired: authentic Aeolus raster preserved
bit-exact, Boreas page generated and listed.

Verified: eggmodel self-test 20/20 (bit-exact raster round-trip, dup
disambiguation, dangling-index catch); ASCII-art decode of the
app-generated VIPER/MONGOOSE rasters reads correctly; live 2-node
relay session on the generated egg -- full ladder, launch, zero
name-bitmap load warnings; operator GUI e2e PASS after the column
shift.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 12:29:57 -05:00
arcattackandClaude Fable 5 43fa53d542 Operator console app: PySide6 station + validated egg model (the lost 1995 console, recreated)
The operator station the archive never preserved: build missions with
authoritative dropdowns, run the console/relay, watch pods arrive, launch --
LAN mesh or internet relay -- plus one-click local instances for testing.

tools/eggmodel.py (headless, importable, self-tested 14/14):
- Order-preserving egg parse/emit: the editor manages [mission]/[pilots]/
  per-pilot pages; bitmap rasters, ordinals and role pages survive untouched.
- EVERY value set read LIVE from content/BTL4.RES (the resscan parser,
  importable): maps = MakeMessageStream(14) INTERSECT ExistanceBoxStream(26)
  (the game aborts unless both exist); colors/badges/patches from the
  VehicleTable resource (type 25, NUL-line NotationFile text with ;-comments);
  vehicles = ModelList names, known-good mechs (bhk1, madcat) surfaced first.
- validate(): the full required-key ruleset from MISSION.cpp/btl4mssn.cpp
  (missing map/time/weather/scenario, per-pilot hostType/vehicle/dropzone/
  color/patch/badge/experience/role, role page model=, illegal values,
  duplicate addresses) -- kills the hand-edited-egg crash class, incl. the
  color=Red-vs-Crimson gotcha that bit the dev eggs.

tools/btoperator.py (PySide6, dark Fusion theme):
- Mission form + pilot roster table (all dropdowns from eggmodel), relay-tag
  auto-numbering, add/remove pilots, egg New/Open/Save/Validate.
- Mode switch: Relay (internet; runs btconsole --relay) / Mesh (LAN legacy;
  dial-out console at address-port minus 1 per the +1 rule).
- Session panel: QProcess drives btconsole.py; stdout parsed live into
  per-pilot state lights (waiting/egg/registered/LAUNCHED) + relay stats.
- Local launcher: spawns btl4.exe per roster row with BT_RELAY/BT_SELF (or
  mesh -net port), BT_DEV_GAUGES/BT_START_INSIDE toggles.
- Export player scripts: per-pilot join_as_playerN.bat with the public
  relay hostname (a remote player's whole setup = run one .bat).
- Wire/protocol code stays in btconsole.py/eggmodel.py -- the GUI is only
  UI + process management; CLI + test harnesses share the same tested core.

Verified: eggmodel self-test 14/14; scripted end-to-end
(scratchpad/operator_e2e.py) drives the real window through its own methods --
start relay session -> launch 2 local instances -> monitor observes the
mission LAUNCH (user-confirmed live on screen: both pods in-mission).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 10:57:30 -05:00