def main(): parser = ArgumentParser(description="List particle systems in particle files") parser.add_argument("input_file", type=FileType("rb"), help="Input file, e.g. input.pcf") parser.add_argument("--full", action="store_true") args = parser.parse_args() p = PCF(include_attributes=args.full) p.unpack(args.input_file) if not args.full: for e in p["elements"]: if e["type"].data == "DmeParticleSystemDefinition": print(e["name"].data.lower()) else: main_element = p["elements"][0] assert main_element["type"].data == "DmElement" assert len(main_element.attribute) == 1 main_attribute = main_element.attribute[0] assert main_attribute["name"].data == "particleSystemDefinitions" assert main_attribute["type"].data == 15 psdl = main_attribute["data"] counter = Counter() for i in range(len(psdl)): psd = psdl[i].data recursive_count(psd, counter) for i in range(len(psdl)): psd = psdl[i].data name = psd["name"].data.lower() if counter[name] != 2: recursive_print(psd, 0, counter)
def edit_particle_file(f, file): p = PCF() with open(source_file(file), "rb") as s: p.unpack(s) p.minimize() main_element = p["elements"][0] assert main_element["type"].data == "DmElement" assert len(main_element.attribute) == 1 main_attribute = main_element.attribute[0] assert main_attribute["name"].data == "particleSystemDefinitions" assert main_attribute["type"].data == 15 psdl = main_attribute["data"] for i in range(len(psdl)): f(psdl, i) if nohats_dir: dest = nohats_file(file) dest_dir = dirname(dest) if not exists(dest_dir): makedirs(dest_dir) with open(dest, "wb") as s: p.full_pack(s) else: s = FakeWriteStream() p.full_pack(s)
def get_particle_file_systems(d, units, npc_heroes): files = [] with open(dota_file("particles/particles_manifest.txt"), "rt", encoding="utf-8") as s: l = s.readline().rstrip("\n") l = "\"" + l + "\"" l += s.read() m = load(StringIO(l)) for k, v in m["particles_manifest"]: assert k == "file", k if v.startswith("!"): v = v[1:] files.append(v) for id, item in chain(units["DOTAUnits"], npc_heroes["DOTAHeroes"]): if "ParticleFile" in item and item["ParticleFile"] not in files: files.append(item["ParticleFile"]) with open(dota_file("scripts/precache.txt"), "rt", encoding="utf-8") as s: p = load(s) for k, v in p["precache"]: if k == "particlefile" and v not in files: files.append(v) for id, item in d["items_game"]["items"]: if "particle_file" in item and item["particle_file"] not in files: files.append(item["particle_file"]) for id, v in d["items_game"]["attribute_controlled_attached_particles"]: if v.get("resource") is not None and v["resource"] not in files: files.append(v["resource"]) for k, v in d["items_game"]["asset_modifiers"]: if "file" in v and v["file"] not in files: files.append(v["file"]) particle_file_systems = OrderedDict() for file in files: if not exists(source_file(file)): print("Warning: referenced particle file '{}' doesn't exist.".format(file), file=stderr) continue particle_file_systems[file] = [] pcf = PCF(include_attributes=False) with open(source_file(file), "rb") as s: pcf.unpack(s) for e in pcf["elements"]: if e["type"].data == "DmeParticleSystemDefinition": system_name = e["name"].data.lower() if system_name not in particle_file_systems[file]: particle_file_systems[file].append(system_name) else: print("Warning: double particle system definition '{}' in '{}'".format(system_name, file), file=stderr) return particle_file_systems
def edit(psdl, i): psd = psdl[i].data assert psd["type"].data == "DmeParticleSystemDefinition" name = psd["name"].data.lower() if name in replacements: if replacements[name] is None: psd.attribute.data = [] else: replacement_file, replacement_system = replacements[name] o = PCF() with open(source_file(replacement_file), "rb") as s: o.unpack(s) for e in o["elements"]: if e["type"].data == "DmeParticleSystemDefinition" and e["name"].data.lower() == replacement_system: psd.attribute.data = e.attribute.data break else: assert False, "Could not find system {} in file {}".format(replacement_system, replacement_file) del replacements[name]
def main(src, dest): p = PCF() with open(src, "rb") as s: p.unpack(s) p.minimize() main_element = p["elements"][0] assert main_element["type"].data == "DmElement" assert len(main_element.attribute) == 1 main_attribute = main_element.attribute[0] assert main_attribute["name"].data == "particleSystemDefinitions" assert main_attribute["type"].data == 15 psdl = main_attribute["data"] for i in range(len(psdl)): psd = psdl[i].data recursive_edit(psd, psdl) with open(dest, "wb") as s: p.full_pack(s)
def fix_particles(d, defaults, default_ids, visuals, sockets, units, npc_heroes): visuals, particle_replacements = get_particle_replacements(d, defaults, visuals, sockets, default_ids) particle_file_systems = get_particle_file_systems(d, units, npc_heroes) particlesystem_files = {} for file, systems in particle_file_systems.items(): for system in systems: particlesystem_files.setdefault(system, []) particlesystem_files[system].append(file) file_replacements = OrderedDict() for system, default_system in particle_replacements.items(): if system not in particlesystem_files: print("Warning: system '{}' is not in any particle file".format(system), file=stderr) continue system_files = particlesystem_files[system] if default_system is None: default_system_files = [] else: default_system_files = particlesystem_files.get(default_system, []) if default_system_files == []: if "_active" in default_system or "_passive" in default_system: # pseudo-system for item triggered particle effects pass else: print("Warning: default system '{}' is not in any particle file".format(default_system), file=stderr) for file in system_files: file_replacements.setdefault(file, OrderedDict()) if default_system_files == []: file_replacements[file][system] = None else: # TODO: figure out the right choice when len(default_system_files) > 1 file_replacements[file][system] = (default_system_files[0], default_system) for file, replacements in file_replacements.items(): print("{}:".format(file)) for system, replacement in replacements.items(): if replacement is None: print("\t{} -> None".format(system)) else: replacement_file, replacement_system = replacement print("\t{} -> {} ({})".format(system, replacement_system, replacement_file)) p = PCF() with open(dota_file(file), "rb") as s: p.unpack(s) p.minimize() main_element = p["elements"][0] assert main_element["type"].data == "DmElement" assert len(main_element.attribute) == 1 main_attribute = main_element.attribute[0] assert main_attribute["name"].data == "particleSystemDefinitions" assert main_attribute["type"].data == 15 psdl = main_attribute["data"] for i in range(len(psdl)): psd = psdl[i].data assert psd["type"].data == "DmeParticleSystemDefinition" name = psd["name"].data if name in replacements: if replacements[name] is None: psd.attribute.data = [] else: replacement_file, replacement_system = replacements[name] o = PCF() with open(dota_file(replacement_file), "rb") as s: o.unpack(s) for e in o["elements"]: if e["type"].data == "DmeParticleSystemDefinition" and e["name"].data == replacement_system: psd.attribute.data = e.attribute.data break del replacements[name] assert not replacements if nohats_dir: dest = nohats_file(file) dest_dir = dirname(dest) if not exists(dest_dir): makedirs(dest_dir) with open(dest, "wb") as s: p.full_pack(s) else: s = FakeWriteStream(0, file) p.full_pack(s) return visuals
def main(): parser = ArgumentParser( description="Replace or delete particle systems in particle files") parser.add_argument("output_file", type=FileType("wb"), help="Output file, e.g. output.pcf") parser.add_argument("input_file", type=FileType("rb"), help="Input file, e.g. input.pcf") parser.add_argument( "--delete", "-d", action="append", metavar="NAME", default=[], help="Replace particle system NAME with an empty particle system.") parser.add_argument( "--replace", "-r", nargs=3, action="append", metavar=("NAME", "SOURCE_FILE", "SOURCE_NAME"), help= "Replace particle system NAME with particle system SOURCE_NAME from SOURCE_FILE.", default=[]) parser.add_argument( "--file", "-f", type=FileType("r"), help= "Read the lines of FILE for commands. Line format: COMMAND NAME [SOURCE_FILE SOURCE_NAME], where COMMAND is delete or replace." ) args = parser.parse_args() replacements = OrderedDict() def add_replacement(name, r): assert name not in replacements, "Double definition for particle system {}".format( name) replacements[name] = r for name in args.delete: add_replacement(name, None) for (name, source_file, source_name) in args.replace: add_replacement(name, (source_file, source_name)) if args.file: for line in args.file: l = line.split() assert len(l) >= 1, "No command in line: {}".format(line) command = l[0] if command == "delete": assert len( l) == 2, "Wrong number of arguments in line: {}".format( line) add_replacement(l[1], None) elif command == "replace": assert len( l) == 4, "Wrong number of arguments in line: {}".format( line) add_replacement(l[1], (expanduser(l[2]), l[3])) else: assert False, "Invalid command {} in line: {}".format( command, line) p = PCF() p.unpack(args.input_file) p.minimize() main_element = p["elements"][0] assert main_element["type"].data == "DmElement" assert len(main_element.attribute) == 1 main_attribute = main_element.attribute[0] assert main_attribute["name"].data == "particleSystemDefinitions" assert main_attribute["type"].data == 15 psl = main_attribute["data"] for ps in psl: psd = ps.data assert psd["type"].data == "DmeParticleSystemDefinition" name = psd["name"].data.lower() if name in replacements: if replacements[name] is None: psd.attribute.data = [] else: replacement_file, replacement_system = replacements[name] o = PCF() with open(replacement_file, "rb") as s: o.unpack(s) for e in o["elements"]: if e["type"].data == "DmeParticleSystemDefinition" and e[ "name"].data.lower() == replacement_system: psd.attribute.data = e.attribute.data break else: assert False, "Could not find system {} in file {}".format( replacement_system, replacement_file) del replacements[name] p.full_pack(args.output_file)