diff --git a/crates/sylpheed-formats/src/game_data.rs b/crates/sylpheed-formats/src/game_data.rs index 3cdc95c..8b5fb39 100644 --- a/crates/sylpheed-formats/src/game_data.rs +++ b/crates/sylpheed-formats/src/game_data.rs @@ -132,9 +132,27 @@ impl Weapon { } } -/// Load every weapon from a pak (e.g. `GP_MAIN_GAME_E.pak`). +/// Load every weapon from a pak. Catches all `Weapon`-shaped records, not just the +/// main [`schema::WEAPON`] — player special/missile weapons live in variant schemas +/// (e.g. `Weapon_DSaber_P_wep_*` in `GP_HANGAR_ARSENAL.pak`). Deduplicated by id. pub fn load_weapons(pak: &PakArchive) -> Vec { - load_table(pak, schema::WEAPON, Weapon::from_idxd) + let mut seen = std::collections::BTreeSet::new(); + let mut out = Vec::new(); + for e in pak.entries() { + let Ok(b) = pak.read(e) else { continue }; + let Ok(o) = IdxdObject::parse(&b) else { continue }; + // `Weapon`/`QWeapon`/… but not the `EnumWeapon` name lists. + let t0 = o.tokens().first().map(String::as_str).unwrap_or(""); + if !t0.ends_with("Weapon") || t0.contains("Enum") { + continue; + } + if let Some(w) = Weapon::from_idxd(&o) { + if w.id.as_deref().is_some_and(|id| seen.insert(id.to_string())) { + out.push(w); + } + } + } + out } // ── Craft / unit ────────────────────────────────────────────────────────────────