BTFrstrm: add weapon location spreadsheets (Special1/2 and rear-facing)
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate special_weapon_locations.csv and rear_facing_weapons.csv from stock mech subsystems."""
|
||||
import csv
|
||||
from pathlib import Path
|
||||
|
||||
BASE = Path("Gameleap/mw4/Content")
|
||||
MECH_TABLE = BASE / "Tables" / "MechTable.tbl"
|
||||
OUT_DIR = Path("BTFrstrm")
|
||||
|
||||
def parse_ini(path):
|
||||
sections, cur_sec, cur_dict = [], None, {}
|
||||
with open(path, 'r', encoding='latin-1', errors='replace') as f:
|
||||
for raw in f:
|
||||
line = raw.strip()
|
||||
if line.startswith('[') and line.endswith(']'):
|
||||
if cur_sec is not None:
|
||||
sections.append((cur_sec, cur_dict))
|
||||
cur_sec, cur_dict = line[1:-1], {}
|
||||
elif '=' in line and cur_sec is not None:
|
||||
k, _, v = line.partition('=')
|
||||
cur_dict[k.strip()] = v.strip()
|
||||
if cur_sec is not None:
|
||||
sections.append((cur_sec, cur_dict))
|
||||
return sections
|
||||
|
||||
def find_dir_ci(parent, name):
|
||||
"""Case-insensitive directory lookup for Linux."""
|
||||
exact = parent / name
|
||||
if exact.exists():
|
||||
return exact
|
||||
name_lower = name.lower()
|
||||
for child in parent.iterdir():
|
||||
if child.is_dir() and child.name.lower() == name_lower:
|
||||
return child
|
||||
return None
|
||||
|
||||
def weapon_model(model_path):
|
||||
return Path(model_path.replace('\\', '/')).stem
|
||||
|
||||
# Read chassis list from MechTable.tbl
|
||||
chassis_list = []
|
||||
with open(MECH_TABLE, 'r', encoding='latin-1') as f:
|
||||
for raw in f:
|
||||
line = raw.strip()
|
||||
if not line or line.startswith('//') or line.startswith('[') or '=' not in line:
|
||||
continue
|
||||
name, _, rel = line.partition('=')
|
||||
# rel is like "Mechs\Atlas\Atlas.instance"
|
||||
parts = rel.strip().replace('\\', '/').split('/')
|
||||
chassis_list.append((name.strip(), parts)) # parts = ['Mechs', 'Atlas', 'Atlas.instance']
|
||||
|
||||
print(f"Found {len(chassis_list)} chassis in MechTable.tbl")
|
||||
|
||||
HDR = ['Chassis', 'InternalLocation', 'Model', 'Site', 'AmmoCount', 'GroupIndex', 'WeaponFacing']
|
||||
special_rows, rear_rows, missing = [], [], []
|
||||
|
||||
mechs_dir = BASE / "Mechs"
|
||||
|
||||
for chassis_name, path_parts in chassis_list:
|
||||
# path_parts[1] is the mech directory name (e.g. 'Atlas', 'MadCat_MkII', 'Urbanmech')
|
||||
if len(path_parts) < 2:
|
||||
missing.append(chassis_name)
|
||||
continue
|
||||
|
||||
mech_dir = find_dir_ci(mechs_dir, path_parts[1])
|
||||
if not mech_dir:
|
||||
missing.append(f"{chassis_name} (dir not found: {path_parts[1]})")
|
||||
continue
|
||||
|
||||
subs = [f for f in mech_dir.glob('*.subsystems') if f.suffix == '.subsystems']
|
||||
if not subs:
|
||||
missing.append(f"{chassis_name} (no .subsystems in {mech_dir.name})")
|
||||
continue
|
||||
|
||||
subsys_file = subs[0]
|
||||
sections = parse_ini(subsys_file)
|
||||
|
||||
for sec_name, fields in sections:
|
||||
if 'WeaponSubsystem' not in fields.get('Model', ''):
|
||||
continue
|
||||
|
||||
loc = fields.get('InternalLocation', '')
|
||||
model = weapon_model(fields.get('Model', ''))
|
||||
site = fields.get('Site', '')
|
||||
ammo = fields.get('AmmoCount', '')
|
||||
group = fields.get('GroupIndex', '')
|
||||
facing = fields.get('WeaponFacing', '')
|
||||
|
||||
if loc in ('Special1', 'Special2'):
|
||||
special_rows.append([chassis_name, loc, model, site, ammo, group, facing])
|
||||
|
||||
if facing and facing != '0':
|
||||
rear_rows.append([chassis_name, loc, model, site, ammo, group, facing])
|
||||
|
||||
# Write CSVs
|
||||
out1 = OUT_DIR / 'special_weapon_locations.csv'
|
||||
with open(out1, 'w', newline='') as f:
|
||||
w = csv.writer(f)
|
||||
w.writerow(HDR)
|
||||
w.writerows(special_rows)
|
||||
|
||||
out2 = OUT_DIR / 'rear_facing_weapons.csv'
|
||||
with open(out2, 'w', newline='') as f:
|
||||
w = csv.writer(f)
|
||||
w.writerow(HDR)
|
||||
w.writerows(rear_rows)
|
||||
|
||||
print(f"Spreadsheet 1 ? Special1/2 weapon locations: {len(special_rows)} rows -> {out1}")
|
||||
print(f"Spreadsheet 2 ? Non-forward WeaponFacing: {len(rear_rows)} rows -> {out2}")
|
||||
if missing:
|
||||
print(f"\nSkipped: {missing}")
|
||||
@@ -0,0 +1,64 @@
|
||||
Chassis,InternalLocation,Model,Site,AmmoCount,GroupIndex,WeaponFacing
|
||||
Archer,LeftTorso,LRM15,site_ldmissile,24,2,2
|
||||
Archer,RightTorso,LRM15,site_rdmissile,24,2,2
|
||||
Ares,Special2,ClanLRM10,site_lmissileport,24,2,2
|
||||
Ares,Special2,ClanLRM10,site_missileport,24,2,2
|
||||
Ares,Special2,ClanLRM10,site_rmissileport,24,2,2
|
||||
AssassinII,Special1,LRM5,site_missileport,24,2,2
|
||||
Atlas,LeftTorso,LRM20,site_lmissileport,12,2,2
|
||||
Avatar,LeftTorso,LRM5,site_lmissileport,24,2,2
|
||||
Avatar,RightTorso,LRM5,site_rmissileport,24,2,2
|
||||
Avatar,LeftTorso,LRM10,site_lmissileport,24,2,2
|
||||
Avatar,RightTorso,LRM10,site_rmissileport,24,2,2
|
||||
Awesome,CenterTorso,LRM5,site_ctorsoport,24,2,2
|
||||
Battlemaster,RightTorso,MediumLaser,site_rdtorsoport,,1,1
|
||||
Battlemaster,LeftTorso,MediumLaser,site_ldtorsoport,,1,1
|
||||
BattlemasterIIC,RightTorso,ClanERMediumLaser,site_rdtorsoport,,1,1
|
||||
BattlemasterIIC,LeftTorso,ClanERMediumLaser,site_ldtorsoport,,1,1
|
||||
Black Lanner,Special2,ClanSRM6,site_rmissileport,15,2,2
|
||||
Black Lanner,Special1,ClanLRM10,site_lmissileport,24,2,2
|
||||
Bushwacker,Special1,LRM5,site_missileport,24,2,2
|
||||
Bushwacker,Special1,LRM5,site_missileport,24,2,2
|
||||
Catapult,LeftArm,LRM20,site_lmissileport,12,2,2
|
||||
Catapult,RightArm,LRM20,site_rmissileport,12,2,2
|
||||
Cauldron-Born,Special1,ClanLRM10,site_rmissileport,24,2,2
|
||||
Cauldron-Born,Special2,ClanLRM10,site_lmissileport,24,2,2
|
||||
Chimera,RightTorso,LRM5,site_missileport,24,2,2
|
||||
Chimera,RightTorso,LRM5,site_missileport,24,2,2
|
||||
Chimera,RightTorso,LRM5,site_missileport,24,2,2
|
||||
Chimera,RightTorso,LRM5,site_missileport,24,2,2
|
||||
Cyclops,LeftTorso,LRM10,site_lmissile,24,2,2
|
||||
Cougar,LeftTorso,ClanLRM10,site_lmissileport,12,2,2
|
||||
Cougar,RightTorso,ClanLRM10,site_rmissileport,12,2,2
|
||||
Deimos,Special1,ClanLRM15,site_lmissileport,16,2,2
|
||||
Deimos,Special2,ClanLRM15,site_rmissileport,16,2,2
|
||||
Dragon,CenterTorso,LRM10,site_missleport,24,2,2
|
||||
Flea,LeftTorso,SmallLaser,site_ltorsoport,,1,1
|
||||
Flea,RightTorso,SmallLaser,site_rtorsoport,,1,1
|
||||
Grizzly,LeftTorso,CLANLRM10,site_missleport,24,2,2
|
||||
Hellhound,LeftTorso,ClanLRM10,site_missileport,12,2,2
|
||||
Mad Cat,Special1,ClanLRM10,site_lmissileport,24,2,2
|
||||
Mad Cat,Special2,ClanLRM10,site_rmissileport,24,2,2
|
||||
Mad Cat MKII,Special2,ClanLRM15,site_lmissileport,16,2,2
|
||||
Mad Cat MKII,Special1,ClanLRM15,site_rmissileport,16,2,2
|
||||
Masakari,LeftTorso,ClanLRM10,site_lmissleport,24,2,2
|
||||
Masakari,LeftTorso,ClanLRM10,site_ltorsoport,24,2,2
|
||||
Mauler,LeftTorso,LRM5,site_lmissileport,24,2,2
|
||||
Mauler,LeftTorso,LRM5,site_lmissileport,24,2,2
|
||||
Mauler,LeftTorso,LRM5,site_lmissileport,24,2,2
|
||||
Mauler,RightTorso,LRM5,site_rmissileport,24,2,2
|
||||
Mauler,RightTorso,LRM5,site_rmissileport,24,2,2
|
||||
Mauler,RightTorso,LRM5,site_rmissileport,24,2,2
|
||||
Raven,RightTorso,LRM5,site_rtorsoport,24,2,2
|
||||
Sunder,LeftTorso,MediumLaser,site_ldtorsoport,,1,1
|
||||
Sunder,RightTorso,MediumLaser,site_rdtorsoport,,1,1
|
||||
Templar,LeftTorso,MediumPulseLaser,site_ldrtorsoport,,1,1
|
||||
Templar,RightTorso,MediumPulseLaser,site_rdrtorsoport,,1,1
|
||||
Thor,Special1,CLANLRM10,site_missileport,24,2,2
|
||||
Uziel,Special1,LRM10,site_missileport,24,2,2
|
||||
Vulture,LeftTorso,ClanLRM5,site_lmissileport,24,2,2
|
||||
Vulture,RightTorso,ClanLRM5,site_rmissileport,24,2,2
|
||||
Vulture,LeftTorso,ClanLRM10,site_lmissileport,24,2,2
|
||||
Vulture,RightTorso,ClanLRM10,site_rmissileport,24,2,2
|
||||
Wolfhound,CenterTorso,ClanERMediumLaser,site_reartorsoport,,1,1
|
||||
Zeus,RightTorso,MediumPulseLaser,site_reartorsoport,,1,1
|
||||
|
@@ -0,0 +1,45 @@
|
||||
Chassis,InternalLocation,Model,Site,AmmoCount,GroupIndex,WeaponFacing
|
||||
Ares,Special1,ClanERSmallLaser,site_lgunport,,1,
|
||||
Ares,Special1,ClanERSmallLaser,site_rgunport,,1,
|
||||
Ares,Special2,ClanLRM10,site_lmissileport,24,2,2
|
||||
Ares,Special2,ClanLRM10,site_missileport,24,2,2
|
||||
Ares,Special2,ClanLRM10,site_rmissileport,24,2,2
|
||||
AssassinII,Special1,LRM5,site_missileport,24,2,2
|
||||
Atlas,Special1,AC20,site_rtorsoport,10,1,
|
||||
Atlas,Special2,SRM6,site_llmissile,15,2,
|
||||
Avatar,Special1,MachineGun,site_ltorsoport,200,1,
|
||||
Avatar,Special1,MachineGun,site_rtorsoport,200,1,
|
||||
Battlemaster,Special2,PPC,site_rdgunport,,1,
|
||||
Battlemaster,Special1,SRM6,site_missile,15,2,
|
||||
BattlemasterIIC,Special1,ClanSSRM6,site_missile,15,2,
|
||||
Behemoth,Special1,LargeLaser,site_ctorsoport,,1,
|
||||
BehemothII,Special1,LargeLaser,site_ctorsoport,,1,
|
||||
Black Lanner,Special2,ClanSRM6,site_rmissileport,15,2,2
|
||||
Black Lanner,Special1,ClanLRM10,site_lmissileport,24,2,2
|
||||
Brigand,Special2,MediumLaser,site_ltorsoport,,1,
|
||||
Brigand,Special1,MediumLaser,site_rtorsoport,,1,
|
||||
Bushwacker,Special1,LRM5,site_missileport,24,2,2
|
||||
Bushwacker,Special1,LRM5,site_missileport,24,2,2
|
||||
Cauldron-Born,Special1,ClanLRM10,site_rmissileport,24,2,2
|
||||
Cauldron-Born,Special2,ClanLRM10,site_lmissileport,24,2,2
|
||||
Cyclops,Special1,MediumPulseLaser,site_gunport,,1,
|
||||
Deimos,Special1,ClanLRM15,site_lmissileport,16,2,2
|
||||
Deimos,Special2,ClanLRM15,site_rmissileport,16,2,2
|
||||
Hauptmann,Special1,ClanUltraAC20,site_rutorsoport,16,1,
|
||||
Hellspawn,Special1,SSRM2,site_rmissileport,50,2,
|
||||
HollanderII,Special2,SmallPulseLaser,site_cltorsoport,,1,
|
||||
HollanderII,Special2,SmallPulseLaser,site_crtorsoport,,1,
|
||||
HollanderII,Special1,GaussRifle,site_rtorsoport,16,1,
|
||||
Hunchback,Special1,AC10,site_rutorsoport,20,1,
|
||||
Loki,Special1,ClanSSRM6,site_missileport,15,2,
|
||||
Mad Cat,Special1,ClanLRM10,site_lmissileport,24,2,2
|
||||
Mad Cat,Special2,ClanLRM10,site_rmissileport,24,2,2
|
||||
Mad Cat MKII,Special2,ClanLRM15,site_lmissileport,16,2,2
|
||||
Mad Cat MKII,Special1,ClanLRM15,site_rmissileport,16,2,2
|
||||
Rifleman,Special1,MediumLaser,site_ltorsoport,,1,
|
||||
Rifleman,Special1,MediumLaser,site_rtorsoport,,1,
|
||||
Solitaire,Special1,ClanERLargeLaser,site_rtorsoport,,1,
|
||||
Thor,Special1,CLANLRM10,site_missileport,24,2,2
|
||||
Uziel,Special1,LRM10,site_missileport,24,2,2
|
||||
Vulture,Special1,ClanMachineGun,site_ltorsoport,200,1,
|
||||
Vulture,Special1,ClanMachineGun,site_rtorsoport,200,1,
|
||||
|
Reference in New Issue
Block a user