[mod] New APIs: clone_mechmind_group(), rename_mechmind_group(), update_mechmind_group_configurations(), set_mechmind_organization().

This commit is contained in:
lzwdgc 2024-06-02 17:41:24 +03:00
parent 5ac5d05083
commit 152b935b25
2 changed files with 118 additions and 9 deletions

View file

@ -238,26 +238,44 @@ int main(int argc, char *argv[]) {
for (auto &&[n,_] : db["Глайдеры"]) { for (auto &&[n,_] : db["Глайдеры"]) {
m2_gliders.erase(n); m2_gliders.erase(n);
} }
for (auto &&[n, _] : m2_gliders) { //mod.copy_glider_from_aim2("GL_M4_S_FLASH");
mod.copy_glider_from_aim2(n); //m2_gliders.erase("GL_M4_S_FLASH");
} //for (auto &&[n, _] : m2_gliders) {
// mod.copy_glider_from_aim2(n);
//}
std::string after; std::string after;
for (after = "GL_M1_A_ATTACKER"s; auto &&[n, _] : db["Глайдеры"]) { 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["Оружие"]) { 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. // 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 // TODO: check in debug why they crash
mod.copy_weapon_from_aim2("GUN_DRAINER"); //mod.copy_weapon_from_aim2("GUN_DRAINER");
after = mod.add_map_good("location1.mmo", "B_L1_BASE1", after, mmo_storage2::map_good("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"); //mod.copy_weapon_from_aim2("GUN_GRAVITON");
after = mod.add_map_good("location1.mmo", "B_L1_BASE1", after, mmo_storage2::map_good("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.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 // does not work, crashes. Maybe different item size
// or maybe too many goods // or maybe too many goods
/*for (auto after = "EQP_POLYMER_ARMOR_S1"s; auto &&[n, _] : db["Оборудование"]) { /*for (auto after = "EQP_POLYMER_ARMOR_S1"s; auto &&[n, _] : db["Оборудование"]) {

View file

@ -473,6 +473,97 @@ struct mod_maker {
// increase number of goods // increase number of goods
++*(uint32_t *)(f.p + it->second.offset); ++*(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<uint8_t> f{fn, primitives::templates2::mmap_file<uint8_t>::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<uint8_t> f{fn, primitives::templates2::mmap_file<uint8_t>::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<uint8_t> f{fn, primitives::templates2::mmap_file<uint8_t>::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<uint8_t> f{fn, primitives::templates2::mmap_file<uint8_t>::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 // all you need is to provide injection address (virtual) with size
// handle the call instruction in 'dispatcher' symbol (naked) of your dll // handle the call instruction in 'dispatcher' symbol (naked) of your dll