// .msm HairData: SourceSkin -> TargetSkin recolour catalogue (PARITY ยง2.4). #include #include #include int main() { // Shape of assets/root/msm/warrior_m.msm HairData. const std::string text = R"( ScriptType RaceDataScript BaseModelFileName "d:/ymir work/pc2/warrior/warrior_novice.GR2" Group HairData { PathName "d:/ymir Work/pc2/warrior/" HairDataCount 3 Group HairData00 { HairIndex 0 Model "hair/hair_1_1.gr2" SourceSkin "hair/hair_1_1.dds" TargetSkin "warrior_hair_01.dds" } Group HairData01 { HairIndex 3 Model "hair/hair_1_1.gr2" SourceSkin "hair/hair_1_1.dds" TargetSkin "warrior_hair_01_red.dds" } Group HairData02 { HairIndex 1001 Model "hair/hair_2_1.gr2" SourceSkin "hair/hair_2_1.dds" TargetSkin "warrior_hair_02_gold.dds" } } )"; fmt::Msm m; std::string err; if (!fmt::parse_msm(text, m, &err)) { std::fprintf(stderr, "parse failed: %s\n", err.c_str()); return 1; } int fails = 0; auto check = [&](bool c, const char *msg) { if (!c) { std::fprintf(stderr, "FAIL: %s\n", msg); ++fails; } }; check(m.base_model_gr2 == "d:/ymir work/pc2/warrior/warrior_novice.GR2" || m.base_model_gr2 == "d:/ymir work/pc2/warrior/warrior_novice.gr2", "base model gr2"); check(m.hair_path == "d:/ymir Work/pc2/warrior/" || m.hair_path == "d:/ymir work/pc2/warrior/", "hair PathName"); check(m.hairs.size() == 3, "3 hair entries"); if (m.hairs.size() == 3) { check(m.hairs[0].index == 0, "entry0 HairIndex"); check(m.hairs[0].model == "hair/hair_1_1.gr2", "entry0 Model"); check(m.hairs[0].source_skin == "hair/hair_1_1.dds", "entry0 SourceSkin"); check(m.hairs[0].target_skin == "warrior_hair_01.dds", "entry0 TargetSkin"); // same gr2 + SourceSkin, different TargetSkin -> the recolour case check(m.hairs[1].model == m.hairs[0].model, "entry1 shares gr2"); check(m.hairs[1].source_skin == m.hairs[0].source_skin, "entry1 shares SourceSkin"); check(m.hairs[1].target_skin == "warrior_hair_01_red.dds", "entry1 TargetSkin differs"); check(m.hairs[1].index == 3, "entry1 HairIndex"); check(m.hairs[2].model == "hair/hair_2_1.gr2", "entry2 Model"); check(m.hairs[2].target_skin == "warrior_hair_02_gold.dds", "entry2 TargetSkin"); } if (fails) { std::fprintf(stderr, "%d check(s) failed\n", fails); return 1; } std::printf("all checks passed\n"); return 0; }