Implemented LUT codegen, untested.

This commit is contained in:
2022-10-24 15:49:07 +11:00
parent 018fe5a743
commit ab6eae3d1c
11 changed files with 2573 additions and 481 deletions

View File

@@ -38,14 +38,18 @@ enum class GroupType : int32_t {
}; };
enum class RecordType { enum class RecordType {
None, AACT, ACHR, ACTI, ADDN, ALCH, AMMO, ANIO, APPA, ARMA, ARMO, ARTO, ASPC,
AACT, ACHR, ACTI, ADDN, ALCH, AMMO, ANIO, APPA, ARMA, ARMO, ARTO, ASPC, ASTP, AVIF, BOOK, BPTD, CAMS, CELL, CLAS, CLDC, CLFM, ASTP, AVIF, BOOK, BPTD, CAMS, CELL, CLAS, CLDC, CLFM, CLMT, COBJ, COLL,
CLMT, COBJ, COLL, CONT, CPTH, CSTY, DEBR, DIAL, DLBR, DLVW, DOBJ, DOOR, DUAL, ECZN, EFSH, ENCH, EQUP, EXPL, EYES, FACT, FLOR, CONT, CPTH, CSTY, DEBR, DIAL, DLBR, DLVW, DOBJ, DOOR, DUAL, ECZN, EFSH,
FLST, FSTP, FSTS, FURN, GLOB, GMST, GRAS, GRUP, HAIR, HAZD, HDPT, IDLE, IDLM, IMAD, IMGS, INFO, INGR, IPCT, IPDS, KEYM, KYWD, ENCH, EQUP, EXPL, EYES, FACT, FLOR, FLST, FSTP, FSTS, FURN, GLOB, GMST,
LAND, LCRT, LCTN, LENS, LGTM, LIGH, LSCR, LTEX, LVLI, LVLN, LVSP, MATO, MATT, MESG, MGEF, MISC, MOVT, MSTT, MUSC, MUST, NAVI, GRAS, GRUP, HAIR, HAZD, HDPT, IDLE, IDLM, IMAD, IMGS, INFO, INGR, IPCT,
NAVM, NOTE, NPC_, OTFT, PACK, PARW, PBAR, PBEA, PCON, PERK, PFLA, PGRE, PHZD, PLYR, PMIS, PROJ, PWAT, QUST, RACE, REFR, REGN, IPDS, KEYM, KYWD, LAND, LCRT, LCTN, LENS, LGTM, LIGH, LSCR, LTEX, LVLI,
RELA, REVB, RFCT, RGDL, SCEN, SCOL, SCOL, SCPT, SCRL, SHOU, SLGM, SMBN, SMEN, SMQN, SNCT, SNDR, SOPM, SOUN, SPEL, SPGD, STAT, LVLN, LVSP, MATO, MATT, MESG, MGEF, MISC, MOVT, MSTT, MUSC, MUST, NAVI,
TACT, TES4, TREE, TXST, VOLI, VTYP, WATR, WEAP, WOOP, WRLD, WTHR NAVM, NOTE, NPC_, OTFT, PACK, PARW, PBAR, PBEA, PCON, PERK, PFLA, PGRE,
PHZD, PLYR, PMIS, PROJ, PWAT, QUST, RACE, REFR, REGN, RELA, REVB, RFCT,
RGDL, SCEN, SCOL, SCPT, SCRL, SHOU, SLGM, SMBN, SMEN, SMQN, SNCT, SNDR,
SOPM, SOUN, SPEL, SPGD, STAT, TACT, TES4, TREE, TXST, VOLI, VTYP, WATR,
WEAP, WOOP, WRLD, WTHR,
}; };
// //
@@ -58,9 +62,9 @@ using Node = std::variant<GroupNode, RecordNode>;
// Aggregate types // Aggregate types
// //
struct FourCC : utility::Store<std::array<char, 4>> { struct FourCC : utility::Store<uint32_t> {
constexpr FourCC() noexcept = default; constexpr FourCC() noexcept = default;
explicit constexpr FourCC(const char (&str)[5]) noexcept : Store{ utility::literal_to_array(str) } { } explicit constexpr FourCC(const char (&str)[5]) noexcept : Store{ utility::fourcc_lit_to_val(str) } { }
}; };
static_assert(std::is_trivial_v<FourCC>); static_assert(std::is_trivial_v<FourCC>);
@@ -68,6 +72,16 @@ struct FormID : utility::Store<uint32_t> { };
struct Timestamp : utility::Store<uint16_t> { }; struct Timestamp : utility::Store<uint16_t> { };
struct VCInfo : utility::Store<uint16_t> { }; struct VCInfo : utility::Store<uint16_t> { };
struct Flag {
RecordType type;
unsigned bit;
};
struct RefrFlag {
RecordType refr_type;
unsigned bit;
};
struct GroupHeader { struct GroupHeader {
struct Coord { struct Coord {
int16_t y, x; int16_t y, x;
@@ -138,5 +152,12 @@ private:
// Free functions // Free functions
// //
[[nodiscard]] constexpr std::optional<std::string_view> esxr_lut::group_type_to_name(GroupType group_type) noexcept;
[[nodiscard]] constexpr std::optional<FourCC> esxr_lut::record_type_to_fourcc(RecordType record_type) noexcept;
[[nodiscard]] constexpr std::optional<RecordType> esxr_lut::fourcc_to_record_type(FourCC fourcc) noexcept;
[[nodiscard]] constexpr std::optional<std::string_view> esxr_lut::record_type_to_name(RecordType record_type) noexcept;
[[nodiscard]] constexpr std::optional<std::string_view> esxr_lut::flag_to_description(Flag flag) noexcept;
[[nodiscard]] constexpr std::optional<std::string_view> esxr_lut::refr_flag_to_description(RefrFlag refr_flag) noexcept;
} }
#endif #endif

View File

@@ -4,7 +4,107 @@ using namespace esxr;
namespace esxr_lut { namespace esxr_lut {
static constexpr std::pair<RecordType, std::string_view> record_type_name_map[] = { static constexpr std::pair<GroupType, std::string_view> group_type_name_map_builtin[] {
{GroupType::Top , "Top Type" },
{GroupType::WorldChildren , "World Children" },
{GroupType::InteriorCellBlock , "Interior Cell Block" },
{GroupType::InteriorCellSubBlock , "Interior Cell Sub-Block" },
{GroupType::ExteriorCellBlock , "Exterior Cell" },
{GroupType::ExteriorCellSubBlock , "Exterior Cell Sub-Block" },
{GroupType::CellChildren , "Cell Children" },
{GroupType::TopicChildren , "Topic Children" },
{GroupType::CellPersistentChildren, "Cell Persistent Children"},
{GroupType::CellTemporaryChildren , "Cell Temporary Children" },
};
static constexpr auto group_type_name_map_std = utility::array_builtin_to_std(group_type_name_map_builtin);
static constexpr auto group_type_name_map = utility::map_to_soa(group_type_name_map_std);
[[nodiscard]] constexpr std::optional<std::string_view> group_type_to_name(GroupType group_type) noexcept
{
return utility::soa_first_to_second(group_type_name_map, group_type);
}
static constexpr std::pair<RecordType, FourCC> record_type_fourcc_map_builtin[] {
{RecordType::AACT, FourCC("AACT")}, {RecordType::ACHR, FourCC("ACHR")},
{RecordType::ACTI, FourCC("ACTI")}, {RecordType::ADDN, FourCC("ADDN")},
{RecordType::ALCH, FourCC("ALCH")}, {RecordType::AMMO, FourCC("AMMO")},
{RecordType::ANIO, FourCC("ANIO")}, {RecordType::APPA, FourCC("APPA")},
{RecordType::ARMA, FourCC("ARMA")}, {RecordType::ARMO, FourCC("ARMO")},
{RecordType::ARTO, FourCC("ARTO")}, {RecordType::ASPC, FourCC("ASPC")},
{RecordType::ASTP, FourCC("ASTP")}, {RecordType::AVIF, FourCC("AVIF")},
{RecordType::BOOK, FourCC("BOOK")}, {RecordType::BPTD, FourCC("BPTD")},
{RecordType::CAMS, FourCC("CAMS")}, {RecordType::CELL, FourCC("CELL")},
{RecordType::CLAS, FourCC("CLAS")}, {RecordType::CLDC, FourCC("CLDC")},
{RecordType::CLFM, FourCC("CLFM")}, {RecordType::CLMT, FourCC("CLMT")},
{RecordType::COBJ, FourCC("COBJ")}, {RecordType::COLL, FourCC("COLL")},
{RecordType::CONT, FourCC("CONT")}, {RecordType::CPTH, FourCC("CPTH")},
{RecordType::CSTY, FourCC("CSTY")}, {RecordType::DEBR, FourCC("DEBR")},
{RecordType::DIAL, FourCC("DIAL")}, {RecordType::DLBR, FourCC("DLBR")},
{RecordType::DLVW, FourCC("DLVW")}, {RecordType::DOBJ, FourCC("DOBJ")},
{RecordType::DOOR, FourCC("DOOR")}, {RecordType::DUAL, FourCC("DUAL")},
{RecordType::ECZN, FourCC("ECZN")}, {RecordType::EFSH, FourCC("EFSH")},
{RecordType::ENCH, FourCC("ENCH")}, {RecordType::EQUP, FourCC("EQUP")},
{RecordType::EXPL, FourCC("EXPL")}, {RecordType::EYES, FourCC("EYES")},
{RecordType::FACT, FourCC("FACT")}, {RecordType::FLOR, FourCC("FLOR")},
{RecordType::FLST, FourCC("FLST")}, {RecordType::FSTP, FourCC("FSTP")},
{RecordType::FSTS, FourCC("FSTS")}, {RecordType::FURN, FourCC("FURN")},
{RecordType::GLOB, FourCC("GLOB")}, {RecordType::GMST, FourCC("GMST")},
{RecordType::GRAS, FourCC("GRAS")}, {RecordType::GRUP, FourCC("GRUP")},
{RecordType::HAIR, FourCC("HAIR")}, {RecordType::HAZD, FourCC("HAZD")},
{RecordType::HDPT, FourCC("HDPT")}, {RecordType::IDLE, FourCC("IDLE")},
{RecordType::IDLM, FourCC("IDLM")}, {RecordType::IMAD, FourCC("IMAD")},
{RecordType::IMGS, FourCC("IMGS")}, {RecordType::INFO, FourCC("INFO")},
{RecordType::INGR, FourCC("INGR")}, {RecordType::IPCT, FourCC("IPCT")},
{RecordType::IPDS, FourCC("IPDS")}, {RecordType::KEYM, FourCC("KEYM")},
{RecordType::KYWD, FourCC("KYWD")}, {RecordType::LAND, FourCC("LAND")},
{RecordType::LCRT, FourCC("LCRT")}, {RecordType::LCTN, FourCC("LCTN")},
{RecordType::LENS, FourCC("LENS")}, {RecordType::LGTM, FourCC("LGTM")},
{RecordType::LIGH, FourCC("LIGH")}, {RecordType::LSCR, FourCC("LSCR")},
{RecordType::LTEX, FourCC("LTEX")}, {RecordType::LVLI, FourCC("LVLI")},
{RecordType::LVLN, FourCC("LVLN")}, {RecordType::LVSP, FourCC("LVSP")},
{RecordType::MATO, FourCC("MATO")}, {RecordType::MATT, FourCC("MATT")},
{RecordType::MESG, FourCC("MESG")}, {RecordType::MGEF, FourCC("MGEF")},
{RecordType::MISC, FourCC("MISC")}, {RecordType::MOVT, FourCC("MOVT")},
{RecordType::MSTT, FourCC("MSTT")}, {RecordType::MUSC, FourCC("MUSC")},
{RecordType::MUST, FourCC("MUST")}, {RecordType::NAVI, FourCC("NAVI")},
{RecordType::NAVM, FourCC("NAVM")}, {RecordType::NOTE, FourCC("NOTE")},
{RecordType::NPC_, FourCC("NPC_")}, {RecordType::OTFT, FourCC("OTFT")},
{RecordType::PACK, FourCC("PACK")}, {RecordType::PARW, FourCC("PARW")},
{RecordType::PBAR, FourCC("PBAR")}, {RecordType::PBEA, FourCC("PBEA")},
{RecordType::PCON, FourCC("PCON")}, {RecordType::PERK, FourCC("PERK")},
{RecordType::PFLA, FourCC("PFLA")}, {RecordType::PGRE, FourCC("PGRE")},
{RecordType::PHZD, FourCC("PHZD")}, {RecordType::PLYR, FourCC("PLYR")},
{RecordType::PMIS, FourCC("PMIS")}, {RecordType::PROJ, FourCC("PROJ")},
{RecordType::PWAT, FourCC("PWAT")}, {RecordType::QUST, FourCC("QUST")},
{RecordType::RACE, FourCC("RACE")}, {RecordType::REFR, FourCC("REFR")},
{RecordType::REGN, FourCC("REGN")}, {RecordType::RELA, FourCC("RELA")},
{RecordType::REVB, FourCC("REVB")}, {RecordType::RFCT, FourCC("RFCT")},
{RecordType::RGDL, FourCC("RGDL")}, {RecordType::SCEN, FourCC("SCEN")},
{RecordType::SCOL, FourCC("SCOL")}, {RecordType::SCPT, FourCC("SCPT")},
{RecordType::SCRL, FourCC("SCRL")}, {RecordType::SHOU, FourCC("SHOU")},
{RecordType::SLGM, FourCC("SLGM")}, {RecordType::SMBN, FourCC("SMBN")},
{RecordType::SMEN, FourCC("SMEN")}, {RecordType::SMQN, FourCC("SMQN")},
{RecordType::SNCT, FourCC("SNCT")}, {RecordType::SNDR, FourCC("SNDR")},
{RecordType::SOPM, FourCC("SOPM")}, {RecordType::SOUN, FourCC("SOUN")},
{RecordType::SPEL, FourCC("SPEL")}, {RecordType::SPGD, FourCC("SPGD")},
{RecordType::STAT, FourCC("STAT")}, {RecordType::TACT, FourCC("TACT")},
{RecordType::TES4, FourCC("TES4")}, {RecordType::TREE, FourCC("TREE")},
{RecordType::TXST, FourCC("TXST")}, {RecordType::VOLI, FourCC("VOLI")},
{RecordType::VTYP, FourCC("VTYP")}, {RecordType::WATR, FourCC("WATR")},
{RecordType::WEAP, FourCC("WEAP")}, {RecordType::WOOP, FourCC("WOOP")},
{RecordType::WRLD, FourCC("WRLD")}, {RecordType::WTHR, FourCC("WTHR")},
};
static constexpr auto record_type_fourcc_map_std = utility::array_builtin_to_std(record_type_fourcc_map_builtin);
static constexpr auto record_type_fourcc_map = utility::map_to_soa(record_type_fourcc_map_std);
[[nodiscard]] constexpr std::optional<FourCC> record_type_to_fourcc(RecordType record_type) noexcept
{
return utility::soa_first_to_second(record_type_fourcc_map, record_type);
}
[[nodiscard]] constexpr std::optional<RecordType> fourcc_to_record_type(FourCC fourcc) noexcept
{
return utility::soa_second_to_first(record_type_fourcc_map, fourcc);
}
static constexpr std::pair<RecordType, std::string_view> record_type_name_map_builtin[] {
{RecordType::AACT, "Action" }, {RecordType::AACT, "Action" },
{RecordType::ACHR, "Placed NPC" }, {RecordType::ACHR, "Placed NPC" },
{RecordType::ACTI, "Activator" }, {RecordType::ACTI, "Activator" },
@@ -54,7 +154,7 @@ static constexpr std::pair<RecordType, std::string_view> record_type_name_map[]
{RecordType::GLOB, "Global" }, {RecordType::GLOB, "Global" },
{RecordType::GMST, "Game Setting" }, {RecordType::GMST, "Game Setting" },
{RecordType::GRAS, "Grass" }, {RecordType::GRAS, "Grass" },
{RecordType::GRUP, "Internal File Structure Group"}, {RecordType::GRUP, "Group" },
{RecordType::HAIR, "HAIR" }, {RecordType::HAIR, "HAIR" },
{RecordType::HAZD, "Hazard" }, {RecordType::HAZD, "Hazard" },
{RecordType::HDPT, "Head Part" }, {RecordType::HDPT, "Head Part" },
@@ -90,7 +190,7 @@ static constexpr std::pair<RecordType, std::string_view> record_type_name_map[]
{RecordType::MUST, "Music Track" }, {RecordType::MUST, "Music Track" },
{RecordType::NAVI, "Navigation Mesh Info Map" }, {RecordType::NAVI, "Navigation Mesh Info Map" },
{RecordType::NAVM, "Navigation Mesh" }, {RecordType::NAVM, "Navigation Mesh" },
{RecordType::NOTE, "NOTE"}, {RecordType::NOTE, "Note" },
{RecordType::NPC_, "Non-Player Character (Actor)"}, {RecordType::NPC_, "Non-Player Character (Actor)"},
{RecordType::OTFT, "Outfit" }, {RecordType::OTFT, "Outfit" },
{RecordType::PACK, "Package" }, {RecordType::PACK, "Package" },
@@ -115,7 +215,6 @@ static constexpr std::pair<RecordType, std::string_view> record_type_name_map[]
{RecordType::RFCT, "Visual Effect" }, {RecordType::RFCT, "Visual Effect" },
{RecordType::RGDL, "RGDL" }, {RecordType::RGDL, "RGDL" },
{RecordType::SCEN, "Scene" }, {RecordType::SCEN, "Scene" },
{RecordType::SCOL, "SCOL"},
{RecordType::SCOL, "Static Collection" }, {RecordType::SCOL, "Static Collection" },
{RecordType::SCPT, "SCPT" }, {RecordType::SCPT, "SCPT" },
{RecordType::SCRL, "Scroll" }, {RecordType::SCRL, "Scroll" },
@@ -141,178 +240,375 @@ static constexpr std::pair<RecordType, std::string_view> record_type_name_map[]
{RecordType::WEAP, "Weapon" }, {RecordType::WEAP, "Weapon" },
{RecordType::WOOP, "Word of Power" }, {RecordType::WOOP, "Word of Power" },
{RecordType::WRLD, "Worldspace" }, {RecordType::WRLD, "Worldspace" },
{RecordType::WTHR, "Weather"} {RecordType::WTHR, "Weather" },
}; };
static constexpr auto record_type_name_map_std = utility::array_builtin_to_std(record_type_name_map_builtin);
static constexpr auto record_type_name_map = utility::map_to_soa(record_type_name_map_std);
[[nodiscard]] constexpr std::optional<std::string_view> record_type_to_name(RecordType record_type) noexcept
{
return utility::soa_first_to_second(record_type_name_map, record_type);
}
static constexpr std::pair<RecordType, FourCC> record_type_fourcc_map[] = { static constexpr std::pair<Flag, std::string_view> flag_description_map_builtin[] {
{RecordType::AACT, FourCC("AACT")},
{RecordType::ACHR, FourCC("ACHR")},
{RecordType::ACTI, FourCC("ACTI")},
{RecordType::ADDN, FourCC("ADDN")},
{RecordType::ALCH, FourCC("ALCH")},
{RecordType::AMMO, FourCC("AMMO")},
{RecordType::ANIO, FourCC("ANIO")},
{RecordType::APPA, FourCC("APPA")},
{RecordType::ARMA, FourCC("ARMA")},
{RecordType::ARMO, FourCC("ARMO")},
{RecordType::ARTO, FourCC("ARTO")},
{RecordType::ASPC, FourCC("ASPC")},
{RecordType::ASTP, FourCC("ASTP")},
{RecordType::AVIF, FourCC("AVIF")},
{RecordType::BOOK, FourCC("BOOK")},
{RecordType::BPTD, FourCC("BPTD")},
{RecordType::CAMS, FourCC("CAMS")},
{RecordType::CELL, FourCC("CELL")},
{RecordType::CLAS, FourCC("CLAS")},
{RecordType::CLDC, FourCC("CLDC")},
{RecordType::CLFM, FourCC("CLFM")},
{RecordType::CLMT, FourCC("CLMT")},
{RecordType::COBJ, FourCC("COBJ")},
{RecordType::COLL, FourCC("COLL")},
{RecordType::CONT, FourCC("CONT")},
{RecordType::CPTH, FourCC("CPTH")},
{RecordType::CSTY, FourCC("CSTY")},
{RecordType::DEBR, FourCC("DEBR")},
{RecordType::DIAL, FourCC("DIAL")},
{RecordType::DLBR, FourCC("DLBR")},
{RecordType::DLVW, FourCC("DLVW")},
{RecordType::DOBJ, FourCC("DOBJ")},
{RecordType::DOOR, FourCC("DOOR")},
{RecordType::DUAL, FourCC("DUAL")},
{RecordType::ECZN, FourCC("ECZN")},
{RecordType::EFSH, FourCC("EFSH")},
{RecordType::ENCH, FourCC("ENCH")},
{RecordType::EQUP, FourCC("EQUP")},
{RecordType::EXPL, FourCC("EXPL")},
{RecordType::EYES, FourCC("EYES")},
{RecordType::FACT, FourCC("FACT")},
{RecordType::FLOR, FourCC("FLOR")},
{RecordType::FLST, FourCC("FLST")},
{RecordType::FSTP, FourCC("FSTP")},
{RecordType::FSTS, FourCC("FSTS")},
{RecordType::FURN, FourCC("FURN")},
{RecordType::GLOB, FourCC("GLOB")},
{RecordType::GMST, FourCC("GMST")},
{RecordType::GRAS, FourCC("GRAS")},
{RecordType::GRUP, FourCC("GRUP")},
{RecordType::HAIR, FourCC("HAIR")},
{RecordType::HAZD, FourCC("HAZD")},
{RecordType::HDPT, FourCC("HDPT")},
{RecordType::IDLE, FourCC("IDLE")},
{RecordType::IDLM, FourCC("IDLM")},
{RecordType::IMAD, FourCC("IMAD")},
{RecordType::IMGS, FourCC("IMGS")},
{RecordType::INFO, FourCC("INFO")},
{RecordType::INGR, FourCC("INGR")},
{RecordType::IPCT, FourCC("IPCT")},
{RecordType::IPDS, FourCC("IPDS")},
{RecordType::KEYM, FourCC("KEYM")},
{RecordType::KYWD, FourCC("KYWD")},
{RecordType::LAND, FourCC("LAND")},
{RecordType::LCRT, FourCC("LCRT")},
{RecordType::LCTN, FourCC("LCTN")},
{RecordType::LENS, FourCC("LENS")},
{RecordType::LGTM, FourCC("LGTM")},
{RecordType::LIGH, FourCC("LIGH")},
{RecordType::LSCR, FourCC("LSCR")},
{RecordType::LTEX, FourCC("LTEX")},
{RecordType::LVLI, FourCC("LVLI")},
{RecordType::LVLN, FourCC("LVLN")},
{RecordType::LVSP, FourCC("LVSP")},
{RecordType::MATO, FourCC("MATO")},
{RecordType::MATT, FourCC("MATT")},
{RecordType::MESG, FourCC("MESG")},
{RecordType::MGEF, FourCC("MGEF")},
{RecordType::MISC, FourCC("MISC")},
{RecordType::MOVT, FourCC("MOVT")},
{RecordType::MSTT, FourCC("MSTT")},
{RecordType::MUSC, FourCC("MUSC")},
{RecordType::MUST, FourCC("MUST")},
{RecordType::NAVI, FourCC("NAVI")},
{RecordType::NAVM, FourCC("NAVM")},
{RecordType::NOTE, FourCC("NOTE")},
{RecordType::NPC_, FourCC("NPC_")},
{RecordType::OTFT, FourCC("OTFT")},
{RecordType::PACK, FourCC("PACK")},
{RecordType::PARW, FourCC("PARW")},
{RecordType::PBAR, FourCC("PBAR")},
{RecordType::PBEA, FourCC("PBEA")},
{RecordType::PCON, FourCC("PCON")},
{RecordType::PERK, FourCC("PERK")},
{RecordType::PFLA, FourCC("PFLA")},
{RecordType::PGRE, FourCC("PGRE")},
{RecordType::PHZD, FourCC("PHZD")},
{RecordType::PLYR, FourCC("PLYR")},
{RecordType::PMIS, FourCC("PMIS")},
{RecordType::PROJ, FourCC("PROJ")},
{RecordType::PWAT, FourCC("PWAT")},
{RecordType::QUST, FourCC("QUST")},
{RecordType::RACE, FourCC("RACE")},
{RecordType::REFR, FourCC("REFR")},
{RecordType::REGN, FourCC("REGN")},
{RecordType::RELA, FourCC("RELA")},
{RecordType::REVB, FourCC("REVB")},
{RecordType::RFCT, FourCC("RFCT")},
{RecordType::RGDL, FourCC("RGDL")},
{RecordType::SCEN, FourCC("SCEN")},
{RecordType::SCOL, FourCC("SCOL")},
{RecordType::SCOL, FourCC("SCOL")},
{RecordType::SCPT, FourCC("SCPT")},
{RecordType::SCRL, FourCC("SCRL")},
{RecordType::SHOU, FourCC("SHOU")},
{RecordType::SLGM, FourCC("SLGM")},
{RecordType::SMBN, FourCC("SMBN")},
{RecordType::SMEN, FourCC("SMEN")},
{RecordType::SMQN, FourCC("SMQN")},
{RecordType::SNCT, FourCC("SNCT")},
{RecordType::SNDR, FourCC("SNDR")},
{RecordType::SOPM, FourCC("SOPM")},
{RecordType::SOUN, FourCC("SOUN")},
{RecordType::SPEL, FourCC("SPEL")},
{RecordType::SPGD, FourCC("SPGD")},
{RecordType::STAT, FourCC("STAT")},
{RecordType::TACT, FourCC("TACT")},
{RecordType::TES4, FourCC("TES4")},
{RecordType::TREE, FourCC("TREE")},
{RecordType::TXST, FourCC("TXST")},
{RecordType::VOLI, FourCC("VOLI")},
{RecordType::VTYP, FourCC("VTYP")},
{RecordType::WATR, FourCC("WATR")},
{RecordType::WEAP, FourCC("WEAP")},
{RecordType::WOOP, FourCC("WOOP")},
{RecordType::WRLD, FourCC("WRLD")},
{RecordType::WTHR, FourCC("WTHR")},
};
static constexpr std::pair<GroupType, std::string_view> group_type_names_map[] = {
{GroupType::Top , "Top Type" },
{GroupType::WorldChildren , "World Children" },
{GroupType::InteriorCellBlock , "Interior Cell Block" },
{GroupType::InteriorCellSubBlock , "Interior Cell Sub-Block" },
{GroupType::ExteriorCellBlock , "Exterior Cell" },
{GroupType::ExteriorCellSubBlock , "Exterior Cell Sub-Block" },
{GroupType::CellChildren , "Cell Children" },
{GroupType::TopicChildren , "Topic Children" },
{GroupType::CellPersistentChildren, "Cell Persistent Children"},
{GroupType::CellTemporaryChildren , "Cell Temporary Children" },
};
struct flag {
RecordType type;
unsigned bit;
};
static constexpr std::pair<flag, std::string_view> flag_strings_map[]{
{{RecordType::ACHR, 9}, "Starts Dead" }, {{RecordType::ACHR, 9}, "Starts Dead" },
{{RecordType::ACHR, 10}, "Persistent" },
{{RecordType::ACHR, 11}, "Initially Disabled" },
{{RecordType::ACHR, 25}, "No AI Acquire" },
{{RecordType::ACHR, 29}, "Don't Havok Settle" },
{{RecordType::ACTI, 6}, "Has Tree LOD" },
{{RecordType::ACTI, 8}, "Must Update Anims" },
{{RecordType::ACTI, 9}, "Hidden From Local Map" },
{{RecordType::ACTI, 15}, "Has Distant LOD" },
{{RecordType::ACTI, 16}, "Random Anim Start" },
{{RecordType::ACTI, 17}, "Dangerous" },
{{RecordType::ACTI, 20}, "Ignore Object Interaction" },
{{RecordType::ACTI, 23}, "Is Marker" },
{{RecordType::ACTI, 25}, "Obstacle" },
{{RecordType::ACTI, 26}, "NavMesh Generation - Filter" },
{{RecordType::ACTI, 27}, "NavMesh Generation - Bounding Box"},
{{RecordType::ACTI, 29}, "Child Can Use" },
{{RecordType::ACTI, 30}, "NavMesh Generation - Ground" },
{{RecordType::ALCH, 29}, "Medicine" },
{{RecordType::AMMO, 2}, "Non-Playable" },
{{RecordType::ANIO, 9}, "Unknown 9" },
{{RecordType::ARMO, 2}, "Non-Playable" },
{{RecordType::ARMO, 6}, "Shield" },
{{RecordType::ARMO, 10}, "Unknown 10" },
{{RecordType::ARMO, 15}, "Unknown 15" },
{{RecordType::CELL, 10}, "Persistent" },
{{RecordType::CELL, 17}, "Off Limits" },
{{RecordType::CELL, 18}, "Compressed" },
{{RecordType::CELL, 19}, "Can't Wait" },
{{RecordType::CLFM, 2}, "Non-Playable" },
{{RecordType::CONT, 15}, "Has Distant LOD" },
{{RecordType::CONT, 16}, "Random Anim Start" },
{{RecordType::CONT, 25}, "Obstacle" },
{{RecordType::CONT, 26}, "NavMesh Generation - Filter" },
{{RecordType::CONT, 27}, "NavMesh Generation - Bounding Box"},
{{RecordType::CONT, 30}, "NavMesh Generation - Ground" },
{{RecordType::CSTY, 19}, "Allow Dual Wielding" },
{{RecordType::DOOR, 15}, "Has Distant LOD" },
{{RecordType::DOOR, 16}, "Random Anim Start" },
{{RecordType::DOOR, 23}, "Is Marker" },
{{RecordType::EYES, 2}, "Non-Playable" },
{{RecordType::FURN, 7}, "Is Perch" },
{{RecordType::FURN, 15}, "Has Distant LOD" },
{{RecordType::FURN, 16}, "Random Anim Start" },
{{RecordType::FURN, 23}, "Is Marker" },
{{RecordType::FURN, 28}, "Must Exit To Talk" },
{{RecordType::FURN, 29}, "Child Can Use" },
{{RecordType::GLOB, 6}, "Constant" },
{{RecordType::HDPT, 2}, "Non-Playable" },
{{RecordType::IDLM, 29}, "Child Can Use" },
{{RecordType::INFO, 13}, "Actor Changed" },
{{RecordType::KEYM, 2}, "Non-Playable" },
{{RecordType::LAND, 18}, "Compressed" },
{{RecordType::LIGH, 16}, "Random Anim Start" },
{{RecordType::LIGH, 17}, "Portal-strict" },
{{RecordType::LIGH, 25}, "Obstacle" },
{{RecordType::LSCR, 10}, "Displays In Main Menu" },
{{RecordType::MISC, 2}, "Non-Playable" },
{{RecordType::MSTT, 8}, "Must Update Anims" },
{{RecordType::MSTT, 9}, "Hidden From Local Map" },
{{RecordType::MSTT, 15}, "Has Distant LOD" },
{{RecordType::MSTT, 16}, "Random Anim Start" },
{{RecordType::MSTT, 19}, "Has Currents" },
{{RecordType::MSTT, 25}, "Obstacle" },
{{RecordType::MSTT, 26}, "NavMesh Generation - Filter" },
{{RecordType::MSTT, 27}, "NavMesh Generation - Bounding Box"},
{{RecordType::MSTT, 30}, "NavMesh Generation - Ground" },
{{RecordType::NAVM, 18}, "Compressed" },
{{RecordType::NAVM, 26}, "AutoGen" },
{{RecordType::NAVM, 31}, "NavmeshGenCell" },
{{RecordType::NPC_, 10}, "Unknown 10" },
{{RecordType::NPC_, 18}, "Compressed" },
{{RecordType::NPC_, 19}, "Unknown 19" },
{{RecordType::NPC_, 29}, "Bleedout Override" },
{{RecordType::PARW, 7}, "Turn Off Fire" },
{{RecordType::PARW, 10}, "Persistent" },
{{RecordType::PARW, 11}, "Initially Disabled" },
{{RecordType::PARW, 28}, "Reflected By Auto Water" },
{{RecordType::PARW, 29}, "Don't Havok Settle" },
{{RecordType::PARW, 30}, "No Respawn" },
{{RecordType::PBAR, 7}, "Turn Off Fire" },
{{RecordType::PBAR, 10}, "Persistent" },
{{RecordType::PBAR, 11}, "Initially Disabled" },
{{RecordType::PBAR, 28}, "Reflected By Auto Water" },
{{RecordType::PBAR, 29}, "Don't Havok Settle" },
{{RecordType::PBAR, 30}, "No Respawn" },
{{RecordType::PBEA, 7}, "Turn Off Fire" },
{{RecordType::PBEA, 10}, "Persistent" },
{{RecordType::PBEA, 11}, "Initially Disabled" },
{{RecordType::PBEA, 28}, "Reflected By Auto Water" },
{{RecordType::PBEA, 29}, "Don't Havok Settle" },
{{RecordType::PBEA, 30}, "No Respawn" },
{{RecordType::PCON, 7}, "Turn Off Fire" },
{{RecordType::PCON, 10}, "Persistent" },
{{RecordType::PCON, 11}, "Initially Disabled" },
{{RecordType::PCON, 28}, "Reflected By Auto Water" },
{{RecordType::PCON, 29}, "Don't Havok Settle" },
{{RecordType::PCON, 30}, "No Respawn" },
{{RecordType::PERK, 2}, "Non-Playable" },
{{RecordType::PFLA, 7}, "Turn Off Fire" },
{{RecordType::PFLA, 10}, "Persistent" },
{{RecordType::PFLA, 11}, "Initially Disabled" },
{{RecordType::PFLA, 28}, "Reflected By Auto Water" },
{{RecordType::PFLA, 29}, "Don't Havok Settle" },
{{RecordType::PFLA, 30}, "No Respawn" },
{{RecordType::PGRE, 7}, "Turn Off Fire" },
{{RecordType::PGRE, 10}, "Persistent" },
{{RecordType::PGRE, 11}, "Initially Disabled" },
{{RecordType::PGRE, 28}, "Reflected By Auto Water" },
{{RecordType::PGRE, 29}, "Don't Havok Settle" },
{{RecordType::PGRE, 30}, "No Respawn" },
{{RecordType::PHZD, 7}, "Turn Off Fire" },
{{RecordType::PHZD, 10}, "Persistent" },
{{RecordType::PHZD, 11}, "Initially Disabled" },
{{RecordType::PHZD, 28}, "Reflected By Auto Water" },
{{RecordType::PHZD, 29}, "Don't Havok Settle" },
{{RecordType::PHZD, 30}, "No Respawn" },
{{RecordType::PMIS, 7}, "Turn Off Fire" },
{{RecordType::PMIS, 10}, "Persistent" },
{{RecordType::PMIS, 11}, "Initially Disabled" },
{{RecordType::PMIS, 28}, "Reflected By Auto Water" },
{{RecordType::PMIS, 29}, "Don't Havok Settle" },
{{RecordType::PMIS, 30}, "No Respawn" },
{{RecordType::RACE, 19}, "Critter?" },
{{RecordType::REFR, 10}, "Persistent" },
{{RecordType::REFR, 11}, "Initially Disabled" },
{{RecordType::REFR, 16}, "Is Full LOD" },
{{RecordType::REFR, 26}, "Filter (Collision Geometry)" },
{{RecordType::REFR, 27}, "Bounding Box (Collision Geometry)"},
{{RecordType::REFR, 28}, "Reflected By Auto Water" },
{{RecordType::REFR, 30}, "Ground" },
{{RecordType::REFR, 31}, "Multibound" },
{{RecordType::REGN, 6}, "Border Region" },
{{RecordType::RELA, 6}, "Secret" },
{{RecordType::SHOU, 7}, "Treat spells as powers" },
{{RecordType::SLGM, 17}, "Can Hold NPC Soul" },
{{RecordType::STAT, 2}, "Never Fades" },
{{RecordType::STAT, 5}, "Deleted" },
{{RecordType::STAT, 6}, "Has Tree LOD" },
{{RecordType::STAT, 7}, "Add-On LOD Object" },
{{RecordType::STAT, 9}, "Hidden From Local Map" },
{{RecordType::STAT, 11}, "Unknown 11" },
{{RecordType::STAT, 15}, "Has Distant LOD" },
{{RecordType::STAT, 16}, "Unknown 16" },
{{RecordType::STAT, 17}, "Uses HD LOD Texture" },
{{RecordType::STAT, 19}, "Has Currents" },
{{RecordType::STAT, 23}, "Is Marker" },
{{RecordType::STAT, 25}, "Obstacle" },
{{RecordType::STAT, 26}, "NavMesh Generation - Filter" },
{{RecordType::STAT, 27}, "NavMesh Generation - Bounding Box"},
{{RecordType::STAT, 28}, "Show In World Map" },
{{RecordType::STAT, 30}, "NavMesh Generation - Ground" },
{{RecordType::TACT, 9}, "Hidden From Local Map" },
{{RecordType::TACT, 16}, "Random Anim Start" },
{{RecordType::TACT, 17}, "Radio Station" },
{{RecordType::TES4, 0}, "ESM" },
{{RecordType::TES4, 1}, "Altered" },
{{RecordType::TES4, 2}, "Checked" },
{{RecordType::TES4, 3}, "Active" },
{{RecordType::TES4, 4}, "Optimized File" },
{{RecordType::TES4, 5}, "Temp ID Owner" },
{{RecordType::TES4, 7}, "Localized" },
{{RecordType::TES4, 8}, "Precalc Data Only" },
{{RecordType::TES4, 9}, "ESL" },
{{RecordType::TREE, 15}, "Has Distant LOD" },
{{RecordType::WEAP, 2}, "Non-Playable" },
{{RecordType::WRLD, 19}, "Can't Wait" },
}; };
static constexpr auto flag_description_map_std = utility::array_builtin_to_std(flag_description_map_builtin);
static constexpr auto flag_description_map = utility::map_to_soa(flag_description_map_std);
[[nodiscard]] constexpr std::optional<std::string_view> flag_to_description(Flag flag) noexcept
{
return utility::soa_first_to_second(flag_description_map, flag);
}
struct refr_flag { static constexpr std::pair<RefrFlag, std::string_view> refr_flag_description_map_builtin[] {
RecordType refr_type; {{RecordType::ACTI, 9}, "Hidden From Local Map" },
unsigned bit; {{RecordType::ACTI, 10}, "Persistent" },
}; {{RecordType::ACTI, 11}, "Initially Disabled" },
{{RecordType::ACTI, 13}, "Sky Marker" },
static constexpr std::pair<flag, std::string_view> refr_flag_strings_map[]{ {{RecordType::ACTI, 15}, "Visible when distant" },
{{RecordType::ACHR, 9}, "Hidden From Local Map"}, {{RecordType::ACTI, 16}, "Is Full LOD" },
{{RecordType::ACTI, 26}, "Filter (Collision Geometry)" },
{{RecordType::ACTI, 27}, "Bounding Box (Collision Geometry)"},
{{RecordType::ACTI, 28}, "Reflected By Auto Water" },
{{RecordType::ACTI, 29}, "Don''t Havok Settle" },
{{RecordType::ACTI, 30}, "No Respawn" },
{{RecordType::ACTI, 31}, "Multibound" },
{{RecordType::ADDN, 10}, "Persistent" },
{{RecordType::ADDN, 11}, "Initially Disabled" },
{{RecordType::ADDN, 16}, "Is Full LOD" },
{{RecordType::ADDN, 28}, "Reflected By Auto Water" },
{{RecordType::ADDN, 29}, "Don''t Havok Settle" },
{{RecordType::ADDN, 30}, "No Respawn" },
{{RecordType::ADDN, 31}, "Multibound" },
{{RecordType::ALCH, 10}, "Persistent" },
{{RecordType::ALCH, 11}, "Initially Disabled" },
{{RecordType::ALCH, 16}, "Is Full LOD" },
{{RecordType::ALCH, 25}, "No AI Acquire" },
{{RecordType::ALCH, 28}, "Reflected By Auto Water" },
{{RecordType::ALCH, 29}, "Don''t Havok Settle" },
{{RecordType::ALCH, 30}, "No Respawn" },
{{RecordType::ALCH, 31}, "Multibound" },
{{RecordType::AMMO, 10}, "Persistent" },
{{RecordType::AMMO, 11}, "Initially Disabled" },
{{RecordType::AMMO, 16}, "Is Full LOD" },
{{RecordType::AMMO, 25}, "No AI Acquire" },
{{RecordType::AMMO, 28}, "Reflected By Auto Water" },
{{RecordType::AMMO, 29}, "Don''t Havok Settle" },
{{RecordType::AMMO, 30}, "No Respawn" },
{{RecordType::AMMO, 31}, "Multibound" },
{{RecordType::ARMO, 10}, "Persistent" },
{{RecordType::ARMO, 11}, "Initially Disabled" },
{{RecordType::ARMO, 16}, "Is Full LOD" },
{{RecordType::ARMO, 25}, "No AI Acquire" },
{{RecordType::ARMO, 28}, "Reflected By Auto Water" },
{{RecordType::ARMO, 29}, "Don''t Havok Settle" },
{{RecordType::ARMO, 30}, "No Respawn" },
{{RecordType::ARMO, 31}, "Multibound" },
{{RecordType::BOOK, 10}, "Persistent" },
{{RecordType::BOOK, 11}, "Initially Disabled" },
{{RecordType::BOOK, 16}, "Is Full LOD" },
{{RecordType::BOOK, 25}, "No AI Acquire" },
{{RecordType::BOOK, 28}, "Reflected By Auto Water" },
{{RecordType::BOOK, 29}, "Don''t Havok Settle" },
{{RecordType::BOOK, 30}, "No Respawn" },
{{RecordType::BOOK, 31}, "Multibound" },
{{RecordType::CONT, 10}, "Persistent" },
{{RecordType::CONT, 11}, "Initially Disabled" },
{{RecordType::CONT, 16}, "Is Full LOD" },
{{RecordType::CONT, 25}, "No AI Acquire" },
{{RecordType::CONT, 26}, "Filter (Collision Geometry)" },
{{RecordType::CONT, 27}, "Bounding Box (Collision Geometry)"},
{{RecordType::CONT, 28}, "Reflected By Auto Water" },
{{RecordType::CONT, 29}, "Don''t Havok Settle" },
{{RecordType::CONT, 30}, "Ground" },
{{RecordType::CONT, 31}, "Multibound" },
{{RecordType::DOOR, 6}, "Hidden From Local Map" },
{{RecordType::DOOR, 8}, "Inaccessible" },
{{RecordType::DOOR, 10}, "Persistent" },
{{RecordType::DOOR, 11}, "Initially Disabled" },
{{RecordType::DOOR, 16}, "Is Full LOD" },
{{RecordType::DOOR, 26}, "Filter (Collision Geometry)" },
{{RecordType::DOOR, 27}, "Bounding Box (Collision Geometry)"},
{{RecordType::DOOR, 28}, "Reflected By Auto Water" },
{{RecordType::DOOR, 29}, "Don''t Havok Settle" },
{{RecordType::DOOR, 30}, "No Respawn" },
{{RecordType::DOOR, 31}, "Multibound" },
{{RecordType::FLOR, 9}, "Hidden From Local Map" },
{{RecordType::FLOR, 10}, "Persistent" },
{{RecordType::FLOR, 11}, "Initially Disabled" },
{{RecordType::FLOR, 13}, "Sky Marker" },
{{RecordType::FLOR, 15}, "Visible when distant" },
{{RecordType::FLOR, 16}, "Is Full LOD" },
{{RecordType::FLOR, 26}, "Filter (Collision Geometry)" },
{{RecordType::FLOR, 27}, "Bounding Box (Collision Geometry)"},
{{RecordType::FLOR, 28}, "Reflected By Auto Water" },
{{RecordType::FLOR, 29}, "Don''t Havok Settle" },
{{RecordType::FLOR, 30}, "No Respawn" },
{{RecordType::FLOR, 31}, "Multibound" },
{{RecordType::INGR, 10}, "Persistent" },
{{RecordType::INGR, 11}, "Initially Disabled" },
{{RecordType::INGR, 16}, "Is Full LOD" },
{{RecordType::INGR, 25}, "No AI Acquire" },
{{RecordType::INGR, 28}, "Reflected By Auto Water" },
{{RecordType::INGR, 29}, "Don''t Havok Settle" },
{{RecordType::INGR, 30}, "No Respawn" },
{{RecordType::INGR, 31}, "Multibound" },
{{RecordType::KEYM, 10}, "Persistent" },
{{RecordType::KEYM, 11}, "Initially Disabled" },
{{RecordType::KEYM, 16}, "Is Full LOD" },
{{RecordType::KEYM, 25}, "No AI Acquire" },
{{RecordType::KEYM, 28}, "Reflected By Auto Water" },
{{RecordType::KEYM, 29}, "Don''t Havok Settle" },
{{RecordType::KEYM, 30}, "No Respawn" },
{{RecordType::KEYM, 31}, "Multibound" },
{{RecordType::LIGH, 8}, "Doesn''t Light Water" },
{{RecordType::LIGH, 9}, "Casts Shadows" },
{{RecordType::LIGH, 10}, "Persistent" },
{{RecordType::LIGH, 11}, "Initially Disabled" },
{{RecordType::LIGH, 16}, "Never Fades" },
{{RecordType::LIGH, 17}, "Doesn''t Light Landscape" },
{{RecordType::LIGH, 25}, "No AI Acquire" },
{{RecordType::LIGH, 28}, "Reflected By Auto Water" },
{{RecordType::LIGH, 29}, "Don''t Havok Settle" },
{{RecordType::LIGH, 30}, "No Respawn" },
{{RecordType::LIGH, 31}, "Multibound" },
{{RecordType::MISC, 10}, "Persistent" },
{{RecordType::MISC, 11}, "Initially Disabled" },
{{RecordType::MISC, 16}, "Is Full LOD" },
{{RecordType::MISC, 25}, "No AI Acquire" },
{{RecordType::MISC, 28}, "Reflected By Auto Water" },
{{RecordType::MISC, 29}, "Don''t Havok Settle" },
{{RecordType::MISC, 30}, "No Respawn" },
{{RecordType::MISC, 31}, "Multibound" },
{{RecordType::MSTT, 9}, "Motion Blur" },
{{RecordType::MSTT, 10}, "Persistent" },
{{RecordType::MSTT, 11}, "Initially Disabled" },
{{RecordType::MSTT, 16}, "Is Full LOD" },
{{RecordType::MSTT, 26}, "Filter (Collision Geometry)" },
{{RecordType::MSTT, 27}, "Bounding Box (Collision Geometry)"},
{{RecordType::MSTT, 28}, "Reflected By Auto Water" },
{{RecordType::MSTT, 29}, "Don''t Havok Settle" },
{{RecordType::MSTT, 30}, "No Respawn" },
{{RecordType::MSTT, 31}, "Multibound" },
{{RecordType::SCRL, 10}, "Persistent" },
{{RecordType::SCRL, 11}, "Initially Disabled" },
{{RecordType::SCRL, 16}, "Is Full LOD" },
{{RecordType::SCRL, 25}, "No AI Acquire" },
{{RecordType::SCRL, 28}, "Reflected By Auto Water" },
{{RecordType::SCRL, 29}, "Don''t Havok Settle" },
{{RecordType::SCRL, 30}, "No Respawn" },
{{RecordType::SCRL, 31}, "Multibound" },
{{RecordType::SLGM, 10}, "Persistent" },
{{RecordType::SLGM, 11}, "Initially Disabled" },
{{RecordType::SLGM, 16}, "Is Full LOD" },
{{RecordType::SLGM, 25}, "No AI Acquire" },
{{RecordType::SLGM, 28}, "Reflected By Auto Water" },
{{RecordType::SLGM, 29}, "Don''t Havok Settle" },
{{RecordType::SLGM, 30}, "No Respawn" },
{{RecordType::SLGM, 31}, "Multibound" },
{{RecordType::STAT, 9}, "Hidden From Local Map" },
{{RecordType::STAT, 10}, "Persistent" },
{{RecordType::STAT, 11}, "Initially Disabled" },
{{RecordType::STAT, 13}, "Sky Marker" },
{{RecordType::STAT, 15}, "Visible when distant" },
{{RecordType::STAT, 16}, "Is Full LOD" },
{{RecordType::STAT, 26}, "Filter (Collision Geometry)" },
{{RecordType::STAT, 27}, "Bounding Box (Collision Geometry)"},
{{RecordType::STAT, 28}, "Reflected By Auto Water" },
{{RecordType::STAT, 29}, "Don''t Havok Settle" },
{{RecordType::STAT, 30}, "No Respawn" },
{{RecordType::STAT, 31}, "Multibound" },
{{RecordType::TREE, 9}, "Hidden From Local Map" },
{{RecordType::TREE, 10}, "Persistent" },
{{RecordType::TREE, 11}, "Initially Disabled" },
{{RecordType::TREE, 13}, "Sky Marker" },
{{RecordType::TREE, 15}, "Visible when distant" },
{{RecordType::TREE, 16}, "Is Full LOD" },
{{RecordType::TREE, 26}, "Filter (Collision Geometry)" },
{{RecordType::TREE, 27}, "Bounding Box (Collision Geometry)"},
{{RecordType::TREE, 28}, "Reflected By Auto Water" },
{{RecordType::TREE, 29}, "Don''t Havok Settle" },
{{RecordType::TREE, 30}, "No Respawn" },
{{RecordType::TREE, 31}, "Multibound" },
{{RecordType::WEAP, 10}, "Persistent" },
{{RecordType::WEAP, 11}, "Initially Disabled" },
{{RecordType::WEAP, 16}, "Is Full LOD" },
{{RecordType::WEAP, 25}, "No AI Acquire" },
{{RecordType::WEAP, 28}, "Reflected By Auto Water" },
{{RecordType::WEAP, 29}, "Don''t Havok Settle" },
{{RecordType::WEAP, 30}, "No Respawn" },
{{RecordType::WEAP, 31}, "Multibound" },
}; };
static constexpr auto refr_flag_description_map_std = utility::array_builtin_to_std(refr_flag_description_map_builtin);
static constexpr auto refr_flag_description_map = utility::map_to_soa(refr_flag_description_map_std);
[[nodiscard]] constexpr std::optional<std::string_view> refr_flag_to_description(RefrFlag refr_flag) noexcept
{
return utility::soa_first_to_second(refr_flag_description_map, refr_flag);
}
} }

View File

@@ -1,23 +1,67 @@
#pragma once #pragma once
#include <array> #include <array>
#include <optional>
#include <bit>
namespace utility { namespace utility {
// Converts a string literal to a std::array<char>, from https://stackoverflow.com/a/33484394 // This is a base class for a generic store for some value that can be represented by
template <std::size_t N, std::size_t ... Is> // type T but should not be type checked as type T, but rather some more constrained class.
constexpr std::array<char, N - 1> template <class T>
literal_to_array(const char(&a)[N], std::index_sequence<Is...>) struct Store {
static_assert(std::is_trivial_v<T>);
T value;
friend constexpr auto operator<=>(const Store &, const Store &) noexcept = default;
};
// Convert a fourcc literal (e.g. "LITR" to a uint32_t)
constexpr uint32_t fourcc_lit_to_val(const char(&a)[5]) noexcept
{ {
return { {a[Is]...} }; char temp[4] = { a[0], a[1], a[2], a[3] };
return std::bit_cast<uint32_t, char[4]>(temp);
} }
template <std::size_t N> // Convert a builtin array to a std::array
constexpr std::array<char, N - 1> literal_to_array(const char(&a)[N]) template <typename T, std::size_t N>
constexpr std::array<T, N> array_builtin_to_std(const T(&builtin)[N]) noexcept
{ {
return literal_to_array(a, std::make_index_sequence<N - 1>()); std::array<T, N> array;
std::copy(std::cbegin(builtin), std::cend(builtin), array.begin());
return array;
} }
template <typename First, typename Second, std::size_t N>
constexpr std::pair<std::array<First, N>, std::array<Second, N>> map_to_soa(std::array<std::pair<First, Second>, N> map) noexcept
{
std::array<First, N> first;
std::array<Second, N> second;
for (std::size_t i = 0; i != N; ++i) {
first[i] = map[i].first;
second[i] = map[i].second;
}
return std::make_pair(first, second);
}
template <typename First, typename Second, std::size_t N>
constexpr std::optional<Second> soa_first_to_second(const std::pair<std::array<First, N>, std::array<Second, N>> &soa, const First &first) noexcept
{
auto lhs = std::find(soa.first.cbegin(), soa.first.cend(), first);
if (lhs == soa.first.cend())
return {};
auto index = std::distance(soa.first.cbegin(), lhs);
return { soa.second[index] };
}
template <typename First, typename Second, std::size_t N>
constexpr std::optional<First> soa_second_to_first(const std::pair<std::array<First, N>, std::array<Second, N>> &soa, const Second &second) noexcept
{
auto lhs = std::find(soa.second.cbegin(), soa.second.cend(), second);
if (lhs == soa.second.cend())
return {};
auto index = std::distance(soa.second.cbegin(), lhs);
return { soa.first[index] };
}
// Used to inspect type sizes and values at compile time. Example: // Used to inspect type sizes and values at compile time. Example:
// //
@@ -32,15 +76,5 @@ class TS;
template<typename T> template<typename T>
class TD; class TD;
// This is a base class for a generic store for some value that can be represented by
// type T but should not be type checked as type T, but rather some more constrained class.
template <class T>
struct Store {
static_assert(std::is_trivial_v<T>);
T value;
friend constexpr auto operator<=>(const Store &, const Store &) noexcept = default;
};
} }

View File

@@ -0,0 +1,19 @@
enum class RecordType {
AACT, ACHR, ACTI, ADDN, ALCH, AMMO, ANIO, APPA, ARMA, ARMO, ARTO, ASPC,
ASTP, AVIF, BOOK, BPTD, CAMS, CELL, CLAS, CLDC, CLFM, CLMT, COBJ, COLL,
CONT, CPTH, CSTY, DEBR, DIAL, DLBR, DLVW, DOBJ, DOOR, DUAL, ECZN, EFSH,
ENCH, EQUP, EXPL, EYES, FACT, FLOR, FLST, FSTP, FSTS, FURN, GLOB, GMST,
GRAS, GRUP, HAIR, HAZD, HDPT, IDLE, IDLM, IMAD, IMGS, INFO, INGR, IPCT,
IPDS, KEYM, KYWD, LAND, LCRT, LCTN, LENS, LGTM, LIGH, LSCR, LTEX, LVLI,
LVLN, LVSP, MATO, MATT, MESG, MGEF, MISC, MOVT, MSTT, MUSC, MUST, NAVI,
NAVM, NOTE, NPC_, OTFT, PACK, PARW, PBAR, PBEA, PCON, PERK, PFLA, PGRE,
PHZD, PLYR, PMIS, PROJ, PWAT, QUST, RACE, REFR, REGN, RELA, REVB, RFCT,
RGDL, SCEN, SCOL, SCPT, SCRL, SHOU, SLGM, SMBN, SMEN, SMQN, SNCT, SNDR,
SOPM, SOUN, SPEL, SPGD, STAT, TACT, TES4, TREE, TXST, VOLI, VTYP, WATR,
WEAP, WOOP, WRLD, WTHR, };
[[nodiscard]] constexpr std::optional<std::string_view> group_type_to_name(GroupType group_type) noexcept;
[[nodiscard]] constexpr std::optional<FourCC> record_type_to_fourcc(RecordType record_type) noexcept;
[[nodiscard]] constexpr std::optional<RecordType> fourcc_to_record_type(FourCC fourcc) noexcept;
[[nodiscard]] constexpr std::optional<std::string_view> record_type_to_name(RecordType record_type) noexcept;
[[nodiscard]] constexpr std::optional<std::string_view> flag_to_description(Flag flag) noexcept;
[[nodiscard]] constexpr std::optional<std::string_view> refr_flag_to_description(RefrFlag refr_flag) noexcept;

View File

@@ -0,0 +1,614 @@
#include "esx_reader.hpp"
using namespace esxr;
namespace esxr_lut {
static constexpr std::pair<GroupType, std::string_view> group_type_name_map_builtin[] {
{GroupType::Top , "Top Type" },
{GroupType::WorldChildren , "World Children" },
{GroupType::InteriorCellBlock , "Interior Cell Block" },
{GroupType::InteriorCellSubBlock , "Interior Cell Sub-Block" },
{GroupType::ExteriorCellBlock , "Exterior Cell" },
{GroupType::ExteriorCellSubBlock , "Exterior Cell Sub-Block" },
{GroupType::CellChildren , "Cell Children" },
{GroupType::TopicChildren , "Topic Children" },
{GroupType::CellPersistentChildren, "Cell Persistent Children"},
{GroupType::CellTemporaryChildren , "Cell Temporary Children" },
};
static constexpr auto group_type_name_map_std = utility::array_builtin_to_std(group_type_name_map_builtin);
static constexpr auto group_type_name_map = utility::map_to_soa(group_type_name_map_std);
[[nodiscard]] constexpr std::optional<std::string_view> group_type_to_name(GroupType group_type) noexcept
{
return utility::soa_first_to_second(group_type_name_map, group_type);
}
static constexpr std::pair<RecordType, FourCC> record_type_fourcc_map_builtin[] {
{RecordType::AACT, FourCC("AACT")}, {RecordType::ACHR, FourCC("ACHR")},
{RecordType::ACTI, FourCC("ACTI")}, {RecordType::ADDN, FourCC("ADDN")},
{RecordType::ALCH, FourCC("ALCH")}, {RecordType::AMMO, FourCC("AMMO")},
{RecordType::ANIO, FourCC("ANIO")}, {RecordType::APPA, FourCC("APPA")},
{RecordType::ARMA, FourCC("ARMA")}, {RecordType::ARMO, FourCC("ARMO")},
{RecordType::ARTO, FourCC("ARTO")}, {RecordType::ASPC, FourCC("ASPC")},
{RecordType::ASTP, FourCC("ASTP")}, {RecordType::AVIF, FourCC("AVIF")},
{RecordType::BOOK, FourCC("BOOK")}, {RecordType::BPTD, FourCC("BPTD")},
{RecordType::CAMS, FourCC("CAMS")}, {RecordType::CELL, FourCC("CELL")},
{RecordType::CLAS, FourCC("CLAS")}, {RecordType::CLDC, FourCC("CLDC")},
{RecordType::CLFM, FourCC("CLFM")}, {RecordType::CLMT, FourCC("CLMT")},
{RecordType::COBJ, FourCC("COBJ")}, {RecordType::COLL, FourCC("COLL")},
{RecordType::CONT, FourCC("CONT")}, {RecordType::CPTH, FourCC("CPTH")},
{RecordType::CSTY, FourCC("CSTY")}, {RecordType::DEBR, FourCC("DEBR")},
{RecordType::DIAL, FourCC("DIAL")}, {RecordType::DLBR, FourCC("DLBR")},
{RecordType::DLVW, FourCC("DLVW")}, {RecordType::DOBJ, FourCC("DOBJ")},
{RecordType::DOOR, FourCC("DOOR")}, {RecordType::DUAL, FourCC("DUAL")},
{RecordType::ECZN, FourCC("ECZN")}, {RecordType::EFSH, FourCC("EFSH")},
{RecordType::ENCH, FourCC("ENCH")}, {RecordType::EQUP, FourCC("EQUP")},
{RecordType::EXPL, FourCC("EXPL")}, {RecordType::EYES, FourCC("EYES")},
{RecordType::FACT, FourCC("FACT")}, {RecordType::FLOR, FourCC("FLOR")},
{RecordType::FLST, FourCC("FLST")}, {RecordType::FSTP, FourCC("FSTP")},
{RecordType::FSTS, FourCC("FSTS")}, {RecordType::FURN, FourCC("FURN")},
{RecordType::GLOB, FourCC("GLOB")}, {RecordType::GMST, FourCC("GMST")},
{RecordType::GRAS, FourCC("GRAS")}, {RecordType::GRUP, FourCC("GRUP")},
{RecordType::HAIR, FourCC("HAIR")}, {RecordType::HAZD, FourCC("HAZD")},
{RecordType::HDPT, FourCC("HDPT")}, {RecordType::IDLE, FourCC("IDLE")},
{RecordType::IDLM, FourCC("IDLM")}, {RecordType::IMAD, FourCC("IMAD")},
{RecordType::IMGS, FourCC("IMGS")}, {RecordType::INFO, FourCC("INFO")},
{RecordType::INGR, FourCC("INGR")}, {RecordType::IPCT, FourCC("IPCT")},
{RecordType::IPDS, FourCC("IPDS")}, {RecordType::KEYM, FourCC("KEYM")},
{RecordType::KYWD, FourCC("KYWD")}, {RecordType::LAND, FourCC("LAND")},
{RecordType::LCRT, FourCC("LCRT")}, {RecordType::LCTN, FourCC("LCTN")},
{RecordType::LENS, FourCC("LENS")}, {RecordType::LGTM, FourCC("LGTM")},
{RecordType::LIGH, FourCC("LIGH")}, {RecordType::LSCR, FourCC("LSCR")},
{RecordType::LTEX, FourCC("LTEX")}, {RecordType::LVLI, FourCC("LVLI")},
{RecordType::LVLN, FourCC("LVLN")}, {RecordType::LVSP, FourCC("LVSP")},
{RecordType::MATO, FourCC("MATO")}, {RecordType::MATT, FourCC("MATT")},
{RecordType::MESG, FourCC("MESG")}, {RecordType::MGEF, FourCC("MGEF")},
{RecordType::MISC, FourCC("MISC")}, {RecordType::MOVT, FourCC("MOVT")},
{RecordType::MSTT, FourCC("MSTT")}, {RecordType::MUSC, FourCC("MUSC")},
{RecordType::MUST, FourCC("MUST")}, {RecordType::NAVI, FourCC("NAVI")},
{RecordType::NAVM, FourCC("NAVM")}, {RecordType::NOTE, FourCC("NOTE")},
{RecordType::NPC_, FourCC("NPC_")}, {RecordType::OTFT, FourCC("OTFT")},
{RecordType::PACK, FourCC("PACK")}, {RecordType::PARW, FourCC("PARW")},
{RecordType::PBAR, FourCC("PBAR")}, {RecordType::PBEA, FourCC("PBEA")},
{RecordType::PCON, FourCC("PCON")}, {RecordType::PERK, FourCC("PERK")},
{RecordType::PFLA, FourCC("PFLA")}, {RecordType::PGRE, FourCC("PGRE")},
{RecordType::PHZD, FourCC("PHZD")}, {RecordType::PLYR, FourCC("PLYR")},
{RecordType::PMIS, FourCC("PMIS")}, {RecordType::PROJ, FourCC("PROJ")},
{RecordType::PWAT, FourCC("PWAT")}, {RecordType::QUST, FourCC("QUST")},
{RecordType::RACE, FourCC("RACE")}, {RecordType::REFR, FourCC("REFR")},
{RecordType::REGN, FourCC("REGN")}, {RecordType::RELA, FourCC("RELA")},
{RecordType::REVB, FourCC("REVB")}, {RecordType::RFCT, FourCC("RFCT")},
{RecordType::RGDL, FourCC("RGDL")}, {RecordType::SCEN, FourCC("SCEN")},
{RecordType::SCOL, FourCC("SCOL")}, {RecordType::SCPT, FourCC("SCPT")},
{RecordType::SCRL, FourCC("SCRL")}, {RecordType::SHOU, FourCC("SHOU")},
{RecordType::SLGM, FourCC("SLGM")}, {RecordType::SMBN, FourCC("SMBN")},
{RecordType::SMEN, FourCC("SMEN")}, {RecordType::SMQN, FourCC("SMQN")},
{RecordType::SNCT, FourCC("SNCT")}, {RecordType::SNDR, FourCC("SNDR")},
{RecordType::SOPM, FourCC("SOPM")}, {RecordType::SOUN, FourCC("SOUN")},
{RecordType::SPEL, FourCC("SPEL")}, {RecordType::SPGD, FourCC("SPGD")},
{RecordType::STAT, FourCC("STAT")}, {RecordType::TACT, FourCC("TACT")},
{RecordType::TES4, FourCC("TES4")}, {RecordType::TREE, FourCC("TREE")},
{RecordType::TXST, FourCC("TXST")}, {RecordType::VOLI, FourCC("VOLI")},
{RecordType::VTYP, FourCC("VTYP")}, {RecordType::WATR, FourCC("WATR")},
{RecordType::WEAP, FourCC("WEAP")}, {RecordType::WOOP, FourCC("WOOP")},
{RecordType::WRLD, FourCC("WRLD")}, {RecordType::WTHR, FourCC("WTHR")},
};
static constexpr auto record_type_fourcc_map_std = utility::array_builtin_to_std(record_type_fourcc_map_builtin);
static constexpr auto record_type_fourcc_map = utility::map_to_soa(record_type_fourcc_map_std);
[[nodiscard]] constexpr std::optional<FourCC> record_type_to_fourcc(RecordType record_type) noexcept
{
return utility::soa_first_to_second(record_type_fourcc_map, record_type);
}
[[nodiscard]] constexpr std::optional<RecordType> fourcc_to_record_type(FourCC fourcc) noexcept
{
return utility::soa_second_to_first(record_type_fourcc_map, fourcc);
}
static constexpr std::pair<RecordType, std::string_view> record_type_name_map_builtin[] {
{RecordType::AACT, "Action" },
{RecordType::ACHR, "Placed NPC" },
{RecordType::ACTI, "Activator" },
{RecordType::ADDN, "Addon Node" },
{RecordType::ALCH, "Ingestible" },
{RecordType::AMMO, "Ammunition" },
{RecordType::ANIO, "Animated Object" },
{RecordType::APPA, "Alchemical Apparatus" },
{RecordType::ARMA, "Armor Addon" },
{RecordType::ARMO, "Armor" },
{RecordType::ARTO, "Art Object" },
{RecordType::ASPC, "Acoustic Space" },
{RecordType::ASTP, "Association Type" },
{RecordType::AVIF, "Actor Value Information" },
{RecordType::BOOK, "Book" },
{RecordType::BPTD, "Body Part Data" },
{RecordType::CAMS, "Camera Shot" },
{RecordType::CELL, "Cell" },
{RecordType::CLAS, "Class" },
{RecordType::CLDC, "CLDC" },
{RecordType::CLFM, "Color" },
{RecordType::CLMT, "Climate" },
{RecordType::COBJ, "Constructible Object" },
{RecordType::COLL, "Collision Layer" },
{RecordType::CONT, "Container" },
{RecordType::CPTH, "Camera Path" },
{RecordType::CSTY, "Combat Style" },
{RecordType::DEBR, "Debris" },
{RecordType::DIAL, "Dialog Topic" },
{RecordType::DLBR, "Dialog Branch" },
{RecordType::DLVW, "Dialog View" },
{RecordType::DOBJ, "Default Object Manager" },
{RecordType::DOOR, "Door" },
{RecordType::DUAL, "Dual Cast Data" },
{RecordType::ECZN, "Encounter Zone" },
{RecordType::EFSH, "Effect Shader" },
{RecordType::ENCH, "Object Effect" },
{RecordType::EQUP, "Equip Type" },
{RecordType::EXPL, "Explosion" },
{RecordType::EYES, "Eyes" },
{RecordType::FACT, "Faction" },
{RecordType::FLOR, "Flora" },
{RecordType::FLST, "FormID List" },
{RecordType::FSTP, "Footstep" },
{RecordType::FSTS, "Footstep Set" },
{RecordType::FURN, "Furniture" },
{RecordType::GLOB, "Global" },
{RecordType::GMST, "Game Setting" },
{RecordType::GRAS, "Grass" },
{RecordType::GRUP, "Group" },
{RecordType::HAIR, "HAIR" },
{RecordType::HAZD, "Hazard" },
{RecordType::HDPT, "Head Part" },
{RecordType::IDLE, "Idle Animation" },
{RecordType::IDLM, "Idle Marker" },
{RecordType::IMAD, "Image Space Adapter" },
{RecordType::IMGS, "Image Space" },
{RecordType::INFO, "Dialog response" },
{RecordType::INGR, "Ingredient" },
{RecordType::IPCT, "Impact" },
{RecordType::IPDS, "Impact Data Set" },
{RecordType::KEYM, "Key" },
{RecordType::KYWD, "Keyword" },
{RecordType::LAND, "Landscape" },
{RecordType::LCRT, "Location Reference Type" },
{RecordType::LCTN, "Location" },
{RecordType::LENS, "Lens Flare" },
{RecordType::LGTM, "Lighting Template" },
{RecordType::LIGH, "Light" },
{RecordType::LSCR, "Load Screen" },
{RecordType::LTEX, "Landscape Texture" },
{RecordType::LVLI, "Leveled Item" },
{RecordType::LVLN, "Leveled NPC" },
{RecordType::LVSP, "Leveled Spell" },
{RecordType::MATO, "Material Object" },
{RecordType::MATT, "Material Type" },
{RecordType::MESG, "Message" },
{RecordType::MGEF, "Magic Effect" },
{RecordType::MISC, "Misc. Item" },
{RecordType::MOVT, "Movement Type" },
{RecordType::MSTT, "Moveable Static" },
{RecordType::MUSC, "Music Type" },
{RecordType::MUST, "Music Track" },
{RecordType::NAVI, "Navigation Mesh Info Map" },
{RecordType::NAVM, "Navigation Mesh" },
{RecordType::NOTE, "Note" },
{RecordType::NPC_, "Non-Player Character (Actor)"},
{RecordType::OTFT, "Outfit" },
{RecordType::PACK, "Package" },
{RecordType::PARW, "Placed Arrow" },
{RecordType::PBAR, "Placed Barrier" },
{RecordType::PBEA, "Placed Beam" },
{RecordType::PCON, "Placed Cone/Voice" },
{RecordType::PERK, "Perk" },
{RecordType::PFLA, "Placed Flame" },
{RecordType::PGRE, "Placed Projectile" },
{RecordType::PHZD, "Placed Hazard" },
{RecordType::PLYR, "Player Reference" },
{RecordType::PMIS, "Placed Missile" },
{RecordType::PROJ, "Projectile" },
{RecordType::PWAT, "PWAT" },
{RecordType::QUST, "Quest" },
{RecordType::RACE, "Race" },
{RecordType::REFR, "Placed Object" },
{RecordType::REGN, "Region" },
{RecordType::RELA, "Relationship" },
{RecordType::REVB, "Reverb Parameters" },
{RecordType::RFCT, "Visual Effect" },
{RecordType::RGDL, "RGDL" },
{RecordType::SCEN, "Scene" },
{RecordType::SCOL, "Static Collection" },
{RecordType::SCPT, "SCPT" },
{RecordType::SCRL, "Scroll" },
{RecordType::SHOU, "Shout" },
{RecordType::SLGM, "Soul Gem" },
{RecordType::SMBN, "Story Manager Branch Node" },
{RecordType::SMEN, "Story Manager Event Node" },
{RecordType::SMQN, "Story Manager Quest Node" },
{RecordType::SNCT, "Sound Category" },
{RecordType::SNDR, "Sound Descriptor" },
{RecordType::SOPM, "Sound Output Model" },
{RecordType::SOUN, "Sound Marker" },
{RecordType::SPEL, "Spell" },
{RecordType::SPGD, "Shader Particle Geometry" },
{RecordType::STAT, "Static" },
{RecordType::TACT, "Talking Activator" },
{RecordType::TES4, "Main File Header" },
{RecordType::TREE, "Tree" },
{RecordType::TXST, "Texture Set" },
{RecordType::VOLI, "Volumetric Lighting" },
{RecordType::VTYP, "Voice Type" },
{RecordType::WATR, "Water" },
{RecordType::WEAP, "Weapon" },
{RecordType::WOOP, "Word of Power" },
{RecordType::WRLD, "Worldspace" },
{RecordType::WTHR, "Weather" },
};
static constexpr auto record_type_name_map_std = utility::array_builtin_to_std(record_type_name_map_builtin);
static constexpr auto record_type_name_map = utility::map_to_soa(record_type_name_map_std);
[[nodiscard]] constexpr std::optional<std::string_view> record_type_to_name(RecordType record_type) noexcept
{
return utility::soa_first_to_second(record_type_name_map, record_type);
}
static constexpr std::pair<Flag, std::string_view> flag_description_map_builtin[] {
{{RecordType::ACHR, 9}, "Starts Dead" },
{{RecordType::ACHR, 10}, "Persistent" },
{{RecordType::ACHR, 11}, "Initially Disabled" },
{{RecordType::ACHR, 25}, "No AI Acquire" },
{{RecordType::ACHR, 29}, "Don't Havok Settle" },
{{RecordType::ACTI, 6}, "Has Tree LOD" },
{{RecordType::ACTI, 8}, "Must Update Anims" },
{{RecordType::ACTI, 9}, "Hidden From Local Map" },
{{RecordType::ACTI, 15}, "Has Distant LOD" },
{{RecordType::ACTI, 16}, "Random Anim Start" },
{{RecordType::ACTI, 17}, "Dangerous" },
{{RecordType::ACTI, 20}, "Ignore Object Interaction" },
{{RecordType::ACTI, 23}, "Is Marker" },
{{RecordType::ACTI, 25}, "Obstacle" },
{{RecordType::ACTI, 26}, "NavMesh Generation - Filter" },
{{RecordType::ACTI, 27}, "NavMesh Generation - Bounding Box"},
{{RecordType::ACTI, 29}, "Child Can Use" },
{{RecordType::ACTI, 30}, "NavMesh Generation - Ground" },
{{RecordType::ALCH, 29}, "Medicine" },
{{RecordType::AMMO, 2}, "Non-Playable" },
{{RecordType::ANIO, 9}, "Unknown 9" },
{{RecordType::ARMO, 2}, "Non-Playable" },
{{RecordType::ARMO, 6}, "Shield" },
{{RecordType::ARMO, 10}, "Unknown 10" },
{{RecordType::ARMO, 15}, "Unknown 15" },
{{RecordType::CELL, 10}, "Persistent" },
{{RecordType::CELL, 17}, "Off Limits" },
{{RecordType::CELL, 18}, "Compressed" },
{{RecordType::CELL, 19}, "Can't Wait" },
{{RecordType::CLFM, 2}, "Non-Playable" },
{{RecordType::CONT, 15}, "Has Distant LOD" },
{{RecordType::CONT, 16}, "Random Anim Start" },
{{RecordType::CONT, 25}, "Obstacle" },
{{RecordType::CONT, 26}, "NavMesh Generation - Filter" },
{{RecordType::CONT, 27}, "NavMesh Generation - Bounding Box"},
{{RecordType::CONT, 30}, "NavMesh Generation - Ground" },
{{RecordType::CSTY, 19}, "Allow Dual Wielding" },
{{RecordType::DOOR, 15}, "Has Distant LOD" },
{{RecordType::DOOR, 16}, "Random Anim Start" },
{{RecordType::DOOR, 23}, "Is Marker" },
{{RecordType::EYES, 2}, "Non-Playable" },
{{RecordType::FURN, 7}, "Is Perch" },
{{RecordType::FURN, 15}, "Has Distant LOD" },
{{RecordType::FURN, 16}, "Random Anim Start" },
{{RecordType::FURN, 23}, "Is Marker" },
{{RecordType::FURN, 28}, "Must Exit To Talk" },
{{RecordType::FURN, 29}, "Child Can Use" },
{{RecordType::GLOB, 6}, "Constant" },
{{RecordType::HDPT, 2}, "Non-Playable" },
{{RecordType::IDLM, 29}, "Child Can Use" },
{{RecordType::INFO, 13}, "Actor Changed" },
{{RecordType::KEYM, 2}, "Non-Playable" },
{{RecordType::LAND, 18}, "Compressed" },
{{RecordType::LIGH, 16}, "Random Anim Start" },
{{RecordType::LIGH, 17}, "Portal-strict" },
{{RecordType::LIGH, 25}, "Obstacle" },
{{RecordType::LSCR, 10}, "Displays In Main Menu" },
{{RecordType::MISC, 2}, "Non-Playable" },
{{RecordType::MSTT, 8}, "Must Update Anims" },
{{RecordType::MSTT, 9}, "Hidden From Local Map" },
{{RecordType::MSTT, 15}, "Has Distant LOD" },
{{RecordType::MSTT, 16}, "Random Anim Start" },
{{RecordType::MSTT, 19}, "Has Currents" },
{{RecordType::MSTT, 25}, "Obstacle" },
{{RecordType::MSTT, 26}, "NavMesh Generation - Filter" },
{{RecordType::MSTT, 27}, "NavMesh Generation - Bounding Box"},
{{RecordType::MSTT, 30}, "NavMesh Generation - Ground" },
{{RecordType::NAVM, 18}, "Compressed" },
{{RecordType::NAVM, 26}, "AutoGen" },
{{RecordType::NAVM, 31}, "NavmeshGenCell" },
{{RecordType::NPC_, 10}, "Unknown 10" },
{{RecordType::NPC_, 18}, "Compressed" },
{{RecordType::NPC_, 19}, "Unknown 19" },
{{RecordType::NPC_, 29}, "Bleedout Override" },
{{RecordType::PARW, 7}, "Turn Off Fire" },
{{RecordType::PARW, 10}, "Persistent" },
{{RecordType::PARW, 11}, "Initially Disabled" },
{{RecordType::PARW, 28}, "Reflected By Auto Water" },
{{RecordType::PARW, 29}, "Don't Havok Settle" },
{{RecordType::PARW, 30}, "No Respawn" },
{{RecordType::PBAR, 7}, "Turn Off Fire" },
{{RecordType::PBAR, 10}, "Persistent" },
{{RecordType::PBAR, 11}, "Initially Disabled" },
{{RecordType::PBAR, 28}, "Reflected By Auto Water" },
{{RecordType::PBAR, 29}, "Don't Havok Settle" },
{{RecordType::PBAR, 30}, "No Respawn" },
{{RecordType::PBEA, 7}, "Turn Off Fire" },
{{RecordType::PBEA, 10}, "Persistent" },
{{RecordType::PBEA, 11}, "Initially Disabled" },
{{RecordType::PBEA, 28}, "Reflected By Auto Water" },
{{RecordType::PBEA, 29}, "Don't Havok Settle" },
{{RecordType::PBEA, 30}, "No Respawn" },
{{RecordType::PCON, 7}, "Turn Off Fire" },
{{RecordType::PCON, 10}, "Persistent" },
{{RecordType::PCON, 11}, "Initially Disabled" },
{{RecordType::PCON, 28}, "Reflected By Auto Water" },
{{RecordType::PCON, 29}, "Don't Havok Settle" },
{{RecordType::PCON, 30}, "No Respawn" },
{{RecordType::PERK, 2}, "Non-Playable" },
{{RecordType::PFLA, 7}, "Turn Off Fire" },
{{RecordType::PFLA, 10}, "Persistent" },
{{RecordType::PFLA, 11}, "Initially Disabled" },
{{RecordType::PFLA, 28}, "Reflected By Auto Water" },
{{RecordType::PFLA, 29}, "Don't Havok Settle" },
{{RecordType::PFLA, 30}, "No Respawn" },
{{RecordType::PGRE, 7}, "Turn Off Fire" },
{{RecordType::PGRE, 10}, "Persistent" },
{{RecordType::PGRE, 11}, "Initially Disabled" },
{{RecordType::PGRE, 28}, "Reflected By Auto Water" },
{{RecordType::PGRE, 29}, "Don't Havok Settle" },
{{RecordType::PGRE, 30}, "No Respawn" },
{{RecordType::PHZD, 7}, "Turn Off Fire" },
{{RecordType::PHZD, 10}, "Persistent" },
{{RecordType::PHZD, 11}, "Initially Disabled" },
{{RecordType::PHZD, 28}, "Reflected By Auto Water" },
{{RecordType::PHZD, 29}, "Don't Havok Settle" },
{{RecordType::PHZD, 30}, "No Respawn" },
{{RecordType::PMIS, 7}, "Turn Off Fire" },
{{RecordType::PMIS, 10}, "Persistent" },
{{RecordType::PMIS, 11}, "Initially Disabled" },
{{RecordType::PMIS, 28}, "Reflected By Auto Water" },
{{RecordType::PMIS, 29}, "Don't Havok Settle" },
{{RecordType::PMIS, 30}, "No Respawn" },
{{RecordType::RACE, 19}, "Critter?" },
{{RecordType::REFR, 10}, "Persistent" },
{{RecordType::REFR, 11}, "Initially Disabled" },
{{RecordType::REFR, 16}, "Is Full LOD" },
{{RecordType::REFR, 26}, "Filter (Collision Geometry)" },
{{RecordType::REFR, 27}, "Bounding Box (Collision Geometry)"},
{{RecordType::REFR, 28}, "Reflected By Auto Water" },
{{RecordType::REFR, 30}, "Ground" },
{{RecordType::REFR, 31}, "Multibound" },
{{RecordType::REGN, 6}, "Border Region" },
{{RecordType::RELA, 6}, "Secret" },
{{RecordType::SHOU, 7}, "Treat spells as powers" },
{{RecordType::SLGM, 17}, "Can Hold NPC Soul" },
{{RecordType::STAT, 2}, "Never Fades" },
{{RecordType::STAT, 5}, "Deleted" },
{{RecordType::STAT, 6}, "Has Tree LOD" },
{{RecordType::STAT, 7}, "Add-On LOD Object" },
{{RecordType::STAT, 9}, "Hidden From Local Map" },
{{RecordType::STAT, 11}, "Unknown 11" },
{{RecordType::STAT, 15}, "Has Distant LOD" },
{{RecordType::STAT, 16}, "Unknown 16" },
{{RecordType::STAT, 17}, "Uses HD LOD Texture" },
{{RecordType::STAT, 19}, "Has Currents" },
{{RecordType::STAT, 23}, "Is Marker" },
{{RecordType::STAT, 25}, "Obstacle" },
{{RecordType::STAT, 26}, "NavMesh Generation - Filter" },
{{RecordType::STAT, 27}, "NavMesh Generation - Bounding Box"},
{{RecordType::STAT, 28}, "Show In World Map" },
{{RecordType::STAT, 30}, "NavMesh Generation - Ground" },
{{RecordType::TACT, 9}, "Hidden From Local Map" },
{{RecordType::TACT, 16}, "Random Anim Start" },
{{RecordType::TACT, 17}, "Radio Station" },
{{RecordType::TES4, 0}, "ESM" },
{{RecordType::TES4, 1}, "Altered" },
{{RecordType::TES4, 2}, "Checked" },
{{RecordType::TES4, 3}, "Active" },
{{RecordType::TES4, 4}, "Optimized File" },
{{RecordType::TES4, 5}, "Temp ID Owner" },
{{RecordType::TES4, 7}, "Localized" },
{{RecordType::TES4, 8}, "Precalc Data Only" },
{{RecordType::TES4, 9}, "ESL" },
{{RecordType::TREE, 15}, "Has Distant LOD" },
{{RecordType::WEAP, 2}, "Non-Playable" },
{{RecordType::WRLD, 19}, "Can't Wait" },
};
static constexpr auto flag_description_map_std = utility::array_builtin_to_std(flag_description_map_builtin);
static constexpr auto flag_description_map = utility::map_to_soa(flag_description_map_std);
[[nodiscard]] constexpr std::optional<std::string_view> flag_to_description(Flag flag) noexcept
{
return utility::soa_first_to_second(flag_description_map, flag);
}
static constexpr std::pair<RefrFlag, std::string_view> refr_flag_description_map_builtin[] {
{{RecordType::ACTI, 9}, "Hidden From Local Map" },
{{RecordType::ACTI, 10}, "Persistent" },
{{RecordType::ACTI, 11}, "Initially Disabled" },
{{RecordType::ACTI, 13}, "Sky Marker" },
{{RecordType::ACTI, 15}, "Visible when distant" },
{{RecordType::ACTI, 16}, "Is Full LOD" },
{{RecordType::ACTI, 26}, "Filter (Collision Geometry)" },
{{RecordType::ACTI, 27}, "Bounding Box (Collision Geometry)"},
{{RecordType::ACTI, 28}, "Reflected By Auto Water" },
{{RecordType::ACTI, 29}, "Don''t Havok Settle" },
{{RecordType::ACTI, 30}, "No Respawn" },
{{RecordType::ACTI, 31}, "Multibound" },
{{RecordType::ADDN, 10}, "Persistent" },
{{RecordType::ADDN, 11}, "Initially Disabled" },
{{RecordType::ADDN, 16}, "Is Full LOD" },
{{RecordType::ADDN, 28}, "Reflected By Auto Water" },
{{RecordType::ADDN, 29}, "Don''t Havok Settle" },
{{RecordType::ADDN, 30}, "No Respawn" },
{{RecordType::ADDN, 31}, "Multibound" },
{{RecordType::ALCH, 10}, "Persistent" },
{{RecordType::ALCH, 11}, "Initially Disabled" },
{{RecordType::ALCH, 16}, "Is Full LOD" },
{{RecordType::ALCH, 25}, "No AI Acquire" },
{{RecordType::ALCH, 28}, "Reflected By Auto Water" },
{{RecordType::ALCH, 29}, "Don''t Havok Settle" },
{{RecordType::ALCH, 30}, "No Respawn" },
{{RecordType::ALCH, 31}, "Multibound" },
{{RecordType::AMMO, 10}, "Persistent" },
{{RecordType::AMMO, 11}, "Initially Disabled" },
{{RecordType::AMMO, 16}, "Is Full LOD" },
{{RecordType::AMMO, 25}, "No AI Acquire" },
{{RecordType::AMMO, 28}, "Reflected By Auto Water" },
{{RecordType::AMMO, 29}, "Don''t Havok Settle" },
{{RecordType::AMMO, 30}, "No Respawn" },
{{RecordType::AMMO, 31}, "Multibound" },
{{RecordType::ARMO, 10}, "Persistent" },
{{RecordType::ARMO, 11}, "Initially Disabled" },
{{RecordType::ARMO, 16}, "Is Full LOD" },
{{RecordType::ARMO, 25}, "No AI Acquire" },
{{RecordType::ARMO, 28}, "Reflected By Auto Water" },
{{RecordType::ARMO, 29}, "Don''t Havok Settle" },
{{RecordType::ARMO, 30}, "No Respawn" },
{{RecordType::ARMO, 31}, "Multibound" },
{{RecordType::BOOK, 10}, "Persistent" },
{{RecordType::BOOK, 11}, "Initially Disabled" },
{{RecordType::BOOK, 16}, "Is Full LOD" },
{{RecordType::BOOK, 25}, "No AI Acquire" },
{{RecordType::BOOK, 28}, "Reflected By Auto Water" },
{{RecordType::BOOK, 29}, "Don''t Havok Settle" },
{{RecordType::BOOK, 30}, "No Respawn" },
{{RecordType::BOOK, 31}, "Multibound" },
{{RecordType::CONT, 10}, "Persistent" },
{{RecordType::CONT, 11}, "Initially Disabled" },
{{RecordType::CONT, 16}, "Is Full LOD" },
{{RecordType::CONT, 25}, "No AI Acquire" },
{{RecordType::CONT, 26}, "Filter (Collision Geometry)" },
{{RecordType::CONT, 27}, "Bounding Box (Collision Geometry)"},
{{RecordType::CONT, 28}, "Reflected By Auto Water" },
{{RecordType::CONT, 29}, "Don''t Havok Settle" },
{{RecordType::CONT, 30}, "Ground" },
{{RecordType::CONT, 31}, "Multibound" },
{{RecordType::DOOR, 6}, "Hidden From Local Map" },
{{RecordType::DOOR, 8}, "Inaccessible" },
{{RecordType::DOOR, 10}, "Persistent" },
{{RecordType::DOOR, 11}, "Initially Disabled" },
{{RecordType::DOOR, 16}, "Is Full LOD" },
{{RecordType::DOOR, 26}, "Filter (Collision Geometry)" },
{{RecordType::DOOR, 27}, "Bounding Box (Collision Geometry)"},
{{RecordType::DOOR, 28}, "Reflected By Auto Water" },
{{RecordType::DOOR, 29}, "Don''t Havok Settle" },
{{RecordType::DOOR, 30}, "No Respawn" },
{{RecordType::DOOR, 31}, "Multibound" },
{{RecordType::FLOR, 9}, "Hidden From Local Map" },
{{RecordType::FLOR, 10}, "Persistent" },
{{RecordType::FLOR, 11}, "Initially Disabled" },
{{RecordType::FLOR, 13}, "Sky Marker" },
{{RecordType::FLOR, 15}, "Visible when distant" },
{{RecordType::FLOR, 16}, "Is Full LOD" },
{{RecordType::FLOR, 26}, "Filter (Collision Geometry)" },
{{RecordType::FLOR, 27}, "Bounding Box (Collision Geometry)"},
{{RecordType::FLOR, 28}, "Reflected By Auto Water" },
{{RecordType::FLOR, 29}, "Don''t Havok Settle" },
{{RecordType::FLOR, 30}, "No Respawn" },
{{RecordType::FLOR, 31}, "Multibound" },
{{RecordType::INGR, 10}, "Persistent" },
{{RecordType::INGR, 11}, "Initially Disabled" },
{{RecordType::INGR, 16}, "Is Full LOD" },
{{RecordType::INGR, 25}, "No AI Acquire" },
{{RecordType::INGR, 28}, "Reflected By Auto Water" },
{{RecordType::INGR, 29}, "Don''t Havok Settle" },
{{RecordType::INGR, 30}, "No Respawn" },
{{RecordType::INGR, 31}, "Multibound" },
{{RecordType::KEYM, 10}, "Persistent" },
{{RecordType::KEYM, 11}, "Initially Disabled" },
{{RecordType::KEYM, 16}, "Is Full LOD" },
{{RecordType::KEYM, 25}, "No AI Acquire" },
{{RecordType::KEYM, 28}, "Reflected By Auto Water" },
{{RecordType::KEYM, 29}, "Don''t Havok Settle" },
{{RecordType::KEYM, 30}, "No Respawn" },
{{RecordType::KEYM, 31}, "Multibound" },
{{RecordType::LIGH, 8}, "Doesn''t Light Water" },
{{RecordType::LIGH, 9}, "Casts Shadows" },
{{RecordType::LIGH, 10}, "Persistent" },
{{RecordType::LIGH, 11}, "Initially Disabled" },
{{RecordType::LIGH, 16}, "Never Fades" },
{{RecordType::LIGH, 17}, "Doesn''t Light Landscape" },
{{RecordType::LIGH, 25}, "No AI Acquire" },
{{RecordType::LIGH, 28}, "Reflected By Auto Water" },
{{RecordType::LIGH, 29}, "Don''t Havok Settle" },
{{RecordType::LIGH, 30}, "No Respawn" },
{{RecordType::LIGH, 31}, "Multibound" },
{{RecordType::MISC, 10}, "Persistent" },
{{RecordType::MISC, 11}, "Initially Disabled" },
{{RecordType::MISC, 16}, "Is Full LOD" },
{{RecordType::MISC, 25}, "No AI Acquire" },
{{RecordType::MISC, 28}, "Reflected By Auto Water" },
{{RecordType::MISC, 29}, "Don''t Havok Settle" },
{{RecordType::MISC, 30}, "No Respawn" },
{{RecordType::MISC, 31}, "Multibound" },
{{RecordType::MSTT, 9}, "Motion Blur" },
{{RecordType::MSTT, 10}, "Persistent" },
{{RecordType::MSTT, 11}, "Initially Disabled" },
{{RecordType::MSTT, 16}, "Is Full LOD" },
{{RecordType::MSTT, 26}, "Filter (Collision Geometry)" },
{{RecordType::MSTT, 27}, "Bounding Box (Collision Geometry)"},
{{RecordType::MSTT, 28}, "Reflected By Auto Water" },
{{RecordType::MSTT, 29}, "Don''t Havok Settle" },
{{RecordType::MSTT, 30}, "No Respawn" },
{{RecordType::MSTT, 31}, "Multibound" },
{{RecordType::SCRL, 10}, "Persistent" },
{{RecordType::SCRL, 11}, "Initially Disabled" },
{{RecordType::SCRL, 16}, "Is Full LOD" },
{{RecordType::SCRL, 25}, "No AI Acquire" },
{{RecordType::SCRL, 28}, "Reflected By Auto Water" },
{{RecordType::SCRL, 29}, "Don''t Havok Settle" },
{{RecordType::SCRL, 30}, "No Respawn" },
{{RecordType::SCRL, 31}, "Multibound" },
{{RecordType::SLGM, 10}, "Persistent" },
{{RecordType::SLGM, 11}, "Initially Disabled" },
{{RecordType::SLGM, 16}, "Is Full LOD" },
{{RecordType::SLGM, 25}, "No AI Acquire" },
{{RecordType::SLGM, 28}, "Reflected By Auto Water" },
{{RecordType::SLGM, 29}, "Don''t Havok Settle" },
{{RecordType::SLGM, 30}, "No Respawn" },
{{RecordType::SLGM, 31}, "Multibound" },
{{RecordType::STAT, 9}, "Hidden From Local Map" },
{{RecordType::STAT, 10}, "Persistent" },
{{RecordType::STAT, 11}, "Initially Disabled" },
{{RecordType::STAT, 13}, "Sky Marker" },
{{RecordType::STAT, 15}, "Visible when distant" },
{{RecordType::STAT, 16}, "Is Full LOD" },
{{RecordType::STAT, 26}, "Filter (Collision Geometry)" },
{{RecordType::STAT, 27}, "Bounding Box (Collision Geometry)"},
{{RecordType::STAT, 28}, "Reflected By Auto Water" },
{{RecordType::STAT, 29}, "Don''t Havok Settle" },
{{RecordType::STAT, 30}, "No Respawn" },
{{RecordType::STAT, 31}, "Multibound" },
{{RecordType::TREE, 9}, "Hidden From Local Map" },
{{RecordType::TREE, 10}, "Persistent" },
{{RecordType::TREE, 11}, "Initially Disabled" },
{{RecordType::TREE, 13}, "Sky Marker" },
{{RecordType::TREE, 15}, "Visible when distant" },
{{RecordType::TREE, 16}, "Is Full LOD" },
{{RecordType::TREE, 26}, "Filter (Collision Geometry)" },
{{RecordType::TREE, 27}, "Bounding Box (Collision Geometry)"},
{{RecordType::TREE, 28}, "Reflected By Auto Water" },
{{RecordType::TREE, 29}, "Don''t Havok Settle" },
{{RecordType::TREE, 30}, "No Respawn" },
{{RecordType::TREE, 31}, "Multibound" },
{{RecordType::WEAP, 10}, "Persistent" },
{{RecordType::WEAP, 11}, "Initially Disabled" },
{{RecordType::WEAP, 16}, "Is Full LOD" },
{{RecordType::WEAP, 25}, "No AI Acquire" },
{{RecordType::WEAP, 28}, "Reflected By Auto Water" },
{{RecordType::WEAP, 29}, "Don''t Havok Settle" },
{{RecordType::WEAP, 30}, "No Respawn" },
{{RecordType::WEAP, 31}, "Multibound" },
};
static constexpr auto refr_flag_description_map_std = utility::array_builtin_to_std(refr_flag_description_map_builtin);
static constexpr auto refr_flag_description_map = utility::map_to_soa(refr_flag_description_map_std);
[[nodiscard]] constexpr std::optional<std::string_view> refr_flag_to_description(RefrFlag refr_flag) noexcept
{
return utility::soa_first_to_second(refr_flag_description_map, refr_flag);
}
}

42
reference/group_type.json Normal file
View File

@@ -0,0 +1,42 @@
[
{
"type": "Top",
"name": "Top Type"
},
{
"type": "WorldChildren",
"name": "World Children"
},
{
"type": "InteriorCellBlock",
"name": "Interior Cell Block"
},
{
"type": "InteriorCellSubBlock",
"name": "Interior Cell Sub-Block"
},
{
"type": "ExteriorCellBlock",
"name": "Exterior Cell"
},
{
"type": "ExteriorCellSubBlock",
"name": "Exterior Cell Sub-Block"
},
{
"type": "CellChildren",
"name": "Cell Children"
},
{
"type": "TopicChildren",
"name": "Topic Children"
},
{
"type": "CellPersistentChildren",
"name": "Cell Persistent Children"
},
{
"type": "CellTemporaryChildren",
"name": "Cell Temporary Children"
}
]

179
reference/record_codegen.py Normal file
View File

@@ -0,0 +1,179 @@
import json
import os
from dataclasses import dataclass
INDENT = 8
WIDTH = 80
LAST = "};"
SV = "std::string_view"
PREAMBLE = """#include "esx_reader.hpp"
using namespace esxr;
namespace esxr_lut {"""
POSTAMBLE = "}\n"
def transpose(seq):
return list(zip(*seq))
def clean(seq):
return [x for x in seq if x is not None]
def indented_block(items):
lines = []
line = ""
for item in items:
if len(line) + len(item) + 1 > WIDTH:
lines += [line[:-1]]
line = ""
if not line:
line = " " * INDENT
line += item + ", "
if line.strip():
lines += [line]
return "\n".join(lines)
def indented_list(items):
return ",\n".join([" " * INDENT + x for x in items])
def max_length(list):
return max(map(lambda x: len(x), list))
def wrap_bracket(list):
return ["{" + string + "}" for string in list]
def padded_join(lists):
maximums = [max_length(x) for x in lists]
padded = []
for max, l in zip(maximums, lists):
padded += [[x + " " * (max - len(x)) for x in l]]
padded_transposed = transpose(padded)
return ["".join(x) for x in padded_transposed]
@dataclass
class Map:
first_type: str
second_type: str
first_name: str
second_name: str
formats: list[str]
F_DECL = "static constexpr std::pair<{0}, {1}> {2}_builtin[] {{"
F_SOA = """static constexpr auto {0}_std = utility::array_builtin_to_std({0}_builtin);
static constexpr auto {0} = utility::map_to_soa({0}_std);"""
F_FUNC_DECL = "[[nodiscard]] constexpr std::optional<{0}> {1}_to_{2}({3} {1}) noexcept"
F_FUNC_BODY_FORWARD = " return utility::soa_first_to_second({0}, {1});"
F_FUNC_BODY_REVERSE = " return utility::soa_second_to_first({0}, {1});"
@property
def name(self):
return self.first_name + "_" + self.second_name + "_map"
@property
def decl(self):
return Map.F_DECL.format(self.first_type, self.second_type, self.name)
@property
def to_soa(self):
return Map.F_SOA.format(self.name)
@property
def forward_decl(self):
return Map.F_FUNC_DECL.format(self.second_type, self.first_name, self.second_name, self.first_type)
@property
def reverse_decl(self):
return Map.F_FUNC_DECL.format(self.first_type, self.second_name, self.first_name, self.second_type)
@property
def forward_func(self):
return self.forward_decl + "\n{\n" + Map.F_FUNC_BODY_FORWARD.format(self.name, self.first_name) + "\n}"
@property
def reverse_func(self):
return self.reverse_decl + "\n{\n" + Map.F_FUNC_BODY_REVERSE.format(self.name, self.second_name) + "\n}"
def data_to_list(self, data):
parts = []
for format in self.formats:
parts += [[format.format(*x) for x in data]]
return indented_block(wrap_bracket(padded_join(parts)))
def code(self, data, reverse = False):
parts = [self.decl, self.data_to_list(data), LAST, self.to_soa, self.forward_func]
decls = [self.forward_decl]
if reverse:
parts += [self.reverse_func]
decls += [self.reverse_decl]
return ["\n".join(parts), "\n".join([x + ';' for x in decls])]
def add_extra(data):
grup = {"fourcc": "GRUP", "name": "Group", "flags": []}
note = {"fourcc": "NOTE", "name": "Note", "flags": []}
data += [grup, note]
data.sort(key=lambda x: x["fourcc"])
def gen_enum(data):
# generate sorted list of signatures
sigs = [r["fourcc"] for r in data]
string = "enum class RecordType {\n" + indented_block(sigs) + LAST
return [None, string]
def gen_group_type(data):
map = Map("GroupType", SV, "group_type", "name", ["GroupType::{0}", ", \"{1}\""])
data = [(x['type'], x['name']) for x in data]
return map.code(data)
def gen_names(data):
map = Map("RecordType", SV, "record_type", "name", ["RecordType::{0}", ", \"{1}\""])
data = [(x['fourcc'], x['name']) for x in data]
return map.code(data)
def gen_fourcc(data):
map = Map("RecordType", "FourCC", "record_type", "fourcc", ["RecordType::{0}", ", FourCC(\"{0}\")"])
data = [(x['fourcc'], ) for x in data]
return map.code(data, reverse = True)
def gen_flags(data):
map = Map("Flag", SV, "flag", "description", ["{{RecordType::{0}, {1:>2}}}", ", \"{2}\""])
data = [(x['fourcc'], y['bit'], y['description']) for x in data for y in x['flags']]
return map.code(data)
def gen_refr_flags(data):
map = Map("RefrFlag", SV, "refr_flag", "description", ["{{RecordType::{0}, {1:>2}}}", ", \"{2}\""])
data = [(x['fourcc'], y['bit'], y['description']) for x in data for y in x['flags']]
return map.code(data)
def main():
fdir = os.path.dirname(__file__)
with open(os.path.join(fdir, "records.json"), "r") as f:
data = json.load(f)
with open(os.path.join(fdir, "refr_flags.json"), "r") as f:
refr_data = json.load(f)
with open(os.path.join(fdir, "group_type.json"), "r") as f:
gt_data = json.load(f)
add_extra(data)
code = []
code += [gen_enum(data)]
code += [gen_group_type(gt_data)]
code += [gen_fourcc(data)]
code += [gen_names(data)]
code += [gen_flags(data)]
code += [gen_refr_flags(refr_data)]
code = transpose(code)
lut = [PREAMBLE] + clean(code[0]) + [POSTAMBLE]
lut = "\n\n".join(lut)
header = clean(code[1])
header = "\n".join(header)
with open(os.path.join(fdir, "esx_reader_lut.cpp"), "w") as f:
f.write(lut)
with open(os.path.join(fdir, "esx_reader.hpp.fragment"), "w") as f:
f.write(header)
if __name__ == "__main__":
main()

View File

@@ -63,7 +63,7 @@ for string in all:
bit, desc = re_flag_line.match(line).groups() bit, desc = re_flag_line.match(line).groups()
# fix '' pascal escape and ESL special case # fix '' pascal escape and ESL special case
desc = desc.replace("''", "'").replace("', '", "") desc = desc.replace("''", "'").replace("', '", "")
flags += [Flag(bit, desc)] flags += [Flag(int(bit), desc)]
# handle STAT special case # handle STAT special case
elif sig == "STAT": elif sig == "STAT":
flags_string = re.match(".*?\n.*?wbFlags\(.*?\n(?:.*?\n){32}.*?\]", string).group(0) flags_string = re.match(".*?\n.*?wbFlags\(.*?\n(?:.*?\n){32}.*?\]", string).group(0)
@@ -78,9 +78,6 @@ for string in all:
rdict = {r.fourcc: r for r in records} rdict = {r.fourcc: r for r in records}
records = list(rdict.values()) records = list(rdict.values())
# add in the apparently supported NOTE
records += [Record("NOTE", "Note", [])]
# sort the records by signature # sort the records by signature
records = sorted(records, key=lambda x: x.fourcc) records = sorted(records, key=lambda x: x.fourcc)
@@ -92,6 +89,6 @@ class Encoder(json.JSONEncoder):
else: else:
return json.JSONEncoder.default(self, obj) return json.JSONEncoder.default(self, obj)
with open(os.path.join(fdir, "flags.json"), "w") as f: with open(os.path.join(fdir, "records.json"), "w") as f:
json.dump(records, f, cls=Encoder, indent=4) json.dump(records, f, cls=Encoder, indent=4)

View File

@@ -9,23 +9,23 @@
"name": "Placed NPC", "name": "Placed NPC",
"flags": [ "flags": [
{ {
"bit": "9", "bit": 9,
"description": "Starts Dead" "description": "Starts Dead"
}, },
{ {
"bit": "10", "bit": 10,
"description": "Persistent" "description": "Persistent"
}, },
{ {
"bit": "11", "bit": 11,
"description": "Initially Disabled" "description": "Initially Disabled"
}, },
{ {
"bit": "25", "bit": 25,
"description": "No AI Acquire" "description": "No AI Acquire"
}, },
{ {
"bit": "29", "bit": 29,
"description": "Don't Havok Settle" "description": "Don't Havok Settle"
} }
] ]
@@ -35,55 +35,55 @@
"name": "Activator", "name": "Activator",
"flags": [ "flags": [
{ {
"bit": "6", "bit": 6,
"description": "Has Tree LOD" "description": "Has Tree LOD"
}, },
{ {
"bit": "8", "bit": 8,
"description": "Must Update Anims" "description": "Must Update Anims"
}, },
{ {
"bit": "9", "bit": 9,
"description": "Hidden From Local Map" "description": "Hidden From Local Map"
}, },
{ {
"bit": "15", "bit": 15,
"description": "Has Distant LOD" "description": "Has Distant LOD"
}, },
{ {
"bit": "16", "bit": 16,
"description": "Random Anim Start" "description": "Random Anim Start"
}, },
{ {
"bit": "17", "bit": 17,
"description": "Dangerous" "description": "Dangerous"
}, },
{ {
"bit": "20", "bit": 20,
"description": "Ignore Object Interaction" "description": "Ignore Object Interaction"
}, },
{ {
"bit": "23", "bit": 23,
"description": "Is Marker" "description": "Is Marker"
}, },
{ {
"bit": "25", "bit": 25,
"description": "Obstacle" "description": "Obstacle"
}, },
{ {
"bit": "26", "bit": 26,
"description": "NavMesh Generation - Filter" "description": "NavMesh Generation - Filter"
}, },
{ {
"bit": "27", "bit": 27,
"description": "NavMesh Generation - Bounding Box" "description": "NavMesh Generation - Bounding Box"
}, },
{ {
"bit": "29", "bit": 29,
"description": "Child Can Use" "description": "Child Can Use"
}, },
{ {
"bit": "30", "bit": 30,
"description": "NavMesh Generation - Ground" "description": "NavMesh Generation - Ground"
} }
] ]
@@ -98,7 +98,7 @@
"name": "Ingestible", "name": "Ingestible",
"flags": [ "flags": [
{ {
"bit": "29", "bit": 29,
"description": "Medicine" "description": "Medicine"
} }
] ]
@@ -108,7 +108,7 @@
"name": "Ammunition", "name": "Ammunition",
"flags": [ "flags": [
{ {
"bit": "2", "bit": 2,
"description": "Non-Playable" "description": "Non-Playable"
} }
] ]
@@ -118,7 +118,7 @@
"name": "Animated Object", "name": "Animated Object",
"flags": [ "flags": [
{ {
"bit": "9", "bit": 9,
"description": "Unknown 9" "description": "Unknown 9"
} }
] ]
@@ -138,19 +138,19 @@
"name": "Armor", "name": "Armor",
"flags": [ "flags": [
{ {
"bit": "2", "bit": 2,
"description": "Non-Playable" "description": "Non-Playable"
}, },
{ {
"bit": "6", "bit": 6,
"description": "Shield" "description": "Shield"
}, },
{ {
"bit": "10", "bit": 10,
"description": "Unknown 10" "description": "Unknown 10"
}, },
{ {
"bit": "15", "bit": 15,
"description": "Unknown 15" "description": "Unknown 15"
} }
] ]
@@ -195,19 +195,19 @@
"name": "Cell", "name": "Cell",
"flags": [ "flags": [
{ {
"bit": "10", "bit": 10,
"description": "Persistent" "description": "Persistent"
}, },
{ {
"bit": "17", "bit": 17,
"description": "Off Limits" "description": "Off Limits"
}, },
{ {
"bit": "18", "bit": 18,
"description": "Compressed" "description": "Compressed"
}, },
{ {
"bit": "19", "bit": 19,
"description": "Can't Wait" "description": "Can't Wait"
} }
] ]
@@ -227,7 +227,7 @@
"name": "Color", "name": "Color",
"flags": [ "flags": [
{ {
"bit": "2", "bit": 2,
"description": "Non-Playable" "description": "Non-Playable"
} }
] ]
@@ -252,27 +252,27 @@
"name": "Container", "name": "Container",
"flags": [ "flags": [
{ {
"bit": "15", "bit": 15,
"description": "Has Distant LOD" "description": "Has Distant LOD"
}, },
{ {
"bit": "16", "bit": 16,
"description": "Random Anim Start" "description": "Random Anim Start"
}, },
{ {
"bit": "25", "bit": 25,
"description": "Obstacle" "description": "Obstacle"
}, },
{ {
"bit": "26", "bit": 26,
"description": "NavMesh Generation - Filter" "description": "NavMesh Generation - Filter"
}, },
{ {
"bit": "27", "bit": 27,
"description": "NavMesh Generation - Bounding Box" "description": "NavMesh Generation - Bounding Box"
}, },
{ {
"bit": "30", "bit": 30,
"description": "NavMesh Generation - Ground" "description": "NavMesh Generation - Ground"
} }
] ]
@@ -287,7 +287,7 @@
"name": "Combat Style", "name": "Combat Style",
"flags": [ "flags": [
{ {
"bit": "19", "bit": 19,
"description": "Allow Dual Wielding" "description": "Allow Dual Wielding"
} }
] ]
@@ -322,15 +322,15 @@
"name": "Door", "name": "Door",
"flags": [ "flags": [
{ {
"bit": "15", "bit": 15,
"description": "Has Distant LOD" "description": "Has Distant LOD"
}, },
{ {
"bit": "16", "bit": 16,
"description": "Random Anim Start" "description": "Random Anim Start"
}, },
{ {
"bit": "23", "bit": 23,
"description": "Is Marker" "description": "Is Marker"
} }
] ]
@@ -370,7 +370,7 @@
"name": "Eyes", "name": "Eyes",
"flags": [ "flags": [
{ {
"bit": "2", "bit": 2,
"description": "Non-Playable" "description": "Non-Playable"
} }
] ]
@@ -405,27 +405,27 @@
"name": "Furniture", "name": "Furniture",
"flags": [ "flags": [
{ {
"bit": "7", "bit": 7,
"description": "Is Perch" "description": "Is Perch"
}, },
{ {
"bit": "15", "bit": 15,
"description": "Has Distant LOD" "description": "Has Distant LOD"
}, },
{ {
"bit": "16", "bit": 16,
"description": "Random Anim Start" "description": "Random Anim Start"
}, },
{ {
"bit": "23", "bit": 23,
"description": "Is Marker" "description": "Is Marker"
}, },
{ {
"bit": "28", "bit": 28,
"description": "Must Exit To Talk" "description": "Must Exit To Talk"
}, },
{ {
"bit": "29", "bit": 29,
"description": "Child Can Use" "description": "Child Can Use"
} }
] ]
@@ -435,7 +435,7 @@
"name": "Global", "name": "Global",
"flags": [ "flags": [
{ {
"bit": "6", "bit": 6,
"description": "Constant" "description": "Constant"
} }
] ]
@@ -465,7 +465,7 @@
"name": "Head Part", "name": "Head Part",
"flags": [ "flags": [
{ {
"bit": "2", "bit": 2,
"description": "Non-Playable" "description": "Non-Playable"
} }
] ]
@@ -480,7 +480,7 @@
"name": "Idle Marker", "name": "Idle Marker",
"flags": [ "flags": [
{ {
"bit": "29", "bit": 29,
"description": "Child Can Use" "description": "Child Can Use"
} }
] ]
@@ -500,7 +500,7 @@
"name": "Dialog response", "name": "Dialog response",
"flags": [ "flags": [
{ {
"bit": "13", "bit": 13,
"description": "Actor Changed" "description": "Actor Changed"
} }
] ]
@@ -525,7 +525,7 @@
"name": "Key", "name": "Key",
"flags": [ "flags": [
{ {
"bit": "2", "bit": 2,
"description": "Non-Playable" "description": "Non-Playable"
} }
] ]
@@ -540,7 +540,7 @@
"name": "Landscape", "name": "Landscape",
"flags": [ "flags": [
{ {
"bit": "18", "bit": 18,
"description": "Compressed" "description": "Compressed"
} }
] ]
@@ -570,15 +570,15 @@
"name": "Light", "name": "Light",
"flags": [ "flags": [
{ {
"bit": "16", "bit": 16,
"description": "Random Anim Start" "description": "Random Anim Start"
}, },
{ {
"bit": "17", "bit": 17,
"description": "Portal-strict" "description": "Portal-strict"
}, },
{ {
"bit": "25", "bit": 25,
"description": "Obstacle" "description": "Obstacle"
} }
] ]
@@ -588,7 +588,7 @@
"name": "Load Screen", "name": "Load Screen",
"flags": [ "flags": [
{ {
"bit": "10", "bit": 10,
"description": "Displays In Main Menu" "description": "Displays In Main Menu"
} }
] ]
@@ -638,7 +638,7 @@
"name": "Misc. Item", "name": "Misc. Item",
"flags": [ "flags": [
{ {
"bit": "2", "bit": 2,
"description": "Non-Playable" "description": "Non-Playable"
} }
] ]
@@ -653,39 +653,39 @@
"name": "Moveable Static", "name": "Moveable Static",
"flags": [ "flags": [
{ {
"bit": "8", "bit": 8,
"description": "Must Update Anims" "description": "Must Update Anims"
}, },
{ {
"bit": "9", "bit": 9,
"description": "Hidden From Local Map" "description": "Hidden From Local Map"
}, },
{ {
"bit": "15", "bit": 15,
"description": "Has Distant LOD" "description": "Has Distant LOD"
}, },
{ {
"bit": "16", "bit": 16,
"description": "Random Anim Start" "description": "Random Anim Start"
}, },
{ {
"bit": "19", "bit": 19,
"description": "Has Currents" "description": "Has Currents"
}, },
{ {
"bit": "25", "bit": 25,
"description": "Obstacle" "description": "Obstacle"
}, },
{ {
"bit": "26", "bit": 26,
"description": "NavMesh Generation - Filter" "description": "NavMesh Generation - Filter"
}, },
{ {
"bit": "27", "bit": 27,
"description": "NavMesh Generation - Bounding Box" "description": "NavMesh Generation - Bounding Box"
}, },
{ {
"bit": "30", "bit": 30,
"description": "NavMesh Generation - Ground" "description": "NavMesh Generation - Ground"
} }
] ]
@@ -710,42 +710,37 @@
"name": "Navigation Mesh", "name": "Navigation Mesh",
"flags": [ "flags": [
{ {
"bit": "18", "bit": 18,
"description": "Compressed" "description": "Compressed"
}, },
{ {
"bit": "26", "bit": 26,
"description": "AutoGen" "description": "AutoGen"
}, },
{ {
"bit": "31", "bit": 31,
"description": "NavmeshGenCell" "description": "NavmeshGenCell"
} }
] ]
}, },
{
"fourcc": "NOTE",
"name": "Note",
"flags": []
},
{ {
"fourcc": "NPC_", "fourcc": "NPC_",
"name": "Non-Player Character (Actor)", "name": "Non-Player Character (Actor)",
"flags": [ "flags": [
{ {
"bit": "10", "bit": 10,
"description": "Unknown 10" "description": "Unknown 10"
}, },
{ {
"bit": "18", "bit": 18,
"description": "Compressed" "description": "Compressed"
}, },
{ {
"bit": "19", "bit": 19,
"description": "Unknown 19" "description": "Unknown 19"
}, },
{ {
"bit": "29", "bit": 29,
"description": "Bleedout Override" "description": "Bleedout Override"
} }
] ]
@@ -765,27 +760,27 @@
"name": "Placed Arrow", "name": "Placed Arrow",
"flags": [ "flags": [
{ {
"bit": "7", "bit": 7,
"description": "Turn Off Fire" "description": "Turn Off Fire"
}, },
{ {
"bit": "10", "bit": 10,
"description": "Persistent" "description": "Persistent"
}, },
{ {
"bit": "11", "bit": 11,
"description": "Initially Disabled" "description": "Initially Disabled"
}, },
{ {
"bit": "28", "bit": 28,
"description": "Reflected By Auto Water" "description": "Reflected By Auto Water"
}, },
{ {
"bit": "29", "bit": 29,
"description": "Don't Havok Settle" "description": "Don't Havok Settle"
}, },
{ {
"bit": "30", "bit": 30,
"description": "No Respawn" "description": "No Respawn"
} }
] ]
@@ -795,27 +790,27 @@
"name": "Placed Barrier", "name": "Placed Barrier",
"flags": [ "flags": [
{ {
"bit": "7", "bit": 7,
"description": "Turn Off Fire" "description": "Turn Off Fire"
}, },
{ {
"bit": "10", "bit": 10,
"description": "Persistent" "description": "Persistent"
}, },
{ {
"bit": "11", "bit": 11,
"description": "Initially Disabled" "description": "Initially Disabled"
}, },
{ {
"bit": "28", "bit": 28,
"description": "Reflected By Auto Water" "description": "Reflected By Auto Water"
}, },
{ {
"bit": "29", "bit": 29,
"description": "Don't Havok Settle" "description": "Don't Havok Settle"
}, },
{ {
"bit": "30", "bit": 30,
"description": "No Respawn" "description": "No Respawn"
} }
] ]
@@ -825,27 +820,27 @@
"name": "Placed Beam", "name": "Placed Beam",
"flags": [ "flags": [
{ {
"bit": "7", "bit": 7,
"description": "Turn Off Fire" "description": "Turn Off Fire"
}, },
{ {
"bit": "10", "bit": 10,
"description": "Persistent" "description": "Persistent"
}, },
{ {
"bit": "11", "bit": 11,
"description": "Initially Disabled" "description": "Initially Disabled"
}, },
{ {
"bit": "28", "bit": 28,
"description": "Reflected By Auto Water" "description": "Reflected By Auto Water"
}, },
{ {
"bit": "29", "bit": 29,
"description": "Don't Havok Settle" "description": "Don't Havok Settle"
}, },
{ {
"bit": "30", "bit": 30,
"description": "No Respawn" "description": "No Respawn"
} }
] ]
@@ -855,27 +850,27 @@
"name": "Placed Cone/Voice", "name": "Placed Cone/Voice",
"flags": [ "flags": [
{ {
"bit": "7", "bit": 7,
"description": "Turn Off Fire" "description": "Turn Off Fire"
}, },
{ {
"bit": "10", "bit": 10,
"description": "Persistent" "description": "Persistent"
}, },
{ {
"bit": "11", "bit": 11,
"description": "Initially Disabled" "description": "Initially Disabled"
}, },
{ {
"bit": "28", "bit": 28,
"description": "Reflected By Auto Water" "description": "Reflected By Auto Water"
}, },
{ {
"bit": "29", "bit": 29,
"description": "Don't Havok Settle" "description": "Don't Havok Settle"
}, },
{ {
"bit": "30", "bit": 30,
"description": "No Respawn" "description": "No Respawn"
} }
] ]
@@ -885,7 +880,7 @@
"name": "Perk", "name": "Perk",
"flags": [ "flags": [
{ {
"bit": "2", "bit": 2,
"description": "Non-Playable" "description": "Non-Playable"
} }
] ]
@@ -895,27 +890,27 @@
"name": "Placed Flame", "name": "Placed Flame",
"flags": [ "flags": [
{ {
"bit": "7", "bit": 7,
"description": "Turn Off Fire" "description": "Turn Off Fire"
}, },
{ {
"bit": "10", "bit": 10,
"description": "Persistent" "description": "Persistent"
}, },
{ {
"bit": "11", "bit": 11,
"description": "Initially Disabled" "description": "Initially Disabled"
}, },
{ {
"bit": "28", "bit": 28,
"description": "Reflected By Auto Water" "description": "Reflected By Auto Water"
}, },
{ {
"bit": "29", "bit": 29,
"description": "Don't Havok Settle" "description": "Don't Havok Settle"
}, },
{ {
"bit": "30", "bit": 30,
"description": "No Respawn" "description": "No Respawn"
} }
] ]
@@ -925,27 +920,27 @@
"name": "Placed Projectile", "name": "Placed Projectile",
"flags": [ "flags": [
{ {
"bit": "7", "bit": 7,
"description": "Turn Off Fire" "description": "Turn Off Fire"
}, },
{ {
"bit": "10", "bit": 10,
"description": "Persistent" "description": "Persistent"
}, },
{ {
"bit": "11", "bit": 11,
"description": "Initially Disabled" "description": "Initially Disabled"
}, },
{ {
"bit": "28", "bit": 28,
"description": "Reflected By Auto Water" "description": "Reflected By Auto Water"
}, },
{ {
"bit": "29", "bit": 29,
"description": "Don't Havok Settle" "description": "Don't Havok Settle"
}, },
{ {
"bit": "30", "bit": 30,
"description": "No Respawn" "description": "No Respawn"
} }
] ]
@@ -955,27 +950,27 @@
"name": "Placed Hazard", "name": "Placed Hazard",
"flags": [ "flags": [
{ {
"bit": "7", "bit": 7,
"description": "Turn Off Fire" "description": "Turn Off Fire"
}, },
{ {
"bit": "10", "bit": 10,
"description": "Persistent" "description": "Persistent"
}, },
{ {
"bit": "11", "bit": 11,
"description": "Initially Disabled" "description": "Initially Disabled"
}, },
{ {
"bit": "28", "bit": 28,
"description": "Reflected By Auto Water" "description": "Reflected By Auto Water"
}, },
{ {
"bit": "29", "bit": 29,
"description": "Don't Havok Settle" "description": "Don't Havok Settle"
}, },
{ {
"bit": "30", "bit": 30,
"description": "No Respawn" "description": "No Respawn"
} }
] ]
@@ -990,27 +985,27 @@
"name": "Placed Missile", "name": "Placed Missile",
"flags": [ "flags": [
{ {
"bit": "7", "bit": 7,
"description": "Turn Off Fire" "description": "Turn Off Fire"
}, },
{ {
"bit": "10", "bit": 10,
"description": "Persistent" "description": "Persistent"
}, },
{ {
"bit": "11", "bit": 11,
"description": "Initially Disabled" "description": "Initially Disabled"
}, },
{ {
"bit": "28", "bit": 28,
"description": "Reflected By Auto Water" "description": "Reflected By Auto Water"
}, },
{ {
"bit": "29", "bit": 29,
"description": "Don't Havok Settle" "description": "Don't Havok Settle"
}, },
{ {
"bit": "30", "bit": 30,
"description": "No Respawn" "description": "No Respawn"
} }
] ]
@@ -1035,7 +1030,7 @@
"name": "Race", "name": "Race",
"flags": [ "flags": [
{ {
"bit": "19", "bit": 19,
"description": "Critter?" "description": "Critter?"
} }
] ]
@@ -1045,35 +1040,35 @@
"name": "Placed Object", "name": "Placed Object",
"flags": [ "flags": [
{ {
"bit": "10", "bit": 10,
"description": "Persistent" "description": "Persistent"
}, },
{ {
"bit": "11", "bit": 11,
"description": "Initially Disabled" "description": "Initially Disabled"
}, },
{ {
"bit": "16", "bit": 16,
"description": "Is Full LOD" "description": "Is Full LOD"
}, },
{ {
"bit": "26", "bit": 26,
"description": "Filter (Collision Geometry)" "description": "Filter (Collision Geometry)"
}, },
{ {
"bit": "27", "bit": 27,
"description": "Bounding Box (Collision Geometry)" "description": "Bounding Box (Collision Geometry)"
}, },
{ {
"bit": "28", "bit": 28,
"description": "Reflected By Auto Water" "description": "Reflected By Auto Water"
}, },
{ {
"bit": "30", "bit": 30,
"description": "Ground" "description": "Ground"
}, },
{ {
"bit": "31", "bit": 31,
"description": "Multibound" "description": "Multibound"
} }
] ]
@@ -1083,7 +1078,7 @@
"name": "Region", "name": "Region",
"flags": [ "flags": [
{ {
"bit": "6", "bit": 6,
"description": "Border Region" "description": "Border Region"
} }
] ]
@@ -1093,7 +1088,7 @@
"name": "Relationship", "name": "Relationship",
"flags": [ "flags": [
{ {
"bit": "6", "bit": 6,
"description": "Secret" "description": "Secret"
} }
] ]
@@ -1138,7 +1133,7 @@
"name": "Shout", "name": "Shout",
"flags": [ "flags": [
{ {
"bit": "7", "bit": 7,
"description": "Treat spells as powers" "description": "Treat spells as powers"
} }
] ]
@@ -1148,7 +1143,7 @@
"name": "Soul Gem", "name": "Soul Gem",
"flags": [ "flags": [
{ {
"bit": "17", "bit": 17,
"description": "Can Hold NPC Soul" "description": "Can Hold NPC Soul"
} }
] ]
@@ -1273,15 +1268,15 @@
"name": "Talking Activator", "name": "Talking Activator",
"flags": [ "flags": [
{ {
"bit": "9", "bit": 9,
"description": "Hidden From Local Map" "description": "Hidden From Local Map"
}, },
{ {
"bit": "16", "bit": 16,
"description": "Random Anim Start" "description": "Random Anim Start"
}, },
{ {
"bit": "17", "bit": 17,
"description": "Radio Station" "description": "Radio Station"
} }
] ]
@@ -1291,39 +1286,39 @@
"name": "Main File Header", "name": "Main File Header",
"flags": [ "flags": [
{ {
"bit": "0", "bit": 0,
"description": "ESM" "description": "ESM"
}, },
{ {
"bit": "1", "bit": 1,
"description": "Altered" "description": "Altered"
}, },
{ {
"bit": "2", "bit": 2,
"description": "Checked" "description": "Checked"
}, },
{ {
"bit": "3", "bit": 3,
"description": "Active" "description": "Active"
}, },
{ {
"bit": "4", "bit": 4,
"description": "Optimized File" "description": "Optimized File"
}, },
{ {
"bit": "5", "bit": 5,
"description": "Temp ID Owner" "description": "Temp ID Owner"
}, },
{ {
"bit": "7", "bit": 7,
"description": "Localized" "description": "Localized"
}, },
{ {
"bit": "8", "bit": 8,
"description": "Precalc Data Only" "description": "Precalc Data Only"
}, },
{ {
"bit": "9", "bit": 9,
"description": "ESL" "description": "ESL"
} }
] ]
@@ -1333,7 +1328,7 @@
"name": "Tree", "name": "Tree",
"flags": [ "flags": [
{ {
"bit": "15", "bit": 15,
"description": "Has Distant LOD" "description": "Has Distant LOD"
} }
] ]
@@ -1363,7 +1358,7 @@
"name": "Weapon", "name": "Weapon",
"flags": [ "flags": [
{ {
"bit": "2", "bit": 2,
"description": "Non-Playable" "description": "Non-Playable"
} }
] ]
@@ -1378,7 +1373,7 @@
"name": "Worldspace", "name": "Worldspace",
"flags": [ "flags": [
{ {
"bit": "19", "bit": 19,
"description": "Can't Wait" "description": "Can't Wait"
} }
] ]

View File

@@ -0,0 +1,90 @@
import os
import re
import json
from dataclasses import dataclass
# helper used when dumping the records to JSON
class Jsonify:
def encode(self, value=None):
if not value:
value = self.__dict__
return value
# Record model
@dataclass
class Flag(Jsonify):
bit: int
description: str
@dataclass
class Record(Jsonify):
fourcc: str
flags: list[Flag]
# open and read the records from xEdit source
fdir = os.path.dirname(__file__)
with open(os.path.join(fdir, "TES5Edit/Core/wbDefinitionsTES5.pas"), "r") as f:
inp = f.read()
# find the REFR flags decider
decider = re.findall("function wbREFRRecordFlagsDecider.*?\n(?:.*?\n)+?end;", inp)
assert len(decider) == 1, "Could not uniquely match wbREFRRecordFlagsDecider."
decider = decider[0]
# get decider sections
sections = re.findall("if\s*?[\\(]?MainRecord.Signature.*?then\s*?Result.*?\n", decider, flags = re.DOTALL)
# for each section get signatures and index
sig_to_index = {}
index_re = re.compile("Result := (\d.*?)")
sig_re = re.compile("MainRecord.Signature = (\w{4})")
for s in sections:
index = index_re.findall(s)
assert len(index) == 1, "Could not parse REFR decider index"
index = int(index[0]) - 1
sigs = sig_re.findall(s)
for sig in sigs:
sig_to_index[sig] = index
# get the REFR record
refr = re.findall("wbRefRecord\((REFR.*?\n(?:.*?\n)*?.*?)\);", inp)
assert len(refr) == 1, "Could not find REFR record"
refr = refr[0]
# get all of the flag lists
flag_lists = re.findall("wbFlagsList\\(\\[.*?\n((?:.*?\n)*?).*?\\]", refr)[1:]
assert len(flag_lists) - 1 == max(sig_to_index.values()), "Could not match decider indices with flag lists."
# process flag lists into flags
index_to_flag_list = {}
re_flag_line = re.compile(".*?(\d+?),.*?'(.*)'")
for index, flist in enumerate(flag_lists):
flags = []
for line in flist.strip().split('\n'):
match = re_flag_line.match(line).groups()
assert len(match) == 2, "Could not parse flag line."
flags += [Flag(int(match[0]), match[1])]
index_to_flag_list[index] = flags
# create list of records
records = []
for sig, index in sig_to_index.items():
records += [Record(sig, index_to_flag_list[index])]
# sort the records by signature
records = sorted(records, key=lambda x: x.fourcc)
# write the records out to a JSON file
class Encoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, Jsonify):
return obj.encode()
else:
return json.JSONEncoder.default(self, obj)
with open(os.path.join(fdir, "refr_flags.json"), "w") as f:
json.dump(records, f, cls=Encoder, indent=4)

805
reference/refr_flags.json Normal file
View File

@@ -0,0 +1,805 @@
[
{
"fourcc": "ACTI",
"flags": [
{
"bit": 9,
"description": "Hidden From Local Map"
},
{
"bit": 10,
"description": "Persistent"
},
{
"bit": 11,
"description": "Initially Disabled"
},
{
"bit": 13,
"description": "Sky Marker"
},
{
"bit": 15,
"description": "Visible when distant"
},
{
"bit": 16,
"description": "Is Full LOD"
},
{
"bit": 26,
"description": "Filter (Collision Geometry)"
},
{
"bit": 27,
"description": "Bounding Box (Collision Geometry)"
},
{
"bit": 28,
"description": "Reflected By Auto Water"
},
{
"bit": 29,
"description": "Don''t Havok Settle"
},
{
"bit": 30,
"description": "No Respawn"
},
{
"bit": 31,
"description": "Multibound"
}
]
},
{
"fourcc": "ADDN",
"flags": [
{
"bit": 10,
"description": "Persistent"
},
{
"bit": 11,
"description": "Initially Disabled"
},
{
"bit": 16,
"description": "Is Full LOD"
},
{
"bit": 28,
"description": "Reflected By Auto Water"
},
{
"bit": 29,
"description": "Don''t Havok Settle"
},
{
"bit": 30,
"description": "No Respawn"
},
{
"bit": 31,
"description": "Multibound"
}
]
},
{
"fourcc": "ALCH",
"flags": [
{
"bit": 10,
"description": "Persistent"
},
{
"bit": 11,
"description": "Initially Disabled"
},
{
"bit": 16,
"description": "Is Full LOD"
},
{
"bit": 25,
"description": "No AI Acquire"
},
{
"bit": 28,
"description": "Reflected By Auto Water"
},
{
"bit": 29,
"description": "Don''t Havok Settle"
},
{
"bit": 30,
"description": "No Respawn"
},
{
"bit": 31,
"description": "Multibound"
}
]
},
{
"fourcc": "AMMO",
"flags": [
{
"bit": 10,
"description": "Persistent"
},
{
"bit": 11,
"description": "Initially Disabled"
},
{
"bit": 16,
"description": "Is Full LOD"
},
{
"bit": 25,
"description": "No AI Acquire"
},
{
"bit": 28,
"description": "Reflected By Auto Water"
},
{
"bit": 29,
"description": "Don''t Havok Settle"
},
{
"bit": 30,
"description": "No Respawn"
},
{
"bit": 31,
"description": "Multibound"
}
]
},
{
"fourcc": "ARMO",
"flags": [
{
"bit": 10,
"description": "Persistent"
},
{
"bit": 11,
"description": "Initially Disabled"
},
{
"bit": 16,
"description": "Is Full LOD"
},
{
"bit": 25,
"description": "No AI Acquire"
},
{
"bit": 28,
"description": "Reflected By Auto Water"
},
{
"bit": 29,
"description": "Don''t Havok Settle"
},
{
"bit": 30,
"description": "No Respawn"
},
{
"bit": 31,
"description": "Multibound"
}
]
},
{
"fourcc": "BOOK",
"flags": [
{
"bit": 10,
"description": "Persistent"
},
{
"bit": 11,
"description": "Initially Disabled"
},
{
"bit": 16,
"description": "Is Full LOD"
},
{
"bit": 25,
"description": "No AI Acquire"
},
{
"bit": 28,
"description": "Reflected By Auto Water"
},
{
"bit": 29,
"description": "Don''t Havok Settle"
},
{
"bit": 30,
"description": "No Respawn"
},
{
"bit": 31,
"description": "Multibound"
}
]
},
{
"fourcc": "CONT",
"flags": [
{
"bit": 10,
"description": "Persistent"
},
{
"bit": 11,
"description": "Initially Disabled"
},
{
"bit": 16,
"description": "Is Full LOD"
},
{
"bit": 25,
"description": "No AI Acquire"
},
{
"bit": 26,
"description": "Filter (Collision Geometry)"
},
{
"bit": 27,
"description": "Bounding Box (Collision Geometry)"
},
{
"bit": 28,
"description": "Reflected By Auto Water"
},
{
"bit": 29,
"description": "Don''t Havok Settle"
},
{
"bit": 30,
"description": "Ground"
},
{
"bit": 31,
"description": "Multibound"
}
]
},
{
"fourcc": "DOOR",
"flags": [
{
"bit": 6,
"description": "Hidden From Local Map"
},
{
"bit": 8,
"description": "Inaccessible"
},
{
"bit": 10,
"description": "Persistent"
},
{
"bit": 11,
"description": "Initially Disabled"
},
{
"bit": 16,
"description": "Is Full LOD"
},
{
"bit": 26,
"description": "Filter (Collision Geometry)"
},
{
"bit": 27,
"description": "Bounding Box (Collision Geometry)"
},
{
"bit": 28,
"description": "Reflected By Auto Water"
},
{
"bit": 29,
"description": "Don''t Havok Settle"
},
{
"bit": 30,
"description": "No Respawn"
},
{
"bit": 31,
"description": "Multibound"
}
]
},
{
"fourcc": "FLOR",
"flags": [
{
"bit": 9,
"description": "Hidden From Local Map"
},
{
"bit": 10,
"description": "Persistent"
},
{
"bit": 11,
"description": "Initially Disabled"
},
{
"bit": 13,
"description": "Sky Marker"
},
{
"bit": 15,
"description": "Visible when distant"
},
{
"bit": 16,
"description": "Is Full LOD"
},
{
"bit": 26,
"description": "Filter (Collision Geometry)"
},
{
"bit": 27,
"description": "Bounding Box (Collision Geometry)"
},
{
"bit": 28,
"description": "Reflected By Auto Water"
},
{
"bit": 29,
"description": "Don''t Havok Settle"
},
{
"bit": 30,
"description": "No Respawn"
},
{
"bit": 31,
"description": "Multibound"
}
]
},
{
"fourcc": "INGR",
"flags": [
{
"bit": 10,
"description": "Persistent"
},
{
"bit": 11,
"description": "Initially Disabled"
},
{
"bit": 16,
"description": "Is Full LOD"
},
{
"bit": 25,
"description": "No AI Acquire"
},
{
"bit": 28,
"description": "Reflected By Auto Water"
},
{
"bit": 29,
"description": "Don''t Havok Settle"
},
{
"bit": 30,
"description": "No Respawn"
},
{
"bit": 31,
"description": "Multibound"
}
]
},
{
"fourcc": "KEYM",
"flags": [
{
"bit": 10,
"description": "Persistent"
},
{
"bit": 11,
"description": "Initially Disabled"
},
{
"bit": 16,
"description": "Is Full LOD"
},
{
"bit": 25,
"description": "No AI Acquire"
},
{
"bit": 28,
"description": "Reflected By Auto Water"
},
{
"bit": 29,
"description": "Don''t Havok Settle"
},
{
"bit": 30,
"description": "No Respawn"
},
{
"bit": 31,
"description": "Multibound"
}
]
},
{
"fourcc": "LIGH",
"flags": [
{
"bit": 8,
"description": "Doesn''t Light Water"
},
{
"bit": 9,
"description": "Casts Shadows"
},
{
"bit": 10,
"description": "Persistent"
},
{
"bit": 11,
"description": "Initially Disabled"
},
{
"bit": 16,
"description": "Never Fades"
},
{
"bit": 17,
"description": "Doesn''t Light Landscape"
},
{
"bit": 25,
"description": "No AI Acquire"
},
{
"bit": 28,
"description": "Reflected By Auto Water"
},
{
"bit": 29,
"description": "Don''t Havok Settle"
},
{
"bit": 30,
"description": "No Respawn"
},
{
"bit": 31,
"description": "Multibound"
}
]
},
{
"fourcc": "MISC",
"flags": [
{
"bit": 10,
"description": "Persistent"
},
{
"bit": 11,
"description": "Initially Disabled"
},
{
"bit": 16,
"description": "Is Full LOD"
},
{
"bit": 25,
"description": "No AI Acquire"
},
{
"bit": 28,
"description": "Reflected By Auto Water"
},
{
"bit": 29,
"description": "Don''t Havok Settle"
},
{
"bit": 30,
"description": "No Respawn"
},
{
"bit": 31,
"description": "Multibound"
}
]
},
{
"fourcc": "MSTT",
"flags": [
{
"bit": 9,
"description": "Motion Blur"
},
{
"bit": 10,
"description": "Persistent"
},
{
"bit": 11,
"description": "Initially Disabled"
},
{
"bit": 16,
"description": "Is Full LOD"
},
{
"bit": 26,
"description": "Filter (Collision Geometry)"
},
{
"bit": 27,
"description": "Bounding Box (Collision Geometry)"
},
{
"bit": 28,
"description": "Reflected By Auto Water"
},
{
"bit": 29,
"description": "Don''t Havok Settle"
},
{
"bit": 30,
"description": "No Respawn"
},
{
"bit": 31,
"description": "Multibound"
}
]
},
{
"fourcc": "SCRL",
"flags": [
{
"bit": 10,
"description": "Persistent"
},
{
"bit": 11,
"description": "Initially Disabled"
},
{
"bit": 16,
"description": "Is Full LOD"
},
{
"bit": 25,
"description": "No AI Acquire"
},
{
"bit": 28,
"description": "Reflected By Auto Water"
},
{
"bit": 29,
"description": "Don''t Havok Settle"
},
{
"bit": 30,
"description": "No Respawn"
},
{
"bit": 31,
"description": "Multibound"
}
]
},
{
"fourcc": "SLGM",
"flags": [
{
"bit": 10,
"description": "Persistent"
},
{
"bit": 11,
"description": "Initially Disabled"
},
{
"bit": 16,
"description": "Is Full LOD"
},
{
"bit": 25,
"description": "No AI Acquire"
},
{
"bit": 28,
"description": "Reflected By Auto Water"
},
{
"bit": 29,
"description": "Don''t Havok Settle"
},
{
"bit": 30,
"description": "No Respawn"
},
{
"bit": 31,
"description": "Multibound"
}
]
},
{
"fourcc": "STAT",
"flags": [
{
"bit": 9,
"description": "Hidden From Local Map"
},
{
"bit": 10,
"description": "Persistent"
},
{
"bit": 11,
"description": "Initially Disabled"
},
{
"bit": 13,
"description": "Sky Marker"
},
{
"bit": 15,
"description": "Visible when distant"
},
{
"bit": 16,
"description": "Is Full LOD"
},
{
"bit": 26,
"description": "Filter (Collision Geometry)"
},
{
"bit": 27,
"description": "Bounding Box (Collision Geometry)"
},
{
"bit": 28,
"description": "Reflected By Auto Water"
},
{
"bit": 29,
"description": "Don''t Havok Settle"
},
{
"bit": 30,
"description": "No Respawn"
},
{
"bit": 31,
"description": "Multibound"
}
]
},
{
"fourcc": "TREE",
"flags": [
{
"bit": 9,
"description": "Hidden From Local Map"
},
{
"bit": 10,
"description": "Persistent"
},
{
"bit": 11,
"description": "Initially Disabled"
},
{
"bit": 13,
"description": "Sky Marker"
},
{
"bit": 15,
"description": "Visible when distant"
},
{
"bit": 16,
"description": "Is Full LOD"
},
{
"bit": 26,
"description": "Filter (Collision Geometry)"
},
{
"bit": 27,
"description": "Bounding Box (Collision Geometry)"
},
{
"bit": 28,
"description": "Reflected By Auto Water"
},
{
"bit": 29,
"description": "Don''t Havok Settle"
},
{
"bit": 30,
"description": "No Respawn"
},
{
"bit": 31,
"description": "Multibound"
}
]
},
{
"fourcc": "WEAP",
"flags": [
{
"bit": 10,
"description": "Persistent"
},
{
"bit": 11,
"description": "Initially Disabled"
},
{
"bit": 16,
"description": "Is Full LOD"
},
{
"bit": 25,
"description": "No AI Acquire"
},
{
"bit": 28,
"description": "Reflected By Auto Water"
},
{
"bit": 29,
"description": "Don''t Havok Settle"
},
{
"bit": 30,
"description": "No Respawn"
},
{
"bit": 31,
"description": "Multibound"
}
]
}
]