def make_new_savedata(store: FlagStore, big_endian: bool, orig_files: list) -> bytes: svwriter = oead.SarcWriter( endian=oead.Endianness.Big if big_endian else oead.Endianness.Little) svdata_array = store.flags_to_svdata_Array() num_files = ceil(len(svdata_array) / 8192) for idx in range(num_files): start = idx * 8192 end = (idx + 1) * 8192 if end > len(svdata_array): end = len(svdata_array) svwriter.files[f"/saveformat_{idx}.bgsvdata"] = oead.byml.to_binary( oead.byml.Hash({ "file_list": oead.byml.Array([ { "IsCommon": False, "IsCommonAtSameAccount": False, "IsSaveSecureCode": True, "file_name": "game_data.sav", }, oead.byml.Array(svdata_array[start:end]), ]), "save_info": oead.byml.Array([{ "directory_num": oead.S32(num_files + 2), "is_build_machine": True, "revision": oead.S32(18203), }]), }), big_endian, ) svwriter.files[f"/saveformat_{num_files}.bgsvdata"] = orig_files[0] svwriter.files[f"/saveformat_{num_files+1}.bgsvdata"] = orig_files[1] return svwriter.write()[1]
def generate_actor_info(pack: ActorPack, has_far: bool, old_info: oead.byml.Hash) -> oead.byml.Hash: entry = old_info entry["name"] = pack.get_name() entry["isHasFar"] = has_far profile = pack.get_link("ProfileUser") if not pack.get_link("SlinkUser") == "Dummy": entry["bugMask"] = oead.S32( 2) # TODO: Find what sets the first bit of bugMask if entry["sortKey"].v > 0: entry["sortKey"] = oead.S32(entry["sortKey"].v + 1) actorlink = pack.get_actorlink() for key, value in get_actorlink_entries(actorlink).items(): if key in KEYS_BY_PROFILE[profile]: entry[key] = value tags = get_actorlink_tags(actorlink) if tags: entry["tags"] = tags funcs = { "ChemicalUser": get_chemical_entries, "DropTableUser": get_droptable_entries, "GParamUser": get_gparamlist_entries, "LifeConditionUser": get_lifecondition_entries, "ModelUser": get_modellist_entries, "PhysicsUser": get_physics_entries, "RecipeUser": get_recipe_entries, } for link, func in funcs.items(): yaml = pack.get_link_data(link) if not yaml == "": for key, value in func( oead.aamp.ParameterIO.from_text(yaml)).items(): entry[key] = value keys_to_pop: list = [] for key in entry.keys(): if not key in KEYS_BY_PROFILE[profile]: keys_to_pop.append(key) for key in keys_to_pop: del entry[key] del keys_to_pop return entry
def get_modded_savedata_entries(savedata: oead.Sarc) -> {}: ref_savedata = get_stock_savedata().get_files() ref_hashes = { int(item["HashValue"]) for file in sorted(ref_savedata, key=lambda f: f.name)[0:-2] for item in oead.byml.from_binary(file.data)["file_list"][1] } new_entries = oead.byml.Array() mod_hashes = set() for file in sorted( savedata.get_files(), key=lambda f: f.name, )[0:-2]: entries = oead.byml.from_binary(file.data)["file_list"][1] mod_hashes |= {int(item["HashValue"]) for item in entries} new_entries.extend({ item for item in entries if int(item["HashValue"]) not in ref_hashes }) del ref_savedata return oead.byml.Hash({ "add": new_entries, "del": oead.byml.Array( {oead.S32(item) for item in ref_hashes if item not in mod_hashes}), })
def get_modded_savedata_entries(savedata: oead.Sarc) -> Hash: ref_savedata = get_stock_savedata().get_files() ref_hashes = { int(item["HashValue"]) for file in sorted(ref_savedata, key=lambda f: f.name)[0:-2] for item in oead.byml.from_binary(file.data)["file_list"][1] } new_entries = oead.byml.Array() mod_hashes = set() for file in savedata.get_files(): data = oead.byml.from_binary(file.data) if data["file_list"][0]["file_name"] != "game_data.sav": continue entries = data["file_list"][1] mod_hashes |= {int(item["HashValue"]) for item in entries} new_entries.extend( [item for item in entries if int(item["HashValue"]) not in ref_hashes] ) del ref_savedata return Hash( { "add": new_entries, "del": oead.byml.Array( oead.S32(item) for item in {item for item in ref_hashes if item not in mod_hashes} ), } )
def __init__(self, def_name: str, type: str, name: str = "", group: str = ""): super().__init__() defs = util.get_ai_defs() key = ("AIs" if type == "ai" else "Actions" if type == "action" else "Behaviors" if type == "behavior" else "Querys" if type == "query" else "") if def_name in defs[key]: ai_def = defs[key][def_name] self.lists = {} self.objects = {crc32(b"Def"): ParameterObject()} self.objects["Def"].params["ClassName"] = Parameter( oead.FixedSafeString32(def_name)) self.objects["Def"].params["Name"] = Parameter(name) self.objects["Def"].params["GroupName"] = Parameter(group) if "childs" in ai_def: self.objects["ChildIdx"] = ParameterObject() for child in ai_def["childs"]: self.objects["ChildIdx"].params[child] = Parameter( oead.S32(-1)) if "StaticInstParams" in ai_def: self.objects["SInst"] = ParameterObject() for sinst in ai_def["StaticInstParams"]: if "Value" in sinst: val = sinst["Value"] else: val = _param_type_map[sinst["Type"]]() self.objects["SInst"].params[sinst["Name"]] = Parameter( val) else: raise ValueError(f"{def_name} is not a valid AI")
def perform_merge(self): actor_path = (util.get_master_modpack_dir() / util.get_content_path() / "Actor" / "ActorInfo.product.sbyml") print("Loading modded actor info...") modded_actors = self.consolidate_diffs(self.get_all_diffs()) if not modded_actors: print("No actor info merging necessary.") if actor_path.exists(): actor_path.unlink() return print("Loading unmodded actor info...") actorinfo = get_stock_actorinfo() stock_actors = { crc32(actor["name"].encode("utf8")): actor for actor in actorinfo["Actors"] } print("Merging changes...") new_hashes = set() for actor_hash, actor_info in modded_actors.items(): if isinstance(actor_hash, str): actor_hash = int(actor_hash) if actor_hash in stock_actors: util.dict_merge(stock_actors[actor_hash], actor_info, overwrite_lists=True) else: actorinfo["Actors"].append(actor_info) new_hashes.add(actor_hash) print("Sorting new actor info...") actorinfo["Hashes"] = oead.byml.Array([ oead.S32(x) if x < 2147483648 else oead.U32(x) for x in sorted(new_hashes | set(stock_actors.keys())) ]) try: actorinfo["Actors"] = sorted( actorinfo["Actors"], key=lambda x: crc32(x["name"].encode("utf-8"))) except KeyError as err: if str(err) == "": raise RuntimeError( "Your actor info mods could not be merged. " "This usually indicates a corrupt game dump.") from err else: raise print("Saving new actor info...") actor_path.parent.mkdir(parents=True, exist_ok=True) actor_path.write_bytes( util.compress( oead.byml.to_binary(actorinfo, big_endian=util.get_settings("wiiu")))) print("Actor info merged successfully")
def get_actorlink_tags( data: oead.aamp.ParameterIO) -> Union[oead.byml.Hash, None]: d: Union[oead.byml.Hash, None] = None if "Tags" in data.objects: d = oead.byml.Hash() for _, val in data.objects["Tags"].params.items(): taghash = zlib.crc32(val.v.encode("utf-8")) tagval = oead.U32(taghash) if taghash > 2147483647 else oead.S32( taghash) taghex = f"tag{padhex(hex(taghash))[2:]}" d[taghex] = tagval return d
def get_chemical_entries(data: oead.aamp.ParameterIO) -> dict: d: dict = {} if "chemical_root" in data.lists: cr = data.lists["chemical_root"] if "chemical_body" in cr.lists: cb = cr.lists["chemical_body"] if "rigid_c_00" in cb.objects: rc = cb.objects["rigid_c_00"] if "attribute" in rc.params: if rc.params["attribute"].v == 650: if not "Chemical" in d: d["Chemical"] = oead.byml.Hash() d["Chemical"]["Capaciter"] = oead.S32(1) if "shape_00" in cb.objects: s0 = cb.objects["shape_00"] if "name" in s0.params: if s0.params["name"].v == "WeaponFire": if not "Chemical" in d: d["Chemical"] = oead.byml.Hash() d["Chemical"]["Burnable"] = oead.S32(1) return d
def _build_actorinfo(params: BuildParams): actors = [] for actor_file in (params.out / params.content / "Actor" / "ActorInfo").glob( "*.info" ): actors.append(oead.byml.from_binary(actor_file.read_bytes())) actor_file.unlink() hashes = oead.byml.Array( [ oead.S32(crc) if crc < 2147483648 else oead.U32(crc) for crc in sorted({crc32(a["name"].encode("utf8")) for a in actors}) ] ) actors.sort(key=lambda actor: crc32(actor["name"].encode("utf8"))) actor_info = oead.byml.Hash({"Actors": oead.byml.Array(actors), "Hashes": hashes}) info_path = params.out / params.content / "Actor" / "ActorInfo.product.sbyml" info_path.parent.mkdir(exist_ok=True, parents=True) info_path.write_bytes( compress(oead.byml.to_binary(actor_info, big_endian=params.be)) )
def _build_actorinfo(params: BuildParams): actors = [] for actor_file in (params.mod / params.content / 'Actor' / 'ActorInfo').glob('*.info.yml'): actors.append( oead.byml.from_text(actor_file.read_text(encoding='utf-8'))) hashes = oead.byml.Array([ oead.S32(crc) if crc < 2147483648 else oead.U32(crc) for crc in sorted({crc32(a['name'].encode('utf8')) for a in actors}) ]) actors.sort(key=lambda actor: crc32(actor['name'].encode('utf8'))) actor_info = oead.byml.Hash({ 'Actors': oead.byml.Array(actors), 'Hashes': hashes }) info_path = params.out / params.content / 'Actor' / 'ActorInfo.product.sbyml' info_path.parent.mkdir(exist_ok=True, parents=True) info_path.write_bytes( compress(oead.byml.to_binary(actor_info, big_endian=params.be)))
def dictParamsToByml(dictIn): subDict = {} dictOut = {} # print(dictIn) for key in dictIn.keys(): keyVal = dictIn.get(key) if isinstance(keyVal, int): dictOut.update({key: oead.S32(keyVal)}) elif isinstance(keyVal, dict): subDict.update({key: keyVal}) dictOut.update({key: dictParamsToByml(subDict)}) elif isinstance(keyVal, str): dictOut.update({key: keyVal}) elif isinstance(keyVal, float): dictOut.update({key: oead.F32(keyVal)}) elif keyVal == None: dictOut.update({key: 'none'}) else: print('error?') dictOut.update({key: keyVal}) # print(dictOut) return(((dict(dictOut))))
def convert_hash(x: int) -> Union[oead.S32, oead.U32]: return oead.U32(x) if x > 0x80000000 else oead.S32(x)
def armor_iter(armor, actorinfo, actors): armor.base = get_def_item(armor.base, actors) old_hash = create_hash(armor.base) new_hash = create_hash(armor.name) loc = 0 for x in actorinfo['Hashes']: if int(new_hash) < int(x): break loc += 1 old_loc = get_arr_index(actorinfo["Hashes"], old_hash) actorinfo["Hashes"].insert(loc, new_hash) # new_loc = get_arr_index(actorinfo["Hashes"], new_hash) new_entry = dict(actorinfo["Actors"][old_loc]) new_entry["name"] = armor.name new_entry = dict(actorinfo["Actors"][old_loc]) new_entry["name"] = armor.name if armor.elink: new_entry["elink"] = armor.elink if armor.slink: new_entry["slink"] = armor.slink if armor.armorStarNum: new_entry["armorStarNum"] = oead.S32(armor.armorStarNum) if armor.armorNextRankName: new_entry["armorNextRankName"] = armor.armorNextRankName if armor.itemUseIconActorName: new_entry["itemUseIconActorName"] = armor.itemUseIconActorName if armor.defence: new_entry["armorDefenceAddLevel"] = oead.S32(int(armor.defence)) if armor.effect_lv: new_entry["armorEffectEffectLevel"] = oead.S32(int(armor.effect_lv)) if armor.effect: new_entry["armorEffectEffectType"] = armor.effect elif armor.effect == 'None': new_entry["armorEffectEffectLevel"] = oead.S32(0) if armor.profile: new_entry["profile"] = armor.profile if armor.series: new_entry["seriesArmorSeriesType"] = armor.series if armor.bfres: new_entry["bfres"] = armor.bfres else: new_entry["bfres"] = armor.bfres_folder if armor.mainmodel: new_entry["mainModel"] = armor.mainmodel else: new_entry["mainModel"] = armor.name #if "bfres" in new_entry: new_entry["bfres"] = armor.bfres_folder #if "mainModel" in new_entry: new_entry["mainModel"] = armor.name new_entry["sortKey"] = S32(int(new_entry["sortKey"]) + 1) #new_entry["armorNextRankName"] = '' if armor.item1 and armor.item1_n: new_entry["normal0ItemName01"] = armor.item1 new_entry["normal0ItemNum01"] = oead.S32(int(armor.item1_n)) else: new_entry["normal0ItemName01"] = 'Item_Enemy_26' new_entry["normal0ItemNum01"] = oead.S32(1) if armor.item1 and armor.item1_n and armor.item2 and armor.item2_n: new_entry["normal0ItemName02"] = armor.item2 new_entry["normal0ItemNum02"] = oead.S32(int(armor.item2_n)) else: new_entry["normal0ItemName02"] = 'Item_Enemy_00' new_entry["normal0ItemNum02"] = oead.S32(1) if armor.item1 and armor.item1_n and armor.item2 and armor.item2_n and armor.item3 and armor.item3_n: new_entry["normal0ItemName03"] = armor.item3 new_entry["normal0ItemNum03"] = oead.S32(int(armor.item3_n)) else: new_entry["normal0ItemName03"] = 'Item_Enemy_28' new_entry["normal0ItemNum03"] = oead.S32(1) new_entry["normal0StuffNum"] = oead.S32(1) if armor.price: new_entry["itemBuyingPrice"] = oead.S32(int(armor.price)) new_entry["itemCreatingPrice"] = oead.S32(int(armor.price)) actorinfo["Actors"].insert(loc, new_entry) del new_entry return actorinfo
def weapon_iter(weapon, actorinfo, actors): weapon.base = get_def_item(weapon.base, actors) old_hash = create_hash(weapon.base) new_hash = create_hash(weapon.name) loc = 0 for x in actorinfo['Hashes']: if int(new_hash) < int(x): break loc += 1 old_loc = get_arr_index(actorinfo["Hashes"], old_hash) actorinfo["Hashes"].insert(loc, new_hash) #new_loc = get_arr_index(actorinfo["Hashes"], new_hash) new_entry = dict(actorinfo["Actors"][old_loc]) new_entry["name"] = weapon.name if weapon.profile == 'WeaponShield': if weapon.attack: new_entry["weaponCommonGuardPower"] = oead.S32(int(weapon.attack)) else: if weapon.attack: new_entry["attackPower"] = oead.S32(int(weapon.attack)) if weapon.elink: new_entry["elink"] = weapon.elink if weapon.slink: new_entry["slink"] = weapon.slink if weapon.dur: new_entry["generalLife"] = oead.S32(int(weapon.dur)) new_entry["bfres"] = weapon.name new_entry["mainModel"] = weapon.name new_entry["sortKey"] = S32(int(new_entry["sortKey"]) + 1) if weapon.item1 and weapon.item1_n: new_entry["normal0ItemName01"] = weapon.item1 new_entry["normal0ItemNum01"] = oead.S32(int(weapon.item1_n)) else: new_entry["normal0ItemName01"] = 'Item_Enemy_26' new_entry["normal0ItemNum01"] = oead.S32(1) if weapon.item1 and weapon.item1_n and weapon.item2 and weapon.item2_n: new_entry["normal0ItemName02"] = weapon.item2 new_entry["normal0ItemNum02"] = oead.S32(int(weapon.item2_n)) else: new_entry["normal0ItemName02"] = 'Item_Enemy_00' new_entry["normal0ItemNum02"] = oead.S32(1) if weapon.item1 and weapon.item1_n and weapon.item2 and weapon.item2_n and weapon.item3 and weapon.item3_n: new_entry["normal0ItemName03"] = weapon.item3 new_entry["normal0ItemNum03"] = oead.S32(int(weapon.item3_n)) else: new_entry["normal0ItemName03"] = 'Item_Enemy_28' new_entry["normal0ItemNum03"] = oead.S32(1) new_entry["normal0StuffNum"] = oead.S32(1) if weapon.price: new_entry["itemBuyingPrice"] = oead.S32(int(weapon.price)) new_entry["itemCreatingPrice"] = oead.S32(int(weapon.price)) actorinfo["Actors"].insert(loc, new_entry) del new_entry return actorinfo
def save(self, root_dir: str, be: bool) -> None: if self._resident: titlebg_path = Path(f"{root_dir}/Pack/TitleBG.pack") actor_dir = f"Actor/Pack/{self._pack.get_name()}.sbactorpack" if not titlebg_path.exists(): titlebg_path.parent.mkdir(parents=True, exist_ok=True) shutil.copy(util.find_file(Path("Pack/TitleBG.pack")), titlebg_path) yaz0_bytes = oead.yaz0.compress(self._pack.get_bytes(be)) util.inject_bytes_into_sarc(titlebg_path, actor_dir, yaz0_bytes) else: actor_path = Path( f"{root_dir}/Actor/Pack/{self._pack.get_name()}.sbactorpack") yaz0_bytes = oead.yaz0.compress(self._pack.get_bytes(be)) if not actor_path.exists(): actor_path.parent.mkdir(parents=True, exist_ok=True) actor_path.touch() actor_path.write_bytes(yaz0_bytes) hash = crc32(self._pack.get_name().encode("utf-8")) info = self.get_info() if self._has_far: actor_path = Path( f"{root_dir}/Actor/Pack/{self._far_pack.get_name()}.sbactorpack" ) yaz0_bytes = oead.yaz0.compress(self._far_pack.get_bytes(be)) if not actor_path.exists(): actor_path.touch() actor_path.write_bytes(yaz0_bytes) far_hash = crc32(self._far_pack.get_name().encode("utf-8")) far_info = self.get_far_info() actorinfo_path = Path(f"{root_dir}/Actor/ActorInfo.product.sbyml") actorinfo_load_path = actorinfo_path if not actorinfo_load_path.exists(): actorinfo_load_path.touch() actorinfo_load_path = Path( util.find_file(Path("Actor/ActorInfo.product.sbyml"))) actorinfo = oead.byml.from_binary( oead.yaz0.decompress(actorinfo_load_path.read_bytes())) hashes = [int(h) for h in actorinfo["Hashes"]] try: hash_index = hashes.index(hash) except ValueError: hashes.append(hash) hashes.sort() hash_index = hashes.index(hash) actorinfo["Actors"].insert(hash_index, oead.byml.Hash()) if self._has_far: try: far_hash_index = hashes.index(far_hash) except ValueError: hashes.append(far_hash) hashes.sort() far_hash_index = hashes.index(far_hash) actorinfo["Actors"].insert(far_hash_index, oead.byml.Hash()) actorinfo["Hashes"] = oead.byml.Array( [oead.U32(h) if h > 2147483647 else oead.S32(h) for h in hashes]) actorinfo["Actors"][hash_index] = info if self._has_far: actorinfo["Actors"][far_hash_index] = far_info actorinfo_path.write_bytes( oead.yaz0.compress(oead.byml.to_binary(actorinfo, be))) self._texts.write(root_dir, be) bootup_path = Path(f"{root_dir}/Pack/Bootup.pack") if not bootup_path.exists(): bootup_path.parent.mkdir(parents=True, exist_ok=True) shutil.copy(util.find_file(Path("Pack/Bootup.pack")), bootup_path) gamedata_sarc = util.get_gamedata_sarc(bootup_path) for bgdata_name, bgdata_hash in map(util.unpack_oead_file, gamedata_sarc.get_files()): self._flags.add_flags_from_Hash(bgdata_name, bgdata_hash, False) files_to_write: list = [] files_to_write.append("GameData/gamedata.ssarc") files_to_write.append("GameData/savedataformat.ssarc") orig_files = util.get_last_two_savedata_files(bootup_path) datas_to_write: list = [] datas_to_write.append( oead.yaz0.compress(util.make_new_gamedata(self._flags, be))) datas_to_write.append( oead.yaz0.compress( util.make_new_savedata(self._flags, be, orig_files))) util.inject_files_into_bootup(bootup_path, files_to_write, datas_to_write)
def perform_merge(self): force = self._options.get("force", False) slog_path = util.get_master_modpack_dir() / "logs" / "savedata.log" new_entries = self.consolidate_diffs(self.get_all_diffs()) if not new_entries: print("No savedata merging necessary.") if slog_path.exists(): slog_path.unlink() if (util.get_master_modpack_dir() / "logs" / "savedata.sarc").exists(): (util.get_master_modpack_dir() / "logs" / "savedata.sarc").unlink() return if slog_path.exists() and not force: with slog_path.open("r") as l_file: if xxhash.xxh64_hexdigest(str(new_entries)) == l_file.read(): print("No savedata merging necessary.") return savedata = get_stock_savedata() save_files = sorted(savedata.get_files(), key=lambda f: f.name)[0:-2] print("Merging changes...") merged_entries = oead.byml.Array( sorted( { entry["HashValue"].v: entry for entry in [ *[ e for file in save_files for e in oead.byml.from_binary(file.data)["file_list"][1] ], *new_entries["add"], ] if entry not in new_entries["del"] }.values(), key=itemgetter("HashValue"), )) print("Creating and injecting new savedataformat.sarc...") new_savedata = oead.SarcWriter( endian=oead.Endianness.Big if util.get_settings("wiiu") else oead. Endianness.Little) num_files = ceil(len(merged_entries) / 8192) for i in range(num_files): end_pos = (i + 1) * 8192 if end_pos > len(merged_entries): end_pos = len(merged_entries) data = oead.byml.to_binary( oead.byml.Hash({ "file_list": oead.byml.Array([ { "IsCommon": False, "IsCommonAtSameAccount": False, "IsSaveSecureCode": True, "file_name": "game_data.sav", }, oead.byml.Array(merged_entries[i * 8192:end_pos]), ]), "save_info": oead.byml.Array([{ "directory_num": oead.S32(8), "is_build_machine": True, "revision": oead.S32(18203), }]), }), big_endian=util.get_settings("wiiu"), ) new_savedata.files[f"/saveformat_{i}.bgsvdata"] = data new_savedata.files[f"/saveformat_{num_files}.bgsvdata"] = oead.Bytes( savedata.get_file("/saveformat_6.bgsvdata").data) new_savedata.files[ f"/saveformat_{num_files + 1}.bgsvdata"] = oead.Bytes( savedata.get_file("/saveformat_7.bgsvdata").data) del savedata new_save_bytes = new_savedata.write()[1] del new_savedata util.inject_file_into_sarc( "GameData/savedataformat.ssarc", util.compress(new_save_bytes), "Pack/Bootup.pack", create_sarc=True, ) (util.get_master_modpack_dir() / "logs").mkdir(parents=True, exist_ok=True) ((util.get_master_modpack_dir() / "logs" / "savedata.sarc").write_bytes(new_save_bytes)) print("Updating RSTB...") rstable.set_size( "GameData/savedataformat.sarc", rstable.calculate_size("GameData/savedataformat.sarc", new_save_bytes), ) del new_save_bytes slog_path.parent.mkdir(parents=True, exist_ok=True) with slog_path.open("w", encoding="utf-8") as l_file: l_file.write(xxhash.xxh64_hexdigest(str(new_entries)))
def main(): # Cli Arguments Setup progDesc = "A program for bulk replacing and deleting parameters and actors in BotW BYML map files." parser = argparse.ArgumentParser(description=progDesc) subParser = parser.add_subparsers(description='Sub-Commands required to use the functions of BMPM', dest='subParserType') parser.add_argument('fileIn', type=str, help="File to open and read data from.", default=None) # parser.add_argument('--version', '-v', dest='version', help='Displays the current version of BMPM being run.', required=False) parser.add_argument('--noCompression', '-nc', action='store_true', help='Add this if you would prefer the program to not compress the output file with yaz0.') parser.add_argument('--bigEndian', '-be', action='store_true', dest='endian', help='Outputs the files in a big endian format', required=False, default=False) editParser = subParser.add_parser('edit', help='edit') editParser.add_argument('termToSearch', type=str, help='Term to look through the file and find.') editParser.add_argument('--value', '-v', type=str, metavar='value', dest='value', help='Value to match with params found in file.', required=False, default=None) editParser.add_argument('replacementTerm', help='Value to replace the original termToSearch value with.') editParser.add_argument('--type', '-t', metavar='value', dest='type', choices=['0', '1'], help='A value of 0 meaning an integer or 1 meaning a string to set the replacement term as. (defaults to zero)', required=False, default=0) remParser = subParser.add_parser('delete', help='Remove an actor or actors from the map file(s) based on either name or hashID') remParser.add_argument('ActorToDelete', help='The actor name or HashID you would like removed from the map file.') remParser.add_argument('--fragment', '-f', dest='subStr', action='store_true', help='Whether or not the inputted search term is a prefix to search for or not.', required=False) remParser.add_argument('--type', '-t', metavar='value', dest='type', choices=['0', '1', 'hash', 'name'], help='Type of string that was inputted for actor removal(0 maps to hash and 1 to actor name, will default to actor name.)', required=False, default=1) convParser = subParser.add_parser('convert', help='Converts one actor to another based off of a template.') convParser.add_argument('--type', '-t', metavar='value', dest='type', choices=['0', '1', 'hash', 'name'], help='Type of string that was inputted for actor removal(0 maps to hash and 1 to actor name, will default to actor name.)', required=False, default=1) convParser.add_argument('--fragment', '-f', dest='subStr', action='store_true', help='Whether or not the inputted search term is a prefix to search for or not.', required=False) convParser.add_argument('actorConvertFrom', help='The actor name or hashID you would like to be converted.') convParser.add_argument('actorConvertTo', type=str, help='Actor to convert to.') endSwap = subParser.add_parser('swap', help='A function to detect and quickly convert the endianness of map files.') genParser = subParser.add_parser('genDB', help='Generate the database of actors necessary for using the replace actor function. Only needs to be run once.') # Global Variables args = parser.parse_args() if (args.fileIn != None): fileToOpen = pathlib.Path(args.fileIn) fileToOpen = fileToOpen if fileToOpen.is_file(): fileObj = fileToOpen fileName = str(fileObj).split('.')[0] fileExt = ('.' + str(fileObj).split('.')[-1]) else: print('Directory entered, beginning recursive processes.') if (args.subParserType == 'edit'): termToSearch = args.termToSearch replaceTerm = args.replacementTerm replacementParamType = None if (int(args.type) == 0): replacementParamType = oead.S32(value=int(replaceTerm)) elif (int(args.type) == 1): replacementParamType = str(replaceTerm) if fileToOpen.is_dir(): fileList = util.checkDir(fileToOpen) for fileToOpen in fileList: fileName = str(fileToOpen).split('.')[0] fileExt = ('.' + str(fileToOpen).split('.')[-1]) if (args.value != None): valToSearch = args.value functions.replaceSpfxParam(fileToOpen, fileName, fileExt, termToSearch, valToSearch, replacementParamType, args) else: functions.replaceParam(fileToOpen, fileName, fileExt, termToSearch, replacementParamType, args) else: if (args.value != None): valToSearch = args.value functions.replaceSpfxParam(fileToOpen, fileName, fileExt, termToSearch, valToSearch, replacementParamType, args) else: functions.replaceParam(fileToOpen, fileName, fileExt, termToSearch, replacementParamType, args) elif (args.subParserType == 'delete'): actorToDel = args.ActorToDelete nameHash = args.type if fileToOpen.is_dir(): fileList = util.checkDir(fileToOpen) for fileToOpen in fileList: fileName = str(fileToOpen).split('.')[0] fileExt = ('.' + str(fileToOpen).split('.')[-1]) functions.removeActor(fileToOpen, fileName, fileExt, actorToDel, nameHash, args) else: functions.removeActor(fileToOpen, fileName, fileExt, actorToDel, nameHash, args) elif (args.subParserType == 'convert'): actorToConv = args.actorConvertFrom actorConvTo = args.actorConvertTo nameHash = args.type if fileToOpen.is_dir(): fileList = util.checkDir(fileToOpen) for fileToOpen in fileList: fileName = str(fileToOpen).split('.')[0] fileExt = ('.' + str(fileToOpen).split('.')[-1]) functions.replaceActor(fileToOpen, fileName, fileExt, nameHash, actorToConv, actorConvTo, args) else: functions.replaceActor(fileToOpen, fileName, fileExt, nameHash, actorToConv, actorConvTo, args) elif(args.subParserType == 'genDB'): if (input('This may take a while, are you sure you would like to continue? (y/n)').lower().startswith('y')): functions.genActorDatabase(fileToOpen) else: print('Cancelling operation.') # elif(args.subParserType == 'version'): # print(f"BMPM-{str(version)}") elif(args.subParserType == 'swap'): if fileToOpen.is_dir(): fileList = util.checkDir(fileToOpen) for fileToOpen in fileList: fileName = str(fileToOpen).split('.')[0] fileExt = ('.' + str(fileToOpen).split('.')[-1]) functions.swapEnd(fileToOpen, fileName, fileExt, args) else: functions.swapEnd(fileToOpen, fileName, fileExt, args) else: print(f'The option {str(args.subParserType)} could not be found.')
def create_hash(x): result = zlib.crc32(bytes(x.encode())) if result < 2147483647: return oead.S32(result) else: return oead.U32(result)