From c4e42dea25dd4f1f87f36fd2fc3e4f5f19c21644 Mon Sep 17 00:00:00 2001 From: lzwdgc Date: Tue, 2 Apr 2024 18:13:48 +0300 Subject: [PATCH] [mod] Allow to copy gliders from aim2. --- examples/mods/aim1_community_fix/my_mod.cpp | 17 +++- src/aim1_mod_maker/aim1_mod_maker.h | 93 +++++++++++++-------- 2 files changed, 74 insertions(+), 36 deletions(-) diff --git a/examples/mods/aim1_community_fix/my_mod.cpp b/examples/mods/aim1_community_fix/my_mod.cpp index 7fbbca0..383f426 100644 --- a/examples/mods/aim1_community_fix/my_mod.cpp +++ b/examples/mods/aim1_community_fix/my_mod.cpp @@ -136,7 +136,6 @@ int main(int argc, char *argv[]) { // patch note: DB auto db = mod.db(); // patch note: set glider GL_S3_PS_FINDER2 model to MOD_GL_S3_PS_FINDER2 (lz) - // patch note - maybe copy from finder1?: change MOD_GL_S3_PS_FINDER2 model radius to MOD_GL_S3_PS_FINDER1 radius (lz) db[u8"Глайдеры"]["GL_S3_PS_FINDER2"]["MODEL"] = "MOD_GL_S3_PS_FINDER2"; // patch note: copy MOD_GL_S3_PS_FINDER2 model from aim2 (lz) // patch note: copy MOD_GL_S3_PS_FINDER2 textures data from aim2 (lz) @@ -161,6 +160,10 @@ int main(int argc, char *argv[]) { tblcfg["CFG_EYEDSTONE_1"]["LIGHTGUN1"] = "GUN_FAST_ELECTROMAGNETIC_BEAM"; // patch note: double gun for config CFG_EYEDSTONE_2: from GUN_FAST_ELECTROMAGNETIC_BEAM to double GUN_FAST_ELECTROMAGNETIC_BEAM (lz) tblcfg["CFG_EYEDSTONE_2"]["LIGHTGUN1"] = "GUN_FAST_ELECTROMAGNETIC_BEAM"; + // end of db changes +#ifdef NDEBUG + db.write(); +#endif // patch note: INFORMATION { auto quest = mod.quest("ru_RU"); @@ -202,6 +205,17 @@ int main(int argc, char *argv[]) { db[u8"Оборудование"]["EQP_ION_DRIVE_S1"]["VALUE1"] = 4158000.f; // patch note dev: make EQP_VACUUM_DRIVE_S4 more powerful db[u8"Оборудование"]["EQP_VACUUM_DRIVE_S4"]["VALUE1"] = 4158000.f; + // end of db changes in dev mode + db.write(); + // patch note dev: copy gliders from m2: GL_M4_C_MASTODON, GL_M4_S_FLASH, GL_M4_A_FORWARD, GL_M4_A_FORWARD_BLACK + auto add_glider = [&, after = "GL_M1_A_ATTACKER"s](auto &&name) mutable { + mod.copy_glider_from_aim2(name); + after = mod.add_map_good("location1.mmo", "B_L1_BASE1", after, mmo_storage2::map_good(name)); + }; + add_glider("GL_M4_C_MASTODON"); + add_glider("GL_M4_A_FORWARD"); + add_glider("GL_M4_A_FORWARD_BLACK"); + add_glider("GL_M4_S_FLASH"); // patch note dev: start money, rating, glider and sector access mod.replace("Script/bin/B_L1_BASE1.scr", "_ADDBALANCE(300)", R"( _ADDBALANCE(300 ) @@ -253,7 +267,6 @@ int main(int argc, char *argv[]) { // patch note: lz // patch note: // patch note: Have fun! - db.write(); mod.apply(); // patch note: diff --git a/src/aim1_mod_maker/aim1_mod_maker.h b/src/aim1_mod_maker/aim1_mod_maker.h index ed018f1..1427f5b 100644 --- a/src/aim1_mod_maker/aim1_mod_maker.h +++ b/src/aim1_mod_maker/aim1_mod_maker.h @@ -138,6 +138,7 @@ struct mod_maker { std::set files_to_pak; std::set files_to_distribute; std::set code_files_to_distribute; + std::set restored_files; std::source_location loc; mod_maker(std::source_location loc = std::source_location::current()) : loc{loc} { @@ -278,9 +279,10 @@ struct mod_maker { write_file(get_hash_fn(fn, data), ""s); } - void add_map_good(path mmo_fn, const std::string &building_name, const std::string &after_good_name, const mmo_storage2::map_good &mg) { + std::string add_map_good(path mmo_fn, const std::string &building_name, const std::string &after_good_name, const mmo_storage2::map_good &mg) { byte_array data((uint8_t*)&mg, (uint8_t*)&mg + sizeof(mg)); add_map_good(mmo_fn, building_name, after_good_name, data); + return mg.name; } void add_map_good(path mmo_fn, const std::string &building_name, const std::string &after_good_name, const byte_array &data) { files_to_pak.insert(find_real_filename(mmo_fn)); @@ -362,28 +364,6 @@ struct mod_maker { fn = find_real_filename(fn); files_to_pak.insert(fn); } - - auto db() { - auto w = open_db("db", 1251); // always 1251 probably - if (aim2_available()) { - w.m2_ = &open_aim2_db(); - } - return w; - } - auto quest(const std::string &language = {}) { - // TODO: check if it's possible to use utf8/16 in aim game - // set codepages here until we fix or implement unicode - int db_codepage = 1251; - if (language == "fr_fr") { - // change cp. Also for other langs - } - if (language.empty()) { - return open_db("quest", db_codepage); - } else { - return open_db("quest_" + language, db_codepage); - } - } - void setup_aim2_path() { try { aim2_game_dir = read_file(game_dir / "aim2_path.txt"); @@ -394,13 +374,13 @@ struct mod_maker { throw std::runtime_error{"aim2 path is not a directory"}; } } catch (std::exception &e) { - throw std::runtime_error{std::format( - "Can't read aim2_path.\n" - "Create aim2_path.txt near your aim.exe and write down aim2 path there.\n" - "Error: {}", e.what())}; + throw std::runtime_error{ + std::format("Can't read aim2_path.\n" + "Create aim2_path.txt near your aim.exe and write down aim2 path there.\n" + "Error: {}", + e.what())}; } } - void copy_from_aim2(auto &&object) { log("copying from aim2: {}", path{object}.filename().string()); @@ -421,7 +401,7 @@ struct mod_maker { } } // TODO: this - fix add_resource()/find_real_filename() - //auto copied_fn = get_mod_dir() / object; + // auto copied_fn = get_mod_dir() / object; auto copied_fn = get_data_dir() / object; fs::copy_file(p, copied_fn, fs::copy_options::overwrite_existing); run_p4_tool("mod_converter2", copied_fn); @@ -464,6 +444,40 @@ struct mod_maker { SW_UNIMPLEMENTED; } } + void copy_glider_from_aim2(auto &&object) { + copy_from_aim2("MOD_"s + object); + db().copy_from_aim2(u8"Глайдеры", path{object}.stem().string()); + quest("ru_RU").copy_from_aim2("INFORMATION", path{object}.stem().string()); + } + + auto db() { + auto w = open_db("db", 1251); // always 1251 probably + if (aim2_available()) { + w.m2_ = &open_aim2_db(); + } + return w; + } + auto quest(const std::string &language = {}) { + // TODO: check if it's possible to use utf8/16 in aim game + // set codepages here until we fix or implement unicode + int db_codepage = 1251; + if (language == "fr_fr") { + // change cp. Also for other langs + } + if (language.empty()) { + auto w = open_db("quest", db_codepage); + if (aim2_available()) { + w.m2_ = &open_aim2_quest(); + } + return w; + } else { + auto w = open_db("quest_" + language, db_codepage); + if (aim2_available()) { + w.m2_ = &open_aim2_quest(); + } + return w; + } + } private: db2::files::db2_internal &open_aim2_db() { @@ -473,10 +487,17 @@ private: static auto m2 = db2{aim2_game_dir / "data" / "db", 1251}.open().to_map(); return m2; } + db2::files::db2_internal &open_aim2_quest() { + if (!aim2_available()) { + throw std::runtime_error{"aim2 is not available, setup it first"}; + } + static auto m2 = db2{aim2_game_dir / "data" / "quest", 1251}.open().to_map(); + return m2; + } bool aim2_available() const { return !aim2_game_dir.empty(); } - path make_bak_file(const path &fn) { + static path make_bak_file(const path &fn) { auto backup = path{fn} += ".bak"; if (!fs::exists(backup)) { fs::copy_file(fn, backup); @@ -487,10 +508,7 @@ private: auto d = db2{get_data_dir() / name, db_codepage}; auto files = d.open().get_files(); for (auto &&f : files) { - auto bak = make_bak_file(f); - if (fs::exists(bak)) { - fs::copy_file(bak, f, fs::copy_options::overwrite_existing); - } + backup_or_restore_once(f); files_to_distribute.insert(f); } db_wrapper w; @@ -499,6 +517,13 @@ private: w.codepage = d.codepage; return w; } + void backup_or_restore_once(const path &fn) { + auto bak = make_bak_file(fn); + if (fs::exists(bak) && !restored_files.contains(fn)) { + fs::copy_file(bak, fn, fs::copy_options::overwrite_existing); + restored_files.insert(fn); + } + } path get_hash_fn(path fn, const byte_array &data) const { return get_mod_dir() / std::format("{:0X}.hash", get_insert_hash(fn, data)); }