diff --git a/examples/mods/aim1_community_fix/my_mod.cpp b/examples/mods/aim1_community_fix/my_mod.cpp index eb41774..529d07c 100644 --- a/examples/mods/aim1_community_fix/my_mod.cpp +++ b/examples/mods/aim1_community_fix/my_mod.cpp @@ -238,26 +238,44 @@ int main(int argc, char *argv[]) { for (auto &&[n,_] : db["Глайдеры"]) { m2_gliders.erase(n); } - for (auto &&[n, _] : m2_gliders) { - mod.copy_glider_from_aim2(n); - } + //mod.copy_glider_from_aim2("GL_M4_S_FLASH"); + //m2_gliders.erase("GL_M4_S_FLASH"); + //for (auto &&[n, _] : m2_gliders) { + // mod.copy_glider_from_aim2(n); + //} std::string after; for (after = "GL_M1_A_ATTACKER"s; auto &&[n, _] : db["Глайдеры"]) { - after = mod.add_map_good("location1.mmo", "B_L1_BASE1", after, mmo_storage2::map_good(n)); + //after = mod.add_map_good("location1.mmo", "B_L1_BASE1", after, mmo_storage2::map_good(n)); } for (after = "GUN_RAY_LAZER"s; auto &&[n, _] : db["Оружие"]) { - after = mod.add_map_good("location1.mmo", "B_L1_BASE1", after, mmo_storage2::map_good(n)); + //after = mod.add_map_good("location1.mmo", "B_L1_BASE1", after, mmo_storage2::map_good(n)); } // patch note dev: copy GUN_DRAINER and GUN_GRAVITON from AIM2. They crash frequently while in F2 mode. Some does not have fx. // TODO: check in debug why they crash - mod.copy_weapon_from_aim2("GUN_DRAINER"); - after = mod.add_map_good("location1.mmo", "B_L1_BASE1", after, mmo_storage2::map_good("GUN_DRAINER")); - mod.copy_weapon_from_aim2("GUN_GRAVITON"); - after = mod.add_map_good("location1.mmo", "B_L1_BASE1", after, mmo_storage2::map_good("GUN_GRAVITON")); + //mod.copy_weapon_from_aim2("GUN_DRAINER"); + //after = mod.add_map_good("location1.mmo", "B_L1_BASE1", after, mmo_storage2::map_good("GUN_DRAINER")); + //mod.copy_weapon_from_aim2("GUN_GRAVITON"); + //after = mod.add_map_good("location1.mmo", "B_L1_BASE1", after, mmo_storage2::map_good("GUN_GRAVITON")); // mod.replace("under.scr", "_ADDSENSOR(T_L4_BASE_2)", "_ADDSENSOR(T_L4_BASE_2 )\n_MARK(T_L4_BASE_2)"); + // + mod.clone_mechmind_group("location1.mmo", "MINVACH-6", "MINVACH-666"); + mod.update_mechmind_group_configurations("location1.mmo", "MINVACH-666", + "CFG_INVADER_1", + "CFG_INVADER_1", + "CFG_INVADER_1", + "CFG_INVADER_1", + "CFG_INVADER_1", + "CFG_INVADER_1", + "CFG_INVADER_1", + "CFG_INVADER_1", + "CFG_INVADER_1", + "CFG_INVADER_1" + ); + mod.set_mechmind_organization("location1.mmo", "MINVACH-666", "ORG_PLAYER"); + // does not work, crashes. Maybe different item size // or maybe too many goods /*for (auto after = "EQP_POLYMER_ARMOR_S1"s; auto &&[n, _] : db["Оборудование"]) { diff --git a/src/aim1_mod_maker/aim1_mod_maker.h b/src/aim1_mod_maker/aim1_mod_maker.h index d92eebd..4f78b5b 100644 --- a/src/aim1_mod_maker/aim1_mod_maker.h +++ b/src/aim1_mod_maker/aim1_mod_maker.h @@ -473,6 +473,97 @@ struct mod_maker { // increase number of goods ++*(uint32_t *)(f.p + it->second.offset); } + void clone_mechmind_group(path mmo_fn, const std::string &name, const std::string &newname) { + auto fn = find_real_filename(mmo_fn); + files_to_pak.insert(fn); + + mmo_storage2 m{fn}; + m.load(); + + auto it = m.mechs.find(name); + if (it == m.mechs.end()) { + throw std::runtime_error{"no such mechmind or group: " + name}; + } + if (newname.size() > 0x20-1) { + throw std::runtime_error{"too long name: " + newname}; + } + primitives::templates2::mmap_file f{fn, primitives::templates2::mmap_file::rw{}}; + auto &n = *(uint32_t*)(f.p + m.n_mech_groups_offset); + ++n; + std::string data{f.p + it->second.offset, f.p + it->second.offset + it->second.size}; + strcpy(data.data(), newname.data()); + f.close(); + bin_patcher::insert(fn, m.mech_groups_offset, data); + } + bool set_mechmind_organization(path mmo_fn, const std::string &name, const std::string &orgname) { + auto fn = find_real_filename(mmo_fn); + files_to_pak.insert(fn); + + mmo_storage2 m{fn}; + m.load(); + + auto it = m.mechs.find(name); + if (it == m.mechs.end()) { + throw std::runtime_error{"no such mechmind or group: " + name}; + } + if (orgname.size() > 0x20-1) { + throw std::runtime_error{"too long organization name: " + orgname}; + } + primitives::templates2::mmap_file f{fn, primitives::templates2::mmap_file::rw{}}; + memcpy(f.p + it->second.name_offset + 0x20, orgname.data(), orgname.size() + 1); + return true; + } + bool rename_mechmind_group(path mmo_fn, const std::string &name, const std::string &newname) { + auto fn = find_real_filename(mmo_fn); + files_to_pak.insert(fn); + + mmo_storage2 m{fn}; + m.load(); + + auto it = m.mechs.find(name); + if (it == m.mechs.end()) { + return false; + } + if (newname.size() > 0x20-1) { + throw std::runtime_error{"too long name: " + newname}; + } + primitives::templates2::mmap_file f{fn, primitives::templates2::mmap_file::rw{}}; + memcpy(f.p + it->second.name_offset, newname.data(), newname.size() + 1); + return true; + } + void update_mechmind_group_configurations(path mmo_fn, const std::string &name, auto &&cfg, auto &&...cfgs) { + auto fn = find_real_filename(mmo_fn); + files_to_pak.insert(fn); + + mmo_storage2 m{fn}; + m.load(); + + auto it = m.mechs.find(name); + if (it == m.mechs.end()) { + throw std::runtime_error{"no such mechmind or group: " + name}; + } + auto new_n = 1 + sizeof...(cfgs); + primitives::templates2::mmap_file f{fn, primitives::templates2::mmap_file::rw{}}; + auto &n = *(uint32_t*)(f.p + it->second.n_mechs_offset); + auto oldn = n; + n = new_n; + f.close(); + + bin_patcher::erase(fn, it->second.mechs_offset, oldn * 0x20); + std::string newcfgs; + newcfgs.resize(0x20 * new_n); + auto p = newcfgs.data(); + auto add = [&](const std::string &cfg) { + if (cfg.size() > 0x20-1) { + throw std::runtime_error{"too long config name: " + cfg}; + } + strcpy(p, cfg.data()); + p += 0x20; + }; + add(cfg); + (add(cfgs),...); + bin_patcher::insert(fn, it->second.mechs_offset, newcfgs); + } // all you need is to provide injection address (virtual) with size // handle the call instruction in 'dispatcher' symbol (naked) of your dll