def handle_noargs(self, **options): project_root = options.get("path", None) if not project_root: project_root = getattr(settings, 'BASE_DIR', None) verbosity = int(options.get("verbosity")) if not project_root: warnings.warn("settings.BASE_DIR or specifying --path will become mandatory in 1.4.0", DeprecationWarning) project_root = get_project_root() if verbosity > 0: self.stdout.write("""No path specified and settings.py does not contain BASE_DIR. Assuming '%s' is the project root. Please add BASE_DIR to your settings.py future versions 1.4.0 and higher of Django-Extensions will require either BASE_DIR or specifying the --path option. Waiting for 30 seconds. Press ctrl-c to abort. """ % project_root) if getattr(settings, 'COMPILE_PYC_DEPRECATION_WAIT', True): try: time.sleep(30) except KeyboardInterrupt: self.stdout.write("Aborted\n") return for root, dirs, filenames in os.walk(project_root): for filename in fnmatch.filter(filenames, '*.py'): full_path = _j(root, filename) if verbosity > 1: self.stdout.write("Compiling %s...\n" % full_path) py_compile.compile(full_path)
def handle_noargs(self, **options): project_root = get_project_root() verbose = options.get("verbose", False) for root, dirs, files in os.walk(project_root): for file in files: ext = os.path.splitext(file)[1] if ext==".py": full_path = _j(root, file) if verbose: print "%sc" % full_path py_compile.compile(full_path)
def handle_noargs(self, **options): project_root = get_project_root() exts = options.get("optimize", False) and [".pyc", ".pyo"] or [".pyc"] verbose = options.get("verbose", False) for root, dirs, files in os.walk(project_root): for file in files: ext = os.path.splitext(file)[1] if ext in exts: full_path = _j(root, file) if verbose: print full_path os.remove(full_path)
def handle_noargs(self, **options): project_root = options.get('path', None) if not project_root: project_root = get_project_root() verbose = int(options.get('verbosity', 1)) > 1 for (root, dirs, files) in os.walk(project_root): for file in files: ext = os.path.splitext(file)[1] if ext == '.py': full_path = _j(root, file) if verbose: print '%sc' % full_path py_compile.compile(full_path)
def handle_noargs(self, **options): project_root = options.get("path", None) if not project_root: project_root = get_project_root() verbose = int(options.get("verbosity", 1)) > 1 for root, dirs, files in os.walk(project_root): for file in files: ext = os.path.splitext(file)[1] if ext == ".py": full_path = _j(root, file) if verbose: print("%sc" % full_path) py_compile.compile(full_path)
def handle_noargs(self, **options): project_root = options.get("path", None) if not project_root: project_root = getattr(settings, 'BASE_DIR', None) verbosity = int(options.get("verbosity")) if not project_root: raise CommandError("No --path specified and settings.py does not contain BASE_DIR") for root, dirs, filenames in os.walk(project_root): for filename in fnmatch.filter(filenames, '*.py'): full_path = _j(root, filename) if verbosity > 1: self.stdout.write("Compiling %s...\n" % full_path) py_compile.compile(full_path)
def handle_noargs(self, **options): project_root = options.get('path', None) if not project_root: project_root = get_project_root() exts = options.get('optimize', False) and ['.pyc', '.pyo'] \ or ['.pyc'] verbose = int(options.get('verbosity', 1)) > 1 for (root, dirs, files) in os.walk(project_root): for file in files: ext = os.path.splitext(file)[1] if ext in exts: full_path = _j(root, file) if verbose: print full_path os.remove(full_path)
def handle_noargs(self, **options): project_root = options.get("path", None) verbosity = int(options.get("verbosity")) if not project_root: project_root = get_project_root() if verbosity > 0: self.stdout.write( "No path specified, assuming %s is the project root.\n" % project_root) for root, dirs, filenames in os.walk(project_root): for filename in fnmatch.filter(filenames, '*.py'): full_path = _j(root, filename) if verbosity > 1: self.stdout.write("Compiling %s...\n" % full_path) py_compile.compile(full_path)
def handle_noargs(self, **options): project_root = options.get("path", None) verbosity = int(options.get("verbosity")) if not project_root: project_root = get_project_root() if verbosity > 0: self.stdout.write( "No path specified, assuming %s is the project root.\n" % project_root) exts = options.get("optimize", False) and "*.py[co]" or "*.pyc" for root, dirs, filenames in os.walk(project_root): for filename in fnmatch.filter(filenames, exts): full_path = _j(root, filename) if verbosity > 1: self.stdout.write("%s\n" % full_path) os.remove(full_path)
def handle_noargs(self, **options): project_root = options.get("path", getattr(settings, 'BASE_DIR', None)) if not project_root: project_root = getattr(settings, 'BASE_DIR', None) verbosity = int(options.get("verbosity")) if not project_root: raise CommandError("No --path specified and settings.py does not contain BASE_DIR") exts = options.get("optimize", False) and "*.py[co]" or "*.pyc" for root, dirs, filenames in os.walk(project_root): for filename in fnmatch.filter(filenames, exts): full_path = _j(root, filename) if verbosity > 1: self.stdout.write("%s\n" % full_path) os.remove(full_path)
def handle_noargs(self, **options): project_root = options.get("path", None) if not project_root: project_root = get_project_root() exts = options.get("optimize", False) and [".pyc", ".pyo"] or [".pyc"] verbose = int(options.get("verbosity", 1)) if verbose > 1: print "Project Root: %s" % project_root for root, dirs, files in os.walk(project_root): for file in files: ext = os.path.splitext(file)[1] if ext in exts: full_path = _j(root, file) if verbose > 1: print full_path os.remove(full_path)
def memoize_newer_than_subdirs(func, args, pickle_file, directory): """ A pickle_file is invalid if at least one subdirectory is newer than it. """ pickle_mtime = os.path.getmtime(pickle_file) for d in os.listdir(directory): d_path = _j(directory, d) if not os.path.isdir(d_path) or \ os.path.basename(d_path) in [ # These change all the time. Ignore them. '.git', 'shadow_library', 'paper', 'generated', ]: continue if os.path.getmtime(d_path) > pickle_mtime: # print ("INVALID: {d_path} > {pickle_file}".format(**locals())) return False # Valid return True
def handle_noargs(self, **options): from django.conf import settings if settings.BUILT: settings.LOG.info("Installation built by build process; skipping clean_pyc") return project_root = options.get("path", None) if not project_root: project_root = get_project_root() exts = options.get("optimize", False) and [".pyc", ".pyo"] or [".pyc"] verbose = int(options.get("verbosity", 1)) if verbose > 1: print "Project Root: %s" % project_root for root, dirs, files in os.walk(project_root): for file in files: ext = os.path.splitext(file)[1] if ext in exts: full_path = _j(root, file) if verbose > 1: print full_path os.remove(full_path)
def each_file(self): for dirpath, dirnames, filenames in os.walk(self.directory): for base in filenames: path = _j(dirpath, base) if self.is_venn_js_path(path) or self.is_js_path(path): yield path
distributed with RL-Scope python wheel. """ from rlscope.profiler.rlscope_logging import logger import sys import textwrap import os from os.path import join as _j, abspath as _a, exists as _e, dirname as _d, basename as _b from rlscope.profiler.util import print_cmd import rlscope DEBUG = False INSTALL_ROOT = _d(os.path.realpath(rlscope.__file__)) CPP_LIB = _j(INSTALL_ROOT, 'cpp', 'lib') CPP_BIN = _j(INSTALL_ROOT, 'cpp', 'bin') CPP_INCLUDE = _j(INSTALL_ROOT, 'cpp', 'include') def execve_rlscope_binary(binary): exe_path = _j(CPP_BIN, binary) if not os.path.exists(exe_path): logger.error("Couldn't find {bin} binary @ {path}".format( bin=binary, path=exe_path, )) sys.exit(1) cmd = [exe_path] + sys.argv[1:] if DEBUG: print_cmd(cmd) env = dict(os.environ)
class Fallout3GameInfo(GameInfo): displayName = u'Fallout 3' fsName = u'Fallout3' altName = u'Wrye Flash' bash_root_prefix = u'Fallout3' launch_exe = u'Fallout3.exe' game_detect_file = u'Fallout3.exe' version_detect_file = u'Fallout3.exe' master_file = u'Fallout3.esm' pklfile = u'Fallout3_ids.pkl' masterlist_dir = u'Fallout3' regInstallKeys = (u'Bethesda Softworks\\Fallout3',u'Installed Path') nexusUrl = u'https://www.nexusmods.com/fallout3/' nexusName = u'Fallout 3 Nexus' nexusKey = u'bash.installers.openFallout3Nexus' using_txt_file = False plugin_name_specific_dirs = GameInfo.plugin_name_specific_dirs + [ _j(u'textures', u'characters', u'BodyMods'), _j(u'textures', u'characters', u'FaceMods')] class Ck(GameInfo.Ck): ck_abbrev = u'GECK' long_name = u'Garden of Eden Creation Kit' exe = u'GECK.exe' se_args = u'-editor' image_name = u'geck%s.png' class Se(GameInfo.Se): se_abbrev = u'FOSE' long_name = u'Fallout 3 Script Extender' exe = u'fose_loader.exe' # There is no fose_steam_loader.dll, so we have to list all included # DLLs, since people could delete any DLL not matching the game version # they're using ver_files = [u'fose_loader.exe', u'fose_1_7ng.dll', u'fose_1_7.dll', u'fose_1_6.dll', u'fose_1_5.dll', u'fose_1_4b.dll', u'fose_1_4.dll', u'fose_1_1.dll', u'fose_1_0.dll'] plugin_dir = u'FOSE' cosave_tag = u'FOSE' cosave_ext = u'.fose' url = u'http://fose.silverlock.org/' url_tip = u'http://fose.silverlock.org/' class Ini(GameInfo.Ini): allow_new_lines = False bsa_redirection_key = (u'Archive', u'sArchiveList') default_ini_file = u'Fallout_default.ini' dropdown_inis = [u'Fallout.ini', u'FalloutPrefs.ini'] supports_mod_inis = False class Ess(GameInfo.Ess): ext = u'.fos' class Bsa(GameInfo.Bsa): allow_reset_timestamps = True # ArchiveInvalidation Invalidated, which we shipped unmodified for a # long time, uses an Oblivion BSA with version 0x67, so we have to # accept those here as well valid_versions = {0x67, 0x68} class Xe(GameInfo.Xe): full_name = u'FO3Edit' xe_key_prefix = u'fo3View' class Bain(GameInfo.Bain): data_dirs = GameInfo.Bain.data_dirs | { u'config', # mod config files (INIs) u'distantlod', u'docs', u'facegen', u'fonts', u'fose', u'menus', u'uio', # User Interface Organizer u'scripts', u'shaders', u'trees', } keep_data_dirs = {u'LSData'} keep_data_files = {u'Fallout - AI!.bsa'} skip_bain_refresh = {u'fo3edit backups', u'fo3edit cache'} wrye_bash_data_files = {u'ArchiveInvalidationInvalidated!.bsa'} class Esp(GameInfo.Esp): canBash = True canEditHeader = True validHeaderVersions = (0.85, 0.94) stringsFiles = [] generate_temp_child_onam = True # Remaining to add: # 'Body-F', 'Body-M', 'Body-Size-F', 'Body-Size-M', 'Eyes', 'Hair', # 'R.Attributes-F', 'R.Attributes-M', 'R.Description', 'R.Ears', 'R.Head', # 'R.Mouth', 'R.Relations', 'R.Skills', 'R.Teeth', 'Voice-F', 'Voice-M' allTags = { u'Actors.ACBS', u'Actors.AIData', u'Actors.AIPackages', u'Actors.AIPackagesForceAdd', u'Actors.Anims', u'Actors.CombatStyle', u'Actors.DeathItem', u'Actors.RecordFlags', u'Actors.Skeleton', u'Actors.Spells', u'Actors.SpellsForceAdd', u'Actors.Stats', u'C.Acoustic', u'C.Climate', u'C.Encounter', u'C.ForceHideLand', u'C.ImageSpace', u'C.Light', u'C.Music', u'C.Name', u'C.Owner', u'C.RecordFlags', u'C.Regions', u'C.Water', u'Creatures.Blood', u'Creatures.Type', u'Deactivate', u'Deflst', u'Delev', u'Destructible', u'EffectStats', u'EnchantmentStats', u'Factions', u'Filter', u'Graphics', u'Invent.Add', u'Invent.Change', u'Invent.Remove', u'MustBeActiveIfImported', u'Names', u'NoMerge', u'NPC.Class', u'NPC.Eyes', u'NPC.FaceGen', u'NPC.Hair', u'NPC.Race', u'NpcFacesForceFullImport', u'ObjectBounds', u'Relations.Add', u'Relations.Change', u'Relations.Remove', u'Relev', u'Scripts', u'Sound', u'SpellStats', u'Stats', u'Text', } # Remaining to add: # AssortedTweaker, NamesTweaker, RacePatcher, UpdateReferences patchers = ( u'PatchMerger', # PatchMerger must come first! u'ActorImporter', u'AliasesPatcher', u'CellImporter', u'ContentsChecker', u'DeathItemPatcher', u'DestructiblePatcher', u'FidListsMerger', u'GmstTweaker', u'GraphicsPatcher', u'ImportActorsSpells', u'ImportEffectsStats', u'ImportEnchantmentStats', u'ImportFactions', u'ImportInventory', u'ImportRelations', u'ImportScripts', u'KFFZPatcher', u'ListsMerger', u'NamesPatcher', u'NPCAIPackagePatcher', u'NpcFacePatcher', u'ObjectBoundsImporter', u'SoundPatcher', u'SpellsPatcher', u'StatsPatcher', u'TextImporter', u'TweakActors', ) weaponTypes = ( _(u'Big gun'), _(u'Energy'), _(u'Small gun'), _(u'Melee'), _(u'Unarmed'), _(u'Thrown'), _(u'Mine'), ) raceNames = { 0x000019 : _(u'Caucasian'), 0x0038e5 : _(u'Hispanic'), 0x0038e6 : _(u'Asian'), 0x003b3e : _(u'Ghoul'), 0x00424a : _(u'AfricanAmerican'), 0x0042be : _(u'AfricanAmerican Child'), 0x0042bf : _(u'AfricanAmerican Old'), 0x0042c0 : _(u'Asian Child'), 0x0042c1 : _(u'Asian Old'), 0x0042c2 : _(u'Caucasian Child'), 0x0042c3 : _(u'Caucasian Old'), 0x0042c4 : _(u'Hispanic Child'), 0x0042c5 : _(u'Hispanic Old'), 0x04bb8d : _(u'Caucasian Raider'), 0x04bf70 : _(u'Hispanic Raider'), 0x04bf71 : _(u'Asian Raider'), 0x04bf72 : _(u'AfricanAmerican Raider'), 0x0987dc : _(u'Hispanic Old Aged'), 0x0987dd : _(u'Asian Old Aged'), 0x0987de : _(u'AfricanAmerican Old Aged'), 0x0987df : _(u'Caucasian Old Aged'), } raceShortNames = { 0x000019 : u'Cau', 0x0038e5 : u'His', 0x0038e6 : u'Asi', 0x003b3e : u'Gho', 0x00424a : u'Afr', 0x0042be : u'AfC', 0x0042bf : u'AfO', 0x0042c0 : u'AsC', 0x0042c1 : u'AsO', 0x0042c2 : u'CaC', 0x0042c3 : u'CaO', 0x0042c4 : u'HiC', 0x0042c5 : u'HiO', 0x04bb8d : u'CaR', 0x04bf70 : u'HiR', 0x04bf71 : u'AsR', 0x04bf72 : u'AfR', 0x0987dc : u'HOA', 0x0987dd : u'AOA', 0x0987de : u'FOA', 0x0987df : u'COA', } raceHairMale = { 0x000019 : 0x014b90, #--Cau 0x0038e5 : 0x0a9d6f, #--His 0x0038e6 : 0x014b90, #--Asi 0x003b3e : None, #--Gho 0x00424a : 0x0306be, #--Afr 0x0042be : 0x060232, #--AfC 0x0042bf : 0x0306be, #--AfO 0x0042c0 : 0x060232, #--AsC 0x0042c1 : 0x014b90, #--AsO 0x0042c2 : 0x060232, #--CaC 0x0042c3 : 0x02bfdb, #--CaO 0x0042c4 : 0x060232, #--HiC 0x0042c5 : 0x02ddee, #--HiO 0x04bb8d : 0x02bfdb, #--CaR 0x04bf70 : 0x02bfdb, #--HiR 0x04bf71 : 0x02bfdb, #--AsR 0x04bf72 : 0x0306be, #--AfR 0x0987dc : 0x0987da, #--HOA 0x0987dd : 0x0987da, #--AOA 0x0987de : 0x0987d9, #--FOA 0x0987df : 0x0987da, #--COA } raceHairFemale = { 0x000019 : 0x05dc6b, #--Cau 0x0038e5 : 0x05dc76, #--His 0x0038e6 : 0x022e50, #--Asi 0x003b3e : None, #--Gho 0x00424a : 0x05dc78, #--Afr 0x0042be : 0x05a59e, #--AfC 0x0042bf : 0x072e39, #--AfO 0x0042c0 : 0x05a5a3, #--AsC 0x0042c1 : 0x072e39, #--AsO 0x0042c2 : 0x05a59e, #--CaC 0x0042c3 : 0x072e39, #--CaO 0x0042c4 : 0x05a59e, #--HiC 0x0042c5 : 0x072e39, #--HiO 0x04bb8d : 0x072e39, #--CaR 0x04bf70 : 0x072e39, #--HiR 0x04bf71 : 0x072e39, #--AsR 0x04bf72 : 0x072e39, #--AfR 0x0987dc : 0x044529, #--HOA 0x0987dd : 0x044529, #--AOA 0x0987de : 0x044529, #--FOA 0x0987df : 0x044529, #--COA } @classmethod def init(cls): cls._dynamic_import_modules(__name__) from .records import MreActi, MreAddn, MreAlch, MreAmmo, MreAnio, \ MreArma, MreArmo, MreAspc, MreAvif, MreBook, MreBptd, MreCams, \ MreClas, MreClmt, MreCobj, MreCont, MreCpth, MreCrea, MreCsty, \ MreDebr, MreDobj, MreDoor, MreEczn, MreEfsh, MreEnch, MreExpl, \ MreEyes, MreFact, MreFurn, MreGras, MreHair, MreHdpt, MreTes4, \ MreIdle, MreIdlm, MreImad, MreImgs, MreIngr, MreIpct, MreIpds, \ MreKeym, MreLgtm, MreLigh, MreLscr, MreLtex, MreLvlc, MreLvli, \ MreLvln, MreMesg, MreMgef, MreMicn, MreMisc, MreMstt, MreMusc, \ MreNote, MreNpc, MrePack, MrePerk, MreProj, MrePwat, MreQust, \ MreRace, MreRads, MreRegn, MreRgdl, MreScol, MreScpt, MreSoun, \ MreSpel, MreStat, MreTact, MreTerm, MreTree, MreTxst, MreVtyp, \ MreWatr, MreWeap, MreWthr, MreAchr, MreAcre, MreCell, MreDial, \ MreGmst, MreInfo, MreNavi, MreNavm, MrePgre, MrePmis, MreRefr, \ MreWrld cls.mergeClasses = ( MreActi, MreAddn, MreAlch, MreAmmo, MreAnio, MreArma, MreArmo, MreAspc, MreAvif, MreBook, MreBptd, MreCams, MreClas, MreClmt, MreCobj, MreCont, MreCpth, MreCrea, MreCsty, MreDebr, MreDobj, MreDoor, MreEczn, MreEfsh, MreEnch, MreExpl, MreEyes, MreFact, MreFlst, MreFurn, MreGlob, MreGras, MreHair, MreHdpt, MreIdle, MreIdlm, MreImad, MreImgs, MreIngr, MreIpct, MreIpds, MreKeym, MreLgtm, MreLigh, MreLscr, MreLtex, MreLvlc, MreLvli, MreLvln, MreMesg, MreMgef, MreMicn, MreMisc, MreMstt, MreMusc, MreNote, MreNpc, MrePack, MrePerk, MreProj, MrePwat, MreQust, MreRace, MreRads, MreRegn, MreRgdl, MreScol, MreScpt, MreSoun, MreSpel, MreStat, MreTact,MreTerm, MreTree, MreTxst, MreVtyp, MreWatr, MreWeap, MreWthr, MreGmst, ) # Setting RecordHeader class variables -------------------------------- header_type = brec.RecordHeader header_type.top_grup_sigs = [ b'GMST', b'TXST', b'MICN', b'GLOB', b'CLAS', b'FACT', b'HDPT', b'HAIR', b'EYES', b'RACE', b'SOUN', b'ASPC', b'MGEF', b'SCPT', b'LTEX', b'ENCH', b'SPEL', b'ACTI', b'TACT', b'TERM', b'ARMO', b'BOOK', b'CONT', b'DOOR', b'INGR', b'LIGH', b'MISC', b'STAT', b'SCOL', b'MSTT', b'PWAT', b'GRAS', b'TREE', b'FURN', b'WEAP', b'AMMO', b'NPC_', b'CREA', b'LVLC', b'LVLN', b'KEYM', b'ALCH', b'IDLM', b'NOTE', b'PROJ', b'LVLI', b'WTHR', b'CLMT', b'COBJ', b'REGN', b'NAVI', b'CELL', b'WRLD', b'DIAL', b'QUST', b'IDLE', b'PACK', b'CSTY', b'LSCR', b'ANIO', b'WATR', b'EFSH', b'EXPL', b'DEBR', b'IMGS', b'IMAD', b'FLST', b'PERK', b'BPTD', b'ADDN', b'AVIF', b'RADS', b'CAMS', b'CPTH', b'VTYP', b'IPCT', b'IPDS', b'ARMA', b'ECZN', b'MESG', b'RGDL', b'DOBJ', b'LGTM', b'MUSC', ] header_type.valid_header_sigs = set( header_type.top_grup_sigs + [b'GRUP', b'TES4', b'ACHR', b'ACRE', b'INFO', b'LAND', b'NAVM', b'PGRE', b'PMIS', b'REFR']) header_type.plugin_form_version = 15 brec.MreRecord.type_class = {x.rec_sig: x for x in (cls.mergeClasses + # Not Mergeable (MreAchr, MreAcre, MreCell, MreDial, MreInfo, MreNavi, MreNavm, MrePgre, MrePmis, MreRefr, MreWrld, MreTes4))} brec.MreRecord.simpleTypes = (set(brec.MreRecord.type_class) - { b'TES4', b'ACHR', b'ACRE', b'CELL', b'DIAL', b'INFO', b'LAND', b'NAVI', b'NAVM', b'PGRE', b'PMIS', b'REFR', b'WRLD'}) cls._validate_records()
class SkyrimGameInfo(PatchGame): displayName = u'Skyrim' fsName = u'Skyrim' altName = u'Wrye Smash' game_icon = u'skyrim_%u.png' bash_root_prefix = u'Skyrim' bak_game_name = u'Skyrim' my_games_name = u'Skyrim' appdata_name = u'Skyrim' launch_exe = u'TESV.exe' # Set to this because TESV.exe also exists for Enderal game_detect_includes = [u'SkyrimLauncher.exe'] version_detect_file = u'TESV.exe' master_file = u'Skyrim.esm' taglist_dir = u'Skyrim' loot_dir = u'Skyrim' boss_game_name = u'Skyrim' regInstallKeys = (u'Bethesda Softworks\\Skyrim', u'Installed Path') nexusUrl = u'https://www.nexusmods.com/skyrim/' nexusName = u'Skyrim Nexus' nexusKey = u'bash.installers.openSkyrimNexus.continue' plugin_name_specific_dirs = GameInfo.plugin_name_specific_dirs + [ _j(u'meshes', u'actors', u'character', u'facegendata', u'facegeom'), _j(u'textures', u'actors', u'character', u'facegendata', u'facetint')] class Ck(GameInfo.Ck): ck_abbrev = u'CK' long_name = u'Creation Kit' exe = u'CreationKit.exe' image_name = u'creationkit%s.png' class Se(GameInfo.Se): se_abbrev = u'SKSE' long_name = u'Skyrim Script Extender' exe = u'skse_loader.exe' ver_files = [u'skse_loader.exe', u'skse_steam_loader.dll'] plugin_dir = u'SKSE' cosave_tag = u'SKSE' cosave_ext = u'.skse' url = u'http://skse.silverlock.org/' url_tip = u'http://skse.silverlock.org/' class Sd(GameInfo.Sd): sd_abbrev = u'SD' long_name = u'Script Dragon' install_dir = u'asi' class Sp(GameInfo.Sp): sp_abbrev = u'SP' long_name = u'SkyProc' install_dir = u'SkyProc Patchers' class Ini(GameInfo.Ini): default_ini_file = u'Skyrim_default.ini' dropdown_inis = [u'Skyrim.ini', u'SkyrimPrefs.ini'] resource_archives_keys = (u'sResourceArchiveList', u'sResourceArchiveList2') class Bsa(GameInfo.Bsa): # Skyrim only accepts the base name attachment_regex = u'' has_bsl = True valid_versions = {0x68} class Psc(GameInfo.Psc): source_extensions = {u'.psc'} # In SSE Bethesda made the mistake of packaging the CK's script source # as 'source/scripts' instead of 'scripts/source'. The CK even still # expects the sources to be in 'scripts/source', so you'd have to edit # its INI if you wanted to use 'source/scripts'. However, some modders # have nonetheless adopted this convention, so to support this we # redirect them to the correct path while scanning the package in BAIN. # Sits here because the situation then got worse - some modders have # started packaging 'source' dirs even in Skyrim LE. source_redirects = { _j(u'source', u'scripts'): _j(u'scripts', u'source'), u'source': _j(u'scripts', u'source'), } class Xe(GameInfo.Xe): full_name = u'TES5Edit' xe_key_prefix = u'tes5View' class Bain(GameInfo.Bain): data_dirs = GameInfo.Bain.data_dirs | { u'asi', # script dragon u'calientetools', # bodyslide u'dialogueviews', u'dyndolod', u'grass', u'interface', u'lodsettings', u'scripts', u'seq', u'shadersfx', u'skse', u'skyproc patchers', u'slanims', # nsfw mods u'source', # see Psc.source_redirects above u'strings', u'tools', # FNIS } keep_data_dirs = {u'LSData'} no_skip = ( # These are all in the Interface folder. Apart from the skyui_ # files, they are all present in vanilla. u'skyui_cfg.txt', u'skyui_translate.txt', u'credits.txt', u'credits_french.txt', u'fontconfig.txt', u'controlmap.txt', u'gamepad.txt', u'mouse.txt', u'keyboard_english.txt', u'keyboard_french.txt', u'keyboard_german.txt', u'keyboard_spanish.txt', u'keyboard_italian.txt', ) no_skip_dirs = GameInfo.Bain.no_skip_dirs.copy() # PY3: dict join no_skip_dirs.update({ # This rule is to allow mods with string translation enabled. _j(u'interface', u'translations'): [u'.txt'] }) skip_bain_refresh = {u'tes5edit backups', u'tes5edit cache'} class Esp(GameInfo.Esp): canBash = True canEditHeader = True validHeaderVersions = (0.94, 1.70,) generate_temp_child_onam = True max_lvl_list_size = 255 biped_flag_names = ( u'head', u'hair', u'body', u'hands', u'forearms', u'amulet', u'ring', u'feet', u'calves', u'shield', u'bodyaddon1_tail', u'long_hair', u'circlet', u'bodyaddon2', u'dragon_head', u'dragon_lwing', u'dragon_rwing', u'dragon_body', u'bodyaddon7', u'bodyaddon8', u'decapate_head', u'decapate', u'bodyaddon9', u'bodyaddon10', u'bodyaddon11', u'bodyaddon12', u'bodyaddon13', u'bodyaddon14', u'bodyaddon15', u'bodyaddon16', u'bodyaddon17', u'fx01') reference_types = {b'ACHR', b'PARW', b'PBAR', b'PBEA', b'PCON', b'PFLA', b'PGRE', b'PHZD', b'PMIS', b'REFR'} allTags = PatchGame.allTags | {u'NoMerge'} patchers = { u'AliasModNames', u'ContentsChecker', u'ImportActors', u'ImportRaces', u'ImportActorsAIPackages', u'ImportActorsDeathItems', u'ImportActorsFactions', u'ImportActorsSpells', u'ImportCells', u'ImportDestructible', u'ImportEffectsStats', u'ImportRacesSpells', u'ImportEnchantmentStats', u'ImportGraphics', u'ImportInventory', u'ImportKeywords', u'ImportNames', u'ImportObjectBounds', u'ImportOutfits', u'ImportRelations', u'ImportSounds', u'ImportSpellStats', u'ImportStats', u'ImportText', u'LeveledLists', u'MergePatches', u'TweakActors', u'TweakAssorted', u'TweakSettings', u'TweakRaces', u'ImportActorsPerks', u'TimescaleChecker', } weaponTypes = ( _(u'Blade (1 Handed)'), _(u'Blade (2 Handed)'), _(u'Blunt (1 Handed)'), _(u'Blunt (2 Handed)'), _(u'Staff'), _(u'Bow'), ) raceNames = { 0x13740 : _(u'Argonian'), 0x13741 : _(u'Breton'), 0x13742 : _(u'Dark Elf'), 0x13743 : _(u'High Elf'), 0x13744 : _(u'Imperial'), 0x13745 : _(u'Khajiit'), 0x13746 : _(u'Nord'), 0x13747 : _(u'Orc'), 0x13748 : _(u'Redguard'), 0x13749 : _(u'Wood Elf'), } raceShortNames = { 0x13740 : u'Arg', 0x13741 : u'Bre', 0x13742 : u'Dun', 0x13743 : u'Alt', 0x13744 : u'Imp', 0x13745 : u'Kha', 0x13746 : u'Nor', 0x13747 : u'Orc', 0x13748 : u'Red', 0x13749 : u'Bos', } raceHairMale = { 0x13740 : 0x64f32, #--Arg 0x13741 : 0x90475, #--Bre 0x13742 : 0x64214, #--Dun 0x13743 : 0x7b792, #--Alt 0x13744 : 0x90475, #--Imp 0x13745 : 0x653d4, #--Kha 0x13746 : 0x1da82, #--Nor 0x13747 : 0x66a27, #--Orc 0x13748 : 0x64215, #--Red 0x13749 : 0x690bc, #--Bos } raceHairFemale = { 0x13740 : 0x64f33, #--Arg 0x13741 : 0x1da83, #--Bre 0x13742 : 0x1da83, #--Dun 0x13743 : 0x690c2, #--Alt 0x13744 : 0x1da83, #--Imp 0x13745 : 0x653d0, #--Kha 0x13746 : 0x1da83, #--Nor 0x13747 : 0x64218, #--Orc 0x13748 : 0x64210, #--Red 0x13749 : 0x69473, #--Bos } bethDataFiles = { #--Vanilla u'skyrim.esm', u'update.esm', u'update.bsa', u'dawnguard.esm', u'dawnguard.bsa', u'hearthfires.bsa', u'hearthfires.esm', u'dragonborn.esm', u'dragonborn.bsa', u'skyrim - animations.bsa', u'skyrim - interface.bsa', u'skyrim - meshes.bsa', u'skyrim - misc.bsa', u'skyrim - shaders.bsa', u'skyrim - sounds.bsa', u'skyrim - textures.bsa', u'skyrim - voices.bsa', u'skyrim - voicesextra.bsa', u'highrestexturepack01.esp', u'highrestexturepack02.esp', u'highrestexturepack03.esp', u'highrestexturepack01.bsa', u'highrestexturepack02.bsa', u'highrestexturepack03.bsa', } _patcher_package = u'bash.game.skyrim' @classmethod def init(cls): cls._dynamic_import_modules(__name__) from .records import MreCell, MreWrld, MreFact, MreAchr, MreDial, \ MreInfo, MreCams, MreWthr, MreDual, MreMato, MreVtyp, MreMatt, \ MreLvsp, MreEnch, MreProj, MreDlbr, MreRfct, MreMisc, MreActi, \ MreEqup, MreCpth, MreDoor, MreAnio, MreHazd, MreIdlm, MreEczn, \ MreIdle, MreLtex, MreQust, MreMstt, MreNpc, MreIpds, MrePack, \ MreGmst, MreRevb, MreClmt, MreDebr, MreSmbn, MreLvli, MreSpel, \ MreKywd, MreLvln, MreAact, MreSlgm, MreRegn, MreFurn, MreGras, \ MreAstp, MreWoop, MreMovt, MreCobj, MreShou, MreSmen, MreColl, \ MreArto, MreAddn, MreSopm, MreCsty, MreAppa, MreArma, MreArmo, \ MreKeym, MreTxst, MreHdpt, MreTes4, MreAlch, MreBook, MreSpgd, \ MreSndr, MreImgs, MreScrl, MreMust, MreFstp, MreFsts, MreMgef, \ MreLgtm, MreMusc, MreClas, MreLctn, MreTact, MreBptd, MreDobj, \ MreLscr, MreDlvw, MreTree, MreWatr, MreFlor, MreEyes, MreWeap, \ MreIngr, MreClfm, MreMesg, MreLigh, MreExpl, MreLcrt, MreStat, \ MreAmmo, MreSmqn, MreImad, MreSoun, MreAvif, MreCont, MreIpct, \ MreAspc, MreRela, MreEfsh, MreSnct, MreOtft, MrePerk, MreRace # --------------------------------------------------------------------- # Unused records, they have empty GRUP in skyrim.esm------------------- # CLDC HAIR PWAT RGDL SCOL SCPT # --------------------------------------------------------------------- # These Are normally not mergeable but added to brec.MreRecord.type_class # # MreCell, # --------------------------------------------------------------------- # These have undefined FormIDs Do not merge them # # MreNavi, MreNavm, # --------------------------------------------------------------------- # These need syntax revision but can be merged once that is corrected # # MreAchr, MreDial, MreInfo, # --------------------------------------------------------------------- cls.mergeable_sigs = {clazz.rec_sig: clazz for clazz in (# MreAchr, MreDial, MreInfo, MreAact, MreActi, MreAddn, MreAlch, MreAmmo, MreAnio, MreAppa, MreArma, MreArmo, MreArto, MreAspc, MreAstp, MreAvif, MreBook, MreBptd, MreCams, MreClas, MreClfm, MreClmt, MreCobj, MreColl, MreCont, MreCpth, MreCsty, MreDebr, MreDlbr, MreDlvw, MreDobj, MreDoor, MreDual, MreEczn, MreEfsh, MreEnch, MreEqup, MreExpl, MreEyes, MreFlor, MreFlst, MreFstp, MreFsts, MreFurn, MreGlob, MreGmst, MreGras, MreHazd, MreHdpt, MreIdle, MreIdlm, MreImad, MreImgs, MreIngr, MreIpct, MreIpds, MreKeym, MreKywd, MreLcrt, MreLctn, MreLgtm, MreLigh, MreLscr, MreLtex, MreLvli, MreLvln, MreLvsp, MreMato, MreMatt, MreMesg, MreMgef, MreMisc, MreMovt, MreMstt, MreMusc, MreMust, MreNpc, MreOtft, MrePerk, MreProj, MreRegn, MreRela, MreRevb, MreRfct, MreScrl, MreShou, MreSlgm, MreSmbn, MreSmen, MreSmqn, MreSnct, MreSndr, MreSopm, MreSoun, MreSpel, MreSpgd, MreStat, MreTact, MreTree, MreTxst, MreVtyp, MreWatr, MreWeap, MreWoop, MreWthr, MreQust, MrePack, MreFact, MreRace, )} # MreScpt is Oblivion/FO3/FNV Only # MreMgef, has not been verified to be used here for Skyrim # Setting RecordHeader class variables -------------------------------- header_type = brec.RecordHeader header_type.top_grup_sigs = [ b'GMST', b'KYWD', b'LCRT', b'AACT', b'TXST', b'GLOB', b'CLAS', b'FACT', b'HDPT', b'HAIR', b'EYES', b'RACE', b'SOUN', b'ASPC', b'MGEF', b'SCPT', b'LTEX', b'ENCH', b'SPEL', b'SCRL', b'ACTI', b'TACT', b'ARMO', b'BOOK', b'CONT', b'DOOR', b'INGR', b'LIGH', b'MISC', b'APPA', b'STAT', b'SCOL', b'MSTT', b'PWAT', b'GRAS', b'TREE', b'CLDC', b'FLOR', b'FURN', b'WEAP', b'AMMO', b'NPC_', b'LVLN', b'KEYM', b'ALCH', b'IDLM', b'COBJ', b'PROJ', b'HAZD', b'SLGM', b'LVLI', b'WTHR', b'CLMT', b'SPGD', b'RFCT', b'REGN', b'NAVI', b'CELL', b'WRLD', b'DIAL', b'QUST', b'IDLE', b'PACK', b'CSTY', b'LSCR', b'LVSP', b'ANIO', b'WATR', b'EFSH', b'EXPL', b'DEBR', b'IMGS', b'IMAD', b'FLST', b'PERK', b'BPTD', b'ADDN', b'AVIF', b'CAMS', b'CPTH', b'VTYP', b'MATT', b'IPCT', b'IPDS', b'ARMA', b'ECZN', b'LCTN', b'MESG', b'RGDL', b'DOBJ', b'LGTM', b'MUSC', b'FSTP', b'FSTS', b'SMBN', b'SMQN', b'SMEN', b'DLBR', b'MUST', b'DLVW', b'WOOP', b'SHOU', b'EQUP', b'RELA', b'SCEN', b'ASTP', b'OTFT', b'ARTO', b'MATO', b'MOVT', b'SNDR', b'DUAL', b'SNCT', b'SOPM', b'COLL', b'CLFM', b'REVB', ] header_type.valid_header_sigs = set( header_type.top_grup_sigs + [b'GRUP', b'TES4', b'REFR', b'ACHR', b'ACRE', b'LAND', b'INFO', b'NAVM', b'PARW', b'PBAR', b'PBEA', b'PCON', b'PFLA', b'PGRE', b'PHZD', b'PMIS']) header_type.plugin_form_version = 43 brec.MreRecord.type_class = {x.rec_sig: x for x in ( MreAchr, MreDial, MreInfo, MreAact, MreActi, MreAddn, MreAlch, MreAmmo, MreAnio, MreAppa, MreArma, MreArmo, MreArto, MreAspc, MreAstp, MreAvif, MreBook, MreBptd, MreCams, MreClas, MreClfm, MreClmt, MreCobj, MreColl, MreCont, MreCpth, MreCsty, MreDebr, MreDlbr, MreDlvw, MreDobj, MreDoor, MreDual, MreEczn, MreEfsh, MreEnch, MreEqup, MreExpl, MreEyes, MreFact, MreFlor, MreFlst, MreFstp, MreFsts, MreFurn, MreGlob, MreGmst, MreGras, MreHazd, MreHdpt, MreIdle, MreIdlm, MreImad, MreImgs, MreIngr, MreIpct, MreIpds, MreKeym, MreKywd, MreLcrt, MreLctn, MreLgtm, MreLigh, MreLscr, MreLtex, MreLvli, MreLvln, MreLvsp, MreMato, MreMatt, MreMesg, MreMgef, MreMisc, MreMovt, MreMstt, MreMusc, MreMust, MreNpc, MreOtft, MrePerk, MreProj, MreRegn, MreRela, MreRevb, MreRfct, MreScrl, MreShou, MreSlgm, MreSmbn, MreSmen, MreSmqn, MreSnct, MreSndr, MreSopm, MreSoun, MreSpel, MreSpgd, MreStat, MreTact, MreTree, MreTxst, MreVtyp, MreWatr, MreWeap, MreWoop, MreWthr, MreCell, MreWrld, MreQust, MreTes4, MrePack, MreRace, # MreNavm, MreNavi )} brec.MreRecord.simpleTypes = ( set(brec.MreRecord.type_class) - {b'TES4', b'ACHR', b'CELL', b'DIAL', b'INFO', b'WRLD'}) cls._validate_records()
class NehrimGameInfo(OblivionGameInfo): displayName = u'Nehrim' bash_root_prefix = u'Nehrim' game_detect_file = _j(u'Data', u'Nehrim.esm') master_file = u'Nehrim.esm' # pklfile = u'Nehrim_ids.pkl' # TODO new pickle nexusUrl = u'https://www.nexusmods.com/nehrim/' nexusName = u'Nehrim Nexus' nexusKey = u'bash.installers.openNehrimNexus.continue' # Oblivion minus Oblivion-specific patchers (Cobl Catalogs, Cobl # Exhaustion, Morph Factions and SEWorld Tests) patchers = tuple(p for p in OblivionGameInfo.patchers if p not in (u'AlchemicalCatalogs', u'CoblExhaustion', u'MFactMarker', u'SEWorldEnforcer')) CBash_patchers = tuple( p for p in OblivionGameInfo.CBash_patchers if p not in (u'CBash_AlchemicalCatalogs', u'CBash_CoblExhaustion', u'CBash_MFactMarker', u'CBash_SEWorldEnforcer')) raceNames = { 0x224fc: _(u'Alemanne'), 0x18d9e5: _(u'Half-Aeterna'), 0x224fd: _(u'Normanne'), } raceShortNames = { 0x224fc: u'Ale', 0x18d9e5: u'Aet', 0x224fd: u'Nor', } raceHairMale = { 0x224fc: 0x90475, #--Ale 0x18d9e5: 0x5c6b, #--Aet 0x224fd: 0x1da82, #--Nor } raceHairFemale = { 0x224fc: 0x1da83, #--Ale 0x18d9e5: 0x3e1e, #--Aet 0x224fd: 0x1da83, #--Nor } @classmethod def init(cls): cls._dynamic_import_modules(__name__) from .records import MreActi, MreAlch, MreAmmo, MreAnio, MreAppa, \ MreArmo, MreBook, MreBsgn, MreClas, MreClot, MreCont, MreCrea, \ MreDoor, MreEfsh, MreEnch, MreEyes, MreFact, MreFlor, MreFurn, \ MreGras, MreHair, MreIngr, MreKeym, MreLigh, MreLscr, MreLvlc, \ MreLvli, MreLvsp, MreMgef, MreMisc, MreNpc, MrePack, MreQust, \ MreRace, MreScpt, MreSgst, MreSlgm, MreSoun, MreSpel, MreStat, \ MreTree, MreWatr, MreWeap, MreWthr, MreClmt, MreCsty, MreIdle, \ MreLtex, MreRegn, MreSbsp, MreSkil, MreAchr, MreAcre, MreCell, \ MreGmst, MreRefr, MreRoad, MreTes4, MreWrld, MreDial, MreInfo, \ MrePgrd cls.mergeClasses = ( MreActi, MreAlch, MreAmmo, MreAnio, MreAppa, MreArmo, MreBook, MreBsgn, MreClas, MreClot, MreCont, MreCrea, MreDoor, MreEfsh, MreEnch, MreEyes, MreFact, MreFlor, MreFurn, MreGlob, MreGras, MreHair, MreIngr, MreKeym, MreLigh, MreLscr, MreLvlc, MreLvli, MreLvsp, MreMgef, MreMisc, MreNpc, MrePack, MreQust, MreRace, MreScpt, MreSgst, MreSlgm, MreSoun, MreSpel, MreStat, MreTree, MreWatr, MreWeap, MreWthr, MreClmt, MreCsty, MreIdle, MreLtex, MreRegn, MreSbsp, MreSkil, MreAchr, MreAcre, MreCell, MreGmst, MreRefr, MreRoad, MreWrld, MreDial, MreInfo, MreLand, MrePgrd, ) cls.readClasses = ( MreMgef, MreScpt, ) cls.writeClasses = (MreMgef, ) # Setting RecordHeader class variables - Oblivion is special header_type = brec.RecordHeader header_type.rec_header_size = 20 header_type.rec_pack_format = [u'=4s', u'I', u'I', u'I', u'I'] header_type.rec_pack_format_str = u''.join(header_type.rec_pack_format) header_type.header_unpack = struct.Struct( header_type.rec_pack_format_str).unpack header_type.pack_formats = {0: u'=4sI4s2I'} header_type.pack_formats.update( {x: u'=4s4I' for x in {1, 6, 7, 8, 9, 10}}) header_type.pack_formats.update({x: u'=4sIi2I' for x in {2, 3}}) header_type.pack_formats.update({x: u'=4sIhh2I' for x in {4, 5}}) # Similar to other games header_type.top_grup_sigs = [ b'GMST', b'GLOB', b'CLAS', b'FACT', b'HAIR', b'EYES', b'RACE', b'SOUN', b'SKIL', b'MGEF', b'SCPT', b'LTEX', b'ENCH', b'SPEL', b'BSGN', b'ACTI', b'APPA', b'ARMO', b'BOOK', b'CLOT', b'CONT', b'DOOR', b'INGR', b'LIGH', b'MISC', b'STAT', b'GRAS', b'TREE', b'FLOR', b'FURN', b'WEAP', b'AMMO', b'NPC_', b'CREA', b'LVLC', b'SLGM', b'KEYM', b'ALCH', b'SBSP', b'SGST', b'LVLI', b'WTHR', b'CLMT', b'REGN', b'CELL', b'WRLD', b'DIAL', b'QUST', b'IDLE', b'PACK', b'CSTY', b'LSCR', b'LVSP', b'ANIO', b'WATR', b'EFSH', ] header_type.valid_header_sigs = set(header_type.top_grup_sigs + [ b'GRUP', b'TES4', b'ROAD', b'REFR', b'ACHR', b'ACRE', b'PGRD', b'LAND', b'INFO' ]) brec.MreRecord.type_class = { x.rec_sig: x for x in (MreAchr, MreAcre, MreActi, MreAlch, MreAmmo, MreAnio, MreAppa, MreArmo, MreBook, MreBsgn, MreCell, MreClas, MreClot, MreCont, MreCrea, MreDoor, MreEfsh, MreEnch, MreEyes, MreFact, MreFlor, MreFurn, MreGlob, MreGmst, MreGras, MreHair, MreIngr, MreKeym, MreLigh, MreLscr, MreLvlc, MreLvli, MreLvsp, MreMgef, MreMisc, MreNpc, MrePack, MreQust, MreRace, MreRefr, MreRoad, MreScpt, MreSgst, MreSkil, MreSlgm, MreSoun, MreSpel, MreStat, MreTree, MreTes4, MreWatr, MreWeap, MreWrld, MreWthr, MreClmt, MreCsty, MreIdle, MreLtex, MreRegn, MreSbsp, MreDial, MreInfo, MreLand, MrePgrd) } brec.MreRecord.simpleTypes = (set(brec.MreRecord.type_class) - { b'TES4', b'ACHR', b'ACRE', b'REFR', b'CELL', b'PGRD', b'ROAD', b'LAND', b'WRLD', b'INFO', b'DIAL' }) cls._validate_records()
class Fallout4GameInfo(GameInfo): displayName = u'Fallout 4' fsName = u'Fallout4' altName = u'Wrye Flash' bash_root_prefix = u'Fallout4' launch_exe = u'Fallout4.exe' game_detect_file = u'Fallout4.exe' version_detect_file = u'Fallout4.exe' master_file = u'Fallout4.esm' pklfile = u'Fallout4_ids.pkl' masterlist_dir = u'Fallout4' regInstallKeys = (u'Bethesda Softworks\\Fallout4', u'Installed Path') nexusUrl = u'https://www.nexusmods.com/fallout4/' nexusName = u'Fallout 4 Nexus' nexusKey = 'bash.installers.openFallout4Nexus.continue' espm_extensions = GameInfo.espm_extensions | {u'.esl'} has_achlist = True check_esl = True plugin_name_specific_dirs = GameInfo.plugin_name_specific_dirs + [ _j(u'meshes', u'actors', u'character', u'facegendata', u'facegeom'), _j(u'meshes', u'actors', u'character', u'facecustomization') ] class Ck(GameInfo.Ck): ck_abbrev = u'CK' long_name = u'Creation Kit' exe = u'CreationKit.exe' image_name = u'creationkit%s.png' class Se(GameInfo.Se): se_abbrev = u'F4SE' long_name = u'Fallout 4 Script Extender' exe = u'f4se_loader.exe' ver_files = [u'f4se_loader.exe', u'f4se_steam_loader.dll'] plugin_dir = u'F4SE' cosave_tag = u'F4SE' cosave_ext = u'.f4se' url = u'http://f4se.silverlock.org/' url_tip = u'http://f4se.silverlock.org/' class Ini(GameInfo.Ini): default_ini_file = u'Fallout4_default.ini' dropdown_inis = [u'Fallout4.ini', u'Fallout4Prefs.ini'] resource_archives_keys = (u'sResourceIndexFileList', u'sResourceStartUpArchiveList', u'sResourceArchiveList', u'sResourceArchiveList2', u'sResourceArchiveListBeta') class Ess(GameInfo.Ess): ext = u'.fos' class Bsa(GameInfo.Bsa): bsa_extension = u'.ba2' valid_versions = {0x01} vanilla_string_bsas = { u'fallout4.esm': [u'Fallout4 - Interface.ba2'], u'dlcrobot.esm': [u'DLCRobot - Main.ba2'], u'dlcworkshop01.esm': [u'DLCworkshop01 - Main.ba2'], u'dlcworkshop02.esm': [u'DLCworkshop02 - Main.ba2'], u'dlcworkshop03.esm': [u'DLCworkshop03 - Main.ba2'], u'dlccoast.esm': [u'DLCCoast - Main.ba2'], u'dlcnukaworld.esm': [u'DLCNukaWorld - Main.ba2'], } class Psc(GameInfo.Psc): source_extensions = {u'.psc'} class Xe(GameInfo.Xe): full_name = u'FO4Edit' xe_key_prefix = u'fo4View' class Bain(GameInfo.Bain): data_dirs = GameInfo.Bain.data_dirs | { u'f4se', u'interface', u'lodsettings', u'materials', u'mcm', # FO4 MCM u'misc', u'programs', u'scripts', u'seq', u'shadersfx', u'strings', u'tools', # bodyslide u'vis', } no_skip_dirs = { # This rule is to allow mods with string translation enabled. _j(u'interface', u'translations'): [u'.txt'] } skip_bain_refresh = {u'fo4edit backups', u'fo4edit cache'} class Esp(GameInfo.Esp): canBash = True canEditHeader = True validHeaderVersions = (0.95, 1.0) expanded_plugin_range = True max_lvl_list_size = 255 allTags = { u'Deactivate', u'Delev', u'Filter', u'ObjectBounds', u'Relev', } patchers = ( # PatchMerger must come first if enabled! u'ListsMerger', u'ObjectBoundsImporter', ) # --------------------------------------------------------------------- # --Imported - MreGlob is special import, not in records.py # --------------------------------------------------------------------- @classmethod def init(cls): cls._dynamic_import_modules(__name__) # First import from fallout4.records file, so MelModel is set correctly from .records import MreGmst, MreTes4, MreLvli, MreLvln # --------------------------------------------------------------------- # These Are normally not mergable but added to brec.MreRecord.type_class # # MreCell, # --------------------------------------------------------------------- # These have undefined FormIDs Do not merge them # # MreNavi, MreNavm, # --------------------------------------------------------------------- # These need syntax revision but can be merged once that is corrected # # MreAchr, MreDial, MreLctn, MreInfo, MreFact, MrePerk, # --------------------------------------------------------------------- cls.mergeClasses = ( # -- Imported from Skyrim/SkyrimSE # Added to records.py MreGmst, MreLvli, MreLvln) # Setting RecordHeader class variables -------------------------------- header_type = brec.RecordHeader header_type.top_grup_sigs = [ b'GMST', b'KYWD', b'LCRT', b'AACT', b'TRNS', b'CMPO', b'TXST', b'GLOB', b'DMGT', b'CLAS', b'FACT', b'HDPT', b'RACE', b'SOUN', b'ASPC', b'MGEF', b'LTEX', b'ENCH', b'SPEL', b'ACTI', b'TACT', b'ARMO', b'BOOK', b'CONT', b'DOOR', b'INGR', b'LIGH', b'MISC', b'STAT', b'SCOL', b'MSTT', b'GRAS', b'TREE', b'FLOR', b'FURN', b'WEAP', b'AMMO', b'NPC_', b'PLYR', b'LVLN', b'KEYM', b'ALCH', b'IDLM', b'NOTE', b'PROJ', b'HAZD', b'BNDS', b'TERM', b'LVLI', b'WTHR', b'CLMT', b'SPGD', b'RFCT', b'REGN', b'NAVI', b'CELL', b'WRLD', b'QUST', b'IDLE', b'PACK', b'CSTY', b'LSCR', b'LVSP', b'ANIO', b'WATR', b'EFSH', b'EXPL', b'DEBR', b'IMGS', b'IMAD', b'FLST', b'PERK', b'BPTD', b'ADDN', b'AVIF', b'CAMS', b'CPTH', b'VTYP', b'MATT', b'IPCT', b'IPDS', b'ARMA', b'ECZN', b'LCTN', b'MESG', b'DOBJ', b'DFOB', b'LGTM', b'MUSC', b'FSTP', b'FSTS', b'SMBN', b'SMQN', b'SMEN', b'DLBR', b'MUST', b'DLVW', b'EQUP', b'RELA', b'SCEN', b'ASTP', b'OTFT', b'ARTO', b'MATO', b'MOVT', b'SNDR', b'SNCT', b'SOPM', b'COLL', b'CLFM', b'REVB', b'PKIN', b'RFGP', b'AMDL', b'LAYR', b'COBJ', b'OMOD', b'MSWP', b'ZOOM', b'INNR', b'KSSM', b'AECH', b'SCCO', b'AORU', b'SCSN', b'STAG', b'NOCM', b'LENS', b'GDRY', b'OVIS', ] header_type.valid_header_sigs = (set(header_type.top_grup_sigs) | { b'GRUP', b'TES4', b'REFR', b'ACHR', b'PMIS', b'PARW', b'PGRE', b'PBEA', b'PFLA', b'PCON', b'PBAR', b'PHZD', b'LAND', b'NAVM', b'DIAL', b'INFO' }) header_type.plugin_form_version = 131 brec.MreRecord.type_class = { x.rec_sig: x for x in ( MreTes4, #--Always present MreGmst, # Imported from Skyrim or SkyrimSE MreLvli, MreLvln, # Added to records.py ) } brec.MreRecord.simpleTypes = (set(brec.MreRecord.type_class) - {b'TES4'}) cls._validate_records()
class OblivionGameInfo(PatchGame): displayName = u'Oblivion' fsName = u'Oblivion' altName = u'Wrye Bash' game_icon = u'oblivion_%u.png' bash_root_prefix = u'Oblivion' bak_game_name = u'Oblivion' template_dir = u'Oblivion' bash_patches_dir = u'Oblivion' my_games_name = u'Oblivion' appdata_name = u'Oblivion' launch_exe = u'Oblivion.exe' # Set to this because that file does not exist in Nehrim, whereas # OblivionLauncher.exe and Oblivion.exe do game_detect_includes = [_j(u'Data', u'Oblivion.esm')] game_detect_excludes = WS_COMMON version_detect_file = u'Oblivion.exe' master_file = u'Oblivion.esm' taglist_dir = u'Oblivion' loot_dir = u'Oblivion' boss_game_name = u'Oblivion' regInstallKeys = (u'Bethesda Softworks\\Oblivion', u'Installed Path') nexusUrl = u'https://www.nexusmods.com/oblivion/' nexusName = u'Oblivion Nexus' nexusKey = u'bash.installers.openOblivionNexus.continue' patchURL = u'http://www.elderscrolls.com/downloads/updates_patches.htm' patchTip = u'http://www.elderscrolls.com/' using_txt_file = False has_standalone_pluggy = True class Ck(GameInfo.Ck): ck_abbrev = u'TESCS' long_name = u'Construction Set' exe = u'TESConstructionSet.exe' se_args = u'-editor' image_name = u'tescs%s.png' class Se(GameInfo.Se): se_abbrev = u'OBSE' long_name = u'Oblivion Script Extender' exe = u'obse_loader.exe' # Not sure why we need obse_1_2_416.dll, was there before refactoring ver_files = [u'obse_loader.exe', u'obse_steam_loader.dll', u'obse_1_2_416.dll'] plugin_dir = u'OBSE' cosave_tag = u'OBSE' cosave_ext = u'.obse' url = u'http://obse.silverlock.org/' url_tip = u'http://obse.silverlock.org/' limit_fixer_plugins = [u'mod_limit_fix.dll', u'Trifle.dll'] class Ge(GameInfo.Ge): ge_abbrev = u'OBGE' long_name = u'Oblivion Graphics Extender' exe = [(u'obse', u'plugins', u'obge.dll'), (u'obse', u'plugins', u'obgev2.dll'), (u'obse', u'plugins', u'oblivionreloaded.dll'), ] url = u'https://www.nexusmods.com/oblivion/mods/30054' url_tip = u'https://www.nexusmods.com/oblivion' class Ini(GameInfo.Ini): allow_new_lines = False bsa_redirection_key = (u'Archive', u'sArchiveList') default_ini_file = u'Oblivion_default.ini' dropdown_inis = [u'Oblivion.ini'] supports_mod_inis = False class Ess(GameInfo.Ess): canEditMore = True can_safely_remove_masters = True class Bsa(GameInfo.Bsa): allow_reset_timestamps = True # Oblivion accepts the base name and literally *anything* after # that. E.g. MyModMeshes.bsa will load from a MyMod.esp plugin attachment_regex = u'.*' redate_dict = defaultdict(lambda: u'2006-01-01', { u'Oblivion - Voices1.bsa': u'2005-01-02', u'Oblivion - Voices2.bsa': u'2005-01-03', u'Oblivion - Meshes.bsa': u'2005-01-04', u'Oblivion - Sounds.bsa': u'2005-01-05', u'Oblivion - Misc.bsa': u'2005-01-06', }) valid_versions = {0x67} class Xe(GameInfo.Xe): full_name = u'TES4Edit' xe_key_prefix = u'tes4View' class Bain(GameInfo.Bain): data_dirs = GameInfo.Bain.data_dirs | { u'_tejon', u'distantlod', u'facegen', u'fonts', u'menus', u'obse', u'pluggy', u'scripts', u'shaders', u'streamline', u'trees', } keep_data_dirs = { _j(u'OBSE', u'Plugins', u'ComponentDLLs', u'CSE'), u'LSData' } keep_data_files = { _j(u'OBSE', u'Plugins', u'Construction Set Extender.dll'), _j(u'OBSE', u'Plugins', u'Construction Set Extender.ini'), } keep_data_file_prefixes = { _j(u'Meshes', u'Characters', u'_Male', u'specialanims', u'0FemaleVariableWalk_'), } skip_bain_refresh = { u'tes4edit backups', u'tes4edit cache', u'bgsee', u'conscribe logs', } wrye_bash_data_files = {u'ArchiveInvalidationInvalidated!.bsa'} class Esp(GameInfo.Esp): canBash = True canEditHeader = True validHeaderVersions = (0.8,1.0) stringsFiles = [] biped_flag_names = (u'head', u'hair', u'upperBody', u'lowerBody', u'hand', u'foot', u'rightRing', u'leftRing', u'amulet', u'weapon', u'backWeapon', u'sideWeapon', u'quiver', u'shield', u'torch', u'tail') reference_types = {b'ACHR', b'ACRE', b'REFR'} allTags = PatchGame.allTags | {u'IIM', u'NoMerge'} patchers = { u'AliasModNames', u'CoblCatalogs', u'CoblExhaustion', u'ContentsChecker', u'ImportActors', u'ImportActorsAIPackages', u'ImportActorsAnimations', u'ImportActorsDeathItems', u'ImportActorsFaces', u'ImportActorsFactions', u'ImportActorsSpells', u'ImportCells', u'ImportEffectsStats', u'ImportEnchantmentStats', u'ImportGraphics', u'ImportInventory', u'ImportNames', u'ImportRelations', u'ImportRoads', u'ImportScripts', u'ImportSounds', u'ImportSpellStats', u'ImportStats', u'ImportText', u'LeveledLists', u'MergePatches', u'MorphFactions', u'NpcChecker', u'ReplaceFormIDs', u'SEWorldTests', u'TweakActors', u'TweakAssorted', u'TweakClothes', u'TweakNames', u'TweakSettings', u'ImportRaces', u'ImportRacesSpells', u'ImportRacesRelations', u'EyeChecker', u'TweakRaces', u'RaceChecker', u'TimescaleChecker', } weaponTypes = ( _(u'Blade (1 Handed)'), _(u'Blade (2 Handed)'), _(u'Blunt (1 Handed)'), _(u'Blunt (2 Handed)'), _(u'Staff'), _(u'Bow'), ) raceNames = { 0x23fe9 : _(u'Argonian'), 0x224fc : _(u'Breton'), 0x191c1 : _(u'Dark Elf'), 0x19204 : _(u'High Elf'), 0x00907 : _(u'Imperial'), 0x22c37 : _(u'Khajiit'), 0x224fd : _(u'Nord'), 0x191c0 : _(u'Orc'), 0x00d43 : _(u'Redguard'), 0x00019 : _(u'Vampire'), 0x223c8 : _(u'Wood Elf'), } raceShortNames = { 0x23fe9 : u'Arg', 0x224fc : u'Bre', 0x191c1 : u'Dun', 0x19204 : u'Alt', 0x00907 : u'Imp', 0x22c37 : u'Kha', 0x224fd : u'Nor', 0x191c0 : u'Orc', 0x00d43 : u'Red', 0x223c8 : u'Bos', } raceHairMale = { 0x23fe9 : 0x64f32, #--Arg 0x224fc : 0x90475, #--Bre 0x191c1 : 0x64214, #--Dun 0x19204 : 0x7b792, #--Alt 0x00907 : 0x90475, #--Imp 0x22c37 : 0x653d4, #--Kha 0x224fd : 0x1da82, #--Nor 0x191c0 : 0x66a27, #--Orc 0x00d43 : 0x64215, #--Red 0x223c8 : 0x690bc, #--Bos } raceHairFemale = { 0x23fe9 : 0x64f33, #--Arg 0x224fc : 0x1da83, #--Bre 0x191c1 : 0x1da83, #--Dun 0x19204 : 0x690c2, #--Alt 0x00907 : 0x1da83, #--Imp 0x22c37 : 0x653d0, #--Kha 0x224fd : 0x1da83, #--Nor 0x191c0 : 0x64218, #--Orc 0x00d43 : 0x64210, #--Red 0x223c8 : 0x69473, #--Bos } bethDataFiles = { #--Vanilla u'oblivion.esm', u'oblivion_1.1.esm', u'oblivion_si.esm', u'oblivion - meshes.bsa', u'oblivion - misc.bsa', u'oblivion - sounds.bsa', u'oblivion - textures - compressed.bsa', u'oblivion - textures - compressed.bsa.orig', u'oblivion - voices1.bsa', u'oblivion - voices2.bsa', #--Shivering Isles u'dlcshiveringisles.esp', u'dlcshiveringisles - meshes.bsa', u'dlcshiveringisles - sounds.bsa', u'dlcshiveringisles - textures.bsa', u'dlcshiveringisles - voices.bsa', #--Knights of the Nine - shipped with all WS versions u'knights.esp', u'knights.bsa', } @classmethod def _dynamic_import_modules(cls, package_name): super(OblivionGameInfo, cls)._dynamic_import_modules(package_name) # Do the imports *after setting the _constants_members* from .patcher import checkers, preservers cls.gameSpecificPatchers = { u'CoblCatalogs': checkers.CoblCatalogsPatcher, u'SEWorldTests': checkers.SEWorldTestsPatcher, } cls.gameSpecificListPatchers = { u'CoblExhaustion': preservers.CoblExhaustionPatcher, u'MorphFactions': preservers.MorphFactionsPatcher, } cls.game_specific_import_patchers = { u'ImportRoads': preservers.ImportRoadsPatcher, } @classmethod def init(cls): cls._dynamic_import_modules(__name__) from .records import MreActi, MreAlch, MreAmmo, MreAnio, MreAppa, \ MreArmo, MreBook, MreBsgn, MreClas, MreClot, MreCont, MreCrea, \ MreDoor, MreEfsh, MreEnch, MreEyes, MreFact, MreFlor, MreFurn, \ MreGras, MreHair, MreIngr, MreKeym, MreLigh, MreLscr, MreLvlc, \ MreLvli, MreLvsp, MreMgef, MreMisc, MreNpc, MrePack, MreQust, \ MreRace, MreScpt, MreSgst, MreSlgm, MreSoun, MreSpel, MreStat, \ MreTree, MreWatr, MreWeap, MreWthr, MreClmt, MreCsty, MreIdle, \ MreLtex, MreRegn, MreSbsp, MreSkil, MreAchr, MreAcre, MreCell, \ MreGmst, MreRefr, MreRoad, MreTes4, MreWrld, MreDial, MreInfo, \ MrePgrd cls.mergeable_sigs = {clazz.rec_sig: clazz for clazz in ( MreActi, MreAlch, MreAmmo, MreAnio, MreAppa, MreArmo, MreBook, MreBsgn, MreClas, MreClot, MreCont, MreCrea, MreDoor, MreEfsh, MreEnch, MreEyes, MreFact, MreFlor, MreFurn, MreGlob, MreGras, MreHair, MreIngr, MreKeym, MreLigh, MreLscr, MreLvlc, MreLvli, MreLvsp, MreMgef, MreMisc, MreNpc, MrePack, MreQust, MreRace, MreScpt, MreSgst, MreSlgm, MreSoun, MreSpel, MreStat, MreTree, MreWatr, MreWeap, MreWthr, MreClmt, MreCsty, MreIdle, MreLtex, MreRegn, MreSbsp, MreSkil, MreAchr, MreAcre, MreCell, MreGmst, MreRefr, MreRoad, MreWrld, MreDial, MreInfo, MreLand, MrePgrd, )} cls.readClasses = (b'MGEF', b'SCPT') cls.writeClasses = (b'MGEF',) # Setting RecordHeader class variables - Oblivion is special header_type = brec.RecordHeader header_type.rec_header_size = 20 header_type.rec_pack_format = [u'=4s', u'I', u'I', u'I', u'I'] header_type.rec_pack_format_str = u''.join(header_type.rec_pack_format) header_type.header_unpack = _struct.Struct( header_type.rec_pack_format_str).unpack header_type.pack_formats = {0: u'=4sI4s2I'} header_type.pack_formats.update( {x: u'=4s4I' for x in {1, 6, 7, 8, 9, 10}}) header_type.pack_formats.update({x: u'=4sIi2I' for x in {2, 3}}) header_type.pack_formats.update({x: u'=4sIhh2I' for x in {4, 5}}) # Similar to other games header_type.top_grup_sigs = [ b'GMST', b'GLOB', b'CLAS', b'FACT', b'HAIR', b'EYES', b'RACE', b'SOUN', b'SKIL', b'MGEF', b'SCPT', b'LTEX', b'ENCH', b'SPEL', b'BSGN', b'ACTI', b'APPA', b'ARMO', b'BOOK', b'CLOT', b'CONT', b'DOOR', b'INGR', b'LIGH', b'MISC', b'STAT', b'GRAS', b'TREE', b'FLOR', b'FURN', b'WEAP', b'AMMO', b'NPC_', b'CREA', b'LVLC', b'SLGM', b'KEYM', b'ALCH', b'SBSP', b'SGST', b'LVLI', b'WTHR', b'CLMT', b'REGN', b'CELL', b'WRLD', b'DIAL', b'QUST', b'IDLE', b'PACK', b'CSTY', b'LSCR', b'LVSP', b'ANIO', b'WATR', b'EFSH', ] header_type.valid_header_sigs = set( header_type.top_grup_sigs + [b'GRUP', b'TES4', b'ROAD', b'REFR', b'ACHR', b'ACRE', b'PGRD', b'LAND', b'INFO']) brec.MreRecord.type_class = {x.rec_sig: x for x in ( MreAchr, MreAcre, MreActi, MreAlch, MreAmmo, MreAnio, MreAppa, MreArmo, MreBook, MreBsgn, MreCell, MreClas, MreClot, MreCont, MreCrea, MreDoor, MreEfsh, MreEnch, MreEyes, MreFact, MreFlor, MreFurn, MreGlob, MreGmst, MreGras, MreHair, MreIngr, MreKeym, MreLigh, MreLscr, MreLvlc, MreLvli, MreLvsp, MreMgef, MreMisc, MreNpc, MrePack, MreQust, MreRace, MreRefr, MreRoad, MreScpt, MreSgst, MreSkil, MreSlgm, MreSoun, MreSpel, MreStat, MreTree, MreTes4, MreWatr, MreWeap, MreWrld, MreWthr, MreClmt, MreCsty, MreIdle, MreLtex, MreRegn, MreSbsp, MreDial, MreInfo, MreLand, MrePgrd)} brec.MreRecord.simpleTypes = (set(brec.MreRecord.type_class) - { b'TES4', b'ACHR', b'ACRE', b'REFR', b'CELL', b'PGRD', b'ROAD', b'LAND', b'WRLD', b'INFO', b'DIAL'}) cls._validate_records()
def experiment_config_path(directory): path = _j(directory, 'experiment_config.json') return path
import dot_config import dot_util # # Configuration # ROOT = _d(_d(_d(_r(__file__)))) if not os.path.exists(ROOT): print ("ERROR: ROOT ({ROOT}) doesn't exist".format(ROOT=ROOT)) sys.exit(1) # Time to wait to connect to various things. MAX_TIME_SEC = 60 COMMON_SH = _j(ROOT, "src/sh/common.sh") EXPORTS_SH = _j(ROOT, "src/sh/exports.sh") # # End of configuration # def config_vars(): ignore = set([ '__builtins__', '__doc__', '__file__', '__name__', '__package__', '_prev_dir', ])
def _call_times_summary_path(self, bench_name): path = _j( self.directory, "pyprof_call_times{bench}.txt".format( bench=bench_suffix(bench_name))) return path
def _csv_path(self): return _j(self.directory, "extrapolated_training_time.csv")
def pickle_path(self, directory, func, args): basename = self.pickle_basename(func) sha = self.argument_hash(args) return _j(directory, ".{basename}.{sha}.cpickle".format(**locals()))
def get_trace_path(directory, trace_id): path = _j( directory, 'machine_util{trace}.proto'.format(trace=trace_suffix(trace_id), )) return path
def _flamegraph_svg_path(self, op_name): return _j( self.directory, 'flamegraph{bench}.svg'.format(bench=bench_suffix(op_name), ))
def _adjust_paths(self, old_entry): entry = dict(old_entry) for key in list(entry.keys()): if re.search(r'_path$', key): entry[key] = _j(self.directory, entry[key]) return entry
import json import codecs from os.path import join as _j, abspath as _a, dirname as _d, exists as _e, basename as _b # pip install progressbar2 import progressbar from rlscope.parser.common import * from rlscope.parser import constants from rlscope.parser.stats import Stats, KernelTime from rlscope.parser.db import SQLCategoryTimesReader, sql_get_source_files, sql_input_path, process_op_nest_single_thread, each_stack_trace from rlscope import py_config FLAME_GRAPH_PERL = _j(py_config.ROOT, 'third_party', 'FlameGraph', 'flamegraph.pl') class PythonFlameGraphParser: def __init__( self, directory, host=None, user=None, password=None, op_name=None, debug=False, # Swallow any excess arguments **kwargs): self.directory = directory self.host = host
""" import argparse import subprocess import textwrap import sys import os import re from os.path import join as _j, abspath as _a, exists as _e, dirname as _d, basename as _b import datetime import pytz from rlscope.profiler.rlscope_logging import logger from rlscope import py_config from rlscope.profiler.util import pprint_msg VERSION_PY = _j(py_config.ROOT, "rlscope", "version.py") RLSCOPE_INIT_PY = _j(py_config.ROOT, "rlscope", "__init__.py") TIME_ZONE = 'America/New_York' class VersionGenerator: def __init__(self, args): self.args = args self._init_versions() self.utc_now = pytz.utc.localize(datetime.datetime.utcnow()) self.tz_now = self.utc_now.astimezone(pytz.timezone(TIME_ZONE)) def _init_versions(self): args = self.args self.cuda = args.cuda_version
class Fallout3GameInfo(PatchGame): displayName = u'Fallout 3' fsName = u'Fallout3' altName = u'Wrye Flash' game_icon = u'fallout3_%u.png' bash_root_prefix = u'Fallout3' bak_game_name = u'Fallout3' template_dir = u'Fallout3' my_games_name = u'Fallout3' appdata_name = u'Fallout3' launch_exe = u'Fallout3.exe' game_detect_includes = [u'Fallout3.exe'] version_detect_file = u'Fallout3.exe' master_file = u'Fallout3.esm' taglist_dir = u'Fallout3' loot_dir = u'Fallout3' boss_game_name = u'Fallout3' regInstallKeys = (u'Bethesda Softworks\\Fallout3',u'Installed Path') nexusUrl = u'https://www.nexusmods.com/fallout3/' nexusName = u'Fallout 3 Nexus' nexusKey = u'bash.installers.openFallout3Nexus.continue' using_txt_file = False plugin_name_specific_dirs = GameInfo.plugin_name_specific_dirs + [ _j(u'textures', u'characters', u'BodyMods'), _j(u'textures', u'characters', u'FaceMods')] class Ck(GameInfo.Ck): ck_abbrev = u'GECK' long_name = u'Garden of Eden Creation Kit' exe = u'GECK.exe' se_args = u'-editor' image_name = u'geck%s.png' class Se(GameInfo.Se): se_abbrev = u'FOSE' long_name = u'Fallout 3 Script Extender' exe = u'fose_loader.exe' # There is no fose_steam_loader.dll, so we have to list all included # DLLs, since people could delete any DLL not matching the game version # they're using ver_files = [u'fose_loader.exe', u'fose_1_7ng.dll', u'fose_1_7.dll', u'fose_1_6.dll', u'fose_1_5.dll', u'fose_1_4b.dll', u'fose_1_4.dll', u'fose_1_1.dll', u'fose_1_0.dll'] plugin_dir = u'FOSE' cosave_tag = u'FOSE' cosave_ext = u'.fose' url = u'http://fose.silverlock.org/' url_tip = u'http://fose.silverlock.org/' limit_fixer_plugins = [u'mod_limit_fix.dll'] class Ini(GameInfo.Ini): allow_new_lines = False bsa_redirection_key = (u'Archive', u'sArchiveList') default_ini_file = u'Fallout_default.ini' dropdown_inis = [u'Fallout.ini', u'FalloutPrefs.ini'] supports_mod_inis = False class Ess(GameInfo.Ess): ext = u'.fos' can_safely_remove_masters = True class Bsa(GameInfo.Bsa): allow_reset_timestamps = True redate_dict = defaultdict(lambda: u'2006-01-01', { u'Fallout - MenuVoices.bsa': u'2005-01-01', u'Fallout - Meshes.bsa': u'2005-01-02', u'Fallout - Misc.bsa': u'2005-01-03', u'Fallout - Sound.bsa': u'2005-01-04', u'Fallout - Textures.bsa': u'2005-01-05', u'Fallout - Voices.bsa': u'2005-01-06', }) # ArchiveInvalidation Invalidated, which we shipped unmodified for a # long time, uses an Oblivion BSA with version 0x67, so we have to # accept those here as well valid_versions = {0x67, 0x68} class Xe(GameInfo.Xe): full_name = u'FO3Edit' xe_key_prefix = u'fo3View' class Bain(GameInfo.Bain): data_dirs = GameInfo.Bain.data_dirs | { u'config', # mod config files (INIs) u'distantlod', u'docs', u'facegen', u'fonts', u'fose', u'menus', u'uio', # User Interface Organizer u'scripts', u'shaders', u'trees', } keep_data_dirs = {u'LSData'} keep_data_files = {u'Fallout - AI!.bsa'} skip_bain_refresh = {u'fo3edit backups', u'fo3edit cache'} wrye_bash_data_files = {u'ArchiveInvalidationInvalidated!.bsa'} class Esp(GameInfo.Esp): canBash = True canEditHeader = True validHeaderVersions = (0.85, 0.94) stringsFiles = [] generate_temp_child_onam = True biped_flag_names = (u'head', u'hair', u'upperBody', u'leftHand', u'rightHand', u'weapon', u'pipboy', u'backpack', u'necklace', u'headband', u'hat', u'eyeGlasses', u'noseRing', u'earrings', u'mask', u'choker', u'mouthObject', u'bodyAddOn1', u'bodyAddOn2', u'bodyAddOn3') reference_types = {b'ACHR', b'ACRE', b'PBEA', b'PGRE', b'PMIS', b'REFR'} allTags = PatchGame.allTags | {u'NoMerge'} patchers = { u'AliasModNames', u'ContentsChecker', u'FormIDLists', u'ImportActors', u'ImportActorsAIPackages', u'ImportActorsAnimations', u'NpcChecker', u'ImportActorsDeathItems', u'ImportActorsFaces', u'RaceChecker', u'ImportActorsFactions', u'ImportActorsSpells', u'ImportCells', u'ImportDestructible', u'ImportEffectsStats', u'ImportRaces', u'ImportEnchantmentStats', u'ImportGraphics', u'ImportInventory', u'ImportNames', u'ImportObjectBounds', u'ImportRelations', u'ImportScripts', u'ImportSounds', u'ImportSpellStats', u'ImportStats', u'ImportText', u'LeveledLists', u'MergePatches', u'TweakActors', u'TweakAssorted', u'TweakSettings', u'ImportRacesRelations', u'TweakRaces', u'TimescaleChecker', u'TweakNames', } weaponTypes = ( _(u'Big gun'), _(u'Energy'), _(u'Small gun'), _(u'Melee'), _(u'Unarmed'), _(u'Thrown'), _(u'Mine'), ) raceNames = { 0x000019 : _(u'Caucasian'), 0x0038e5 : _(u'Hispanic'), 0x0038e6 : _(u'Asian'), 0x003b3e : _(u'Ghoul'), 0x00424a : _(u'AfricanAmerican'), 0x0042be : _(u'AfricanAmerican Child'), 0x0042bf : _(u'AfricanAmerican Old'), 0x0042c0 : _(u'Asian Child'), 0x0042c1 : _(u'Asian Old'), 0x0042c2 : _(u'Caucasian Child'), 0x0042c3 : _(u'Caucasian Old'), 0x0042c4 : _(u'Hispanic Child'), 0x0042c5 : _(u'Hispanic Old'), 0x04bb8d : _(u'Caucasian Raider'), 0x04bf70 : _(u'Hispanic Raider'), 0x04bf71 : _(u'Asian Raider'), 0x04bf72 : _(u'AfricanAmerican Raider'), 0x0987dc : _(u'Hispanic Old Aged'), 0x0987dd : _(u'Asian Old Aged'), 0x0987de : _(u'AfricanAmerican Old Aged'), 0x0987df : _(u'Caucasian Old Aged'), } raceShortNames = { 0x000019 : u'Cau', 0x0038e5 : u'His', 0x0038e6 : u'Asi', 0x003b3e : u'Gho', 0x00424a : u'Afr', 0x0042be : u'AfC', 0x0042bf : u'AfO', 0x0042c0 : u'AsC', 0x0042c1 : u'AsO', 0x0042c2 : u'CaC', 0x0042c3 : u'CaO', 0x0042c4 : u'HiC', 0x0042c5 : u'HiO', 0x04bb8d : u'CaR', 0x04bf70 : u'HiR', 0x04bf71 : u'AsR', 0x04bf72 : u'AfR', 0x0987dc : u'HOA', 0x0987dd : u'AOA', 0x0987de : u'FOA', 0x0987df : u'COA', } raceHairMale = { 0x000019 : 0x014b90, #--Cau 0x0038e5 : 0x0a9d6f, #--His 0x0038e6 : 0x014b90, #--Asi 0x003b3e : None, #--Gho 0x00424a : 0x0306be, #--Afr 0x0042be : 0x060232, #--AfC 0x0042bf : 0x0306be, #--AfO 0x0042c0 : 0x060232, #--AsC 0x0042c1 : 0x014b90, #--AsO 0x0042c2 : 0x060232, #--CaC 0x0042c3 : 0x02bfdb, #--CaO 0x0042c4 : 0x060232, #--HiC 0x0042c5 : 0x02ddee, #--HiO 0x04bb8d : 0x02bfdb, #--CaR 0x04bf70 : 0x02bfdb, #--HiR 0x04bf71 : 0x02bfdb, #--AsR 0x04bf72 : 0x0306be, #--AfR 0x0987dc : 0x0987da, #--HOA 0x0987dd : 0x0987da, #--AOA 0x0987de : 0x0987d9, #--FOA 0x0987df : 0x0987da, #--COA } raceHairFemale = { 0x000019 : 0x05dc6b, #--Cau 0x0038e5 : 0x05dc76, #--His 0x0038e6 : 0x022e50, #--Asi 0x003b3e : None, #--Gho 0x00424a : 0x05dc78, #--Afr 0x0042be : 0x05a59e, #--AfC 0x0042bf : 0x072e39, #--AfO 0x0042c0 : 0x05a5a3, #--AsC 0x0042c1 : 0x072e39, #--AsO 0x0042c2 : 0x05a59e, #--CaC 0x0042c3 : 0x072e39, #--CaO 0x0042c4 : 0x05a59e, #--HiC 0x0042c5 : 0x072e39, #--HiO 0x04bb8d : 0x072e39, #--CaR 0x04bf70 : 0x072e39, #--HiR 0x04bf71 : 0x072e39, #--AsR 0x04bf72 : 0x072e39, #--AfR 0x0987dc : 0x044529, #--HOA 0x0987dd : 0x044529, #--AOA 0x0987de : 0x044529, #--FOA 0x0987df : 0x044529, #--COA } bethDataFiles = { #--Vanilla u'fallout3.esm', u'fallout - menuvoices.bsa', u'fallout - meshes.bsa', u'fallout - misc.bsa', u'fallout - sound.bsa', u'fallout - textures.bsa', u'fallout - voices.bsa', #-- DLC u'anchorage.esm', u'anchorage - main.bsa', u'anchorage - sounds.bsa', u'thepitt.esm', u'thepitt - main.bsa', u'thepitt - sounds.bsa', u'brokensteel.esm', u'brokensteel - main.bsa', u'brokensteel - sounds.bsa', u'pointlookout.esm', u'pointlookout - main.bsa', u'pointlookout - sounds.bsa', u'zeta.esm', u'zeta - main.bsa', u'zeta - sounds.bsa', } @classmethod def init(cls): cls._dynamic_import_modules(__name__) from .records import MreActi, MreAddn, MreAlch, MreAmmo, MreAnio, \ MreArma, MreArmo, MreAspc, MreAvif, MreBook, MreBptd, MreCams, \ MreClas, MreClmt, MreCobj, MreCont, MreCpth, MreCrea, MreCsty, \ MreDebr, MreDobj, MreDoor, MreEczn, MreEfsh, MreEnch, MreExpl, \ MreEyes, MreFact, MreFurn, MreGras, MreHair, MreHdpt, MreTes4, \ MreIdle, MreIdlm, MreImad, MreImgs, MreIngr, MreIpct, MreIpds, \ MreKeym, MreLgtm, MreLigh, MreLscr, MreLtex, MreLvlc, MreLvli, \ MreLvln, MreMesg, MreMgef, MreMicn, MreMisc, MreMstt, MreMusc, \ MreNote, MreNpc, MrePack, MrePerk, MreProj, MrePwat, MreQust, \ MreRace, MreRads, MreRegn, MreRgdl, MreScol, MreScpt, MreSoun, \ MreSpel, MreStat, MreTact, MreTerm, MreTree, MreTxst, MreVtyp, \ MreWatr, MreWeap, MreWthr, MreAchr, MreAcre, MreCell, MreDial, \ MreGmst, MreInfo, MreNavi, MreNavm, MrePgre, MrePmis, MreRefr, \ MreWrld cls.mergeable_sigs = {clazz.rec_sig: clazz for clazz in ( MreActi, MreAddn, MreAlch, MreAmmo, MreAnio, MreArma, MreArmo, MreAspc, MreAvif, MreBook, MreBptd, MreCams, MreClas, MreClmt, MreCobj, MreCont, MreCpth, MreCrea, MreCsty, MreDebr, MreDobj, MreDoor, MreEczn, MreEfsh, MreEnch, MreExpl, MreEyes, MreFact, MreFlst, MreFurn, MreGlob, MreGras, MreHair, MreHdpt, MreIdle, MreIdlm, MreImad, MreImgs, MreIngr, MreIpct, MreIpds, MreKeym, MreLgtm, MreLigh, MreLscr, MreLtex, MreLvlc, MreLvli, MreLvln, MreMesg, MreMgef, MreMicn, MreMisc, MreMstt, MreMusc, MreNote, MreNpc, MrePack, MrePerk, MreProj, MrePwat, MreQust, MreRace, MreRads, MreRegn, MreRgdl, MreScol, MreScpt, MreSoun, MreSpel, MreStat, MreTact,MreTerm, MreTree, MreTxst, MreVtyp, MreWatr, MreWeap, MreWthr, MreGmst, )} # Setting RecordHeader class variables -------------------------------- header_type = brec.RecordHeader header_type.top_grup_sigs = [ b'GMST', b'TXST', b'MICN', b'GLOB', b'CLAS', b'FACT', b'HDPT', b'HAIR', b'EYES', b'RACE', b'SOUN', b'ASPC', b'MGEF', b'SCPT', b'LTEX', b'ENCH', b'SPEL', b'ACTI', b'TACT', b'TERM', b'ARMO', b'BOOK', b'CONT', b'DOOR', b'INGR', b'LIGH', b'MISC', b'STAT', b'SCOL', b'MSTT', b'PWAT', b'GRAS', b'TREE', b'FURN', b'WEAP', b'AMMO', b'NPC_', b'CREA', b'LVLC', b'LVLN', b'KEYM', b'ALCH', b'IDLM', b'NOTE', b'PROJ', b'LVLI', b'WTHR', b'CLMT', b'COBJ', b'REGN', b'NAVI', b'CELL', b'WRLD', b'DIAL', b'QUST', b'IDLE', b'PACK', b'CSTY', b'LSCR', b'ANIO', b'WATR', b'EFSH', b'EXPL', b'DEBR', b'IMGS', b'IMAD', b'FLST', b'PERK', b'BPTD', b'ADDN', b'AVIF', b'RADS', b'CAMS', b'CPTH', b'VTYP', b'IPCT', b'IPDS', b'ARMA', b'ECZN', b'MESG', b'RGDL', b'DOBJ', b'LGTM', b'MUSC', ] header_type.valid_header_sigs = set( header_type.top_grup_sigs + [b'GRUP', b'TES4', b'ACHR', b'ACRE', b'INFO', b'LAND', b'NAVM', b'PGRE', b'PMIS', b'REFR']) header_type.plugin_form_version = 15 brec.MreRecord.type_class = {x.rec_sig: x for x in ( # Not Mergeable (MreAchr, MreAcre, MreCell, MreDial, MreInfo, MreNavi, MreNavm, MrePgre, MrePmis, MreRefr, MreWrld, MreTes4))} brec.MreRecord.type_class.update(cls.mergeable_sigs) brec.MreRecord.simpleTypes = (set(brec.MreRecord.type_class) - { b'TES4', b'ACHR', b'ACRE', b'CELL', b'DIAL', b'INFO', b'LAND', b'NAVI', b'NAVM', b'PGRE', b'PMIS', b'REFR', b'WRLD'}) cls._validate_records()
class GameInfo(object): # Main game info - should be overridden ----------------------------------- # Name of the game to use in UI. displayName = u'' ## Example: u'Skyrim' # Name of the game's filesystem folder. fsName = u'' ## Example: u'Skyrim' # Alternate display name of Wrye Bash when managing this game altName = u'' ## Example: u'Wrye Smash' # Name of the prefix of the '<X> Mods' folder, i.e. <X> is this string. # Preferably pick a single word here, equal to fsName if possible. bash_root_prefix = u'' ## Example: u'Skyrim' # True if the game uses the 'My Documents' folder, False to just use the # game path uses_personal_folders = True # The exe to use when launching the game (without xSE present) launch_exe = u'' ## Example: u'TESV.exe' # Path to a file to look for to see if this is the right game when joined # with the -o parameter. Must be unique among all games. As a rule of # thumb, use the file you specified in launch_exe, unless that file is # shared by multiple games, in which case you MUST find unique files - see # Skyrim and Enderal, which share TESV.exe. game_detect_file = u'' # Path to a file to pass to env.get_file_version to determine the game's # version. Usually the same as launch_exe, but some games need different # ones here (e.g. Enderal, which has Skyrim's version in the launch_exe, # and therefore needs a different file here). version_detect_file = u'' # The main plugin Wrye Bash should look for master_file = u'' # The directory in which mods and other data files reside. This is relative # to the game directory. mods_dir = u'Data' # The pickle file for this game. Holds encoded GMST IDs from the big list # below pklfile = u'*GAMENAME*_ids.pkl' # The directory containing the masterlist for this game, relative to # 'Mopy/Bash Patches' masterlist_dir = u'' # Registry keys to read to find the install location # These are relative to: # HKLM\Software # HKLM\Software\Wow6432Node # HKCU\Software # HKCU\Software\Wow6432Node # Example: (u'Bethesda Softworks\\Oblivion', u'Installed Path') regInstallKeys = () # URL to the Nexus site for this game nexusUrl = u'' # URL nexusName = u'' # Long Name nexusKey = u'' # Key for the "always ask this question" setting in # settings.dat # Additional game info - override as needed ------------------------------- # URL to download patches for the main game. patchURL = u'' # Tooltip to display over the URL when displayed patchTip = u'Update via Steam' # plugin extensions espm_extensions = {u'.esm', u'.esp', u'.esu'} # Load order info using_txt_file = True # bethesda net export files has_achlist = False # check if a plugin is convertible to a light master instead of checking # mergeability check_esl = False # Whether or not this game has standalone .pluggy cosaves has_standalone_pluggy = False # Information about Plugin-Name-specific Directories supported by this # game. Some examples are sound\voices\PLUGIN_NAME.esp, or the facegendata # ones. An empty list means that the game does not have any such # directories. plugin_name_specific_dirs = [_j(u'sound', u'voice')] def __init__(self, gamePath): self.gamePath = gamePath # absolute bolt Path to the game directory self.has_esl = u'.esl' in self.espm_extensions class Ck(object): """Information about the official plugin editor (generally called some variation of 'Creation Kit') for this game.""" ck_abbrev = u'' # Abbreviated name long_name = u'' # Full name exe = u'*DNE*' # Executable to run # Argument to pass to the script extender to load the CK. If None, # indicates that this game's script extender does not have this feature se_args = None image_name = u'' # Image name template for the status bar class Se(object): """Information about the Script Extender for this game.""" se_abbrev = u'' # Abbreviated name. If this is empty, it signals that # no xSE is available for this game. Note that this # should NEVER be used to program other xSE # behavior - create new variables like plugin_dir and # cosave_ext instead. long_name = u'' # Full name exe = u'' # Exe to run ver_files = [] # List of file names to use for version detection. # Tried in order until one exists. Needed because # it's technically not required to install the EXE. plugin_dir = u'' # One level above the directory in which xSE plugins # should be placed (e.g. when plugins should be in # Data\OBSE\Plugins, this should be u'OBSE') cosave_tag = u'' # The magic tag that the cosaves use (e.g. u'SKSE'). # If this is empty, it signals that this script # extender has no cosaves. cosave_ext = u'' # The extension that the cosaves use (e.g. u'.skse') url = u'' # URL to download from url_tip = u'' # Tooltip for mouse over the URL class Sd(object): """Information about Script Dragon for this game.""" sd_abbrev = u'' # Abbreviated name. If this is empty, it signals that # no Script Dragon is available for this game. long_name = u'' # Full name install_dir = u'' # The directory, relative to the Data folder, into # which Script Dragon plugins will be installed. class Sp(object): """Information about SkyProc patchers for this game.""" sp_abbrev = u'' # Abbreviated name. If this is empty, it signals that # this game does not support SkyProc patchers. long_name = u'' # Full name install_dir = u'' # The directory, relative to the Data folder, into # which SkyProc patchers will be installed. class Ge(object): """Information about the Graphics Extender for this game.""" ge_abbrev = u'' # Abbreviated name. If this is empty, it signals # that no graphics extender is available for this game. long_name = u'' # Full name # exe is treated specially here. If it is a string, then it should # be the path relative to the root directory of the game, if it is # a list, each list element should be an iterable to pass to Path.join # relative to the root directory of the game. In this case, # each filename will be tested in reverse order. This was required # for Oblivion, as the newer OBGE has a different filename than the # older OBGE exe = u'' url = u'' # URL to download from url_tip = u'' # Tooltip for mouse over the URL class Laa(object): """Information about the LAA (Large Address Aware) launcher for this game.""" laa_name = u'' # Display name of the launcher exe = u'*DNE*' # Executable to run launchesSE = False # Whether the launcher will automatically launch # the SE class Ini(object): """Information about this game's INI handling.""" # True means new lines are allowed to be added via INI tweaks # (by default) allow_new_lines = True # INI Entry to enable BSA Redirection - two empty strings if this game # does not need BSA redirection bsa_redirection_key = (u'', u'') # Name of game's default ini file. default_ini_file = u'' # INI files that should show up in the INI Edits tab. Note that the # first one *must* be the main INI! # Example: [u'Oblivion.ini'] dropdown_inis = [] # INI setting used to setup Save Profiles # (section, key) save_profiles_key = (u'General', u'SLocalSavePath') # Base dir for the save_profiles_key setting above save_prefix = u'Saves' # INI setting used to enable or disable screenshots # (section, key, default value) screenshot_enabled_key = (u'Display', u'bAllowScreenShot', u'1') # INI setting used to set base screenshot name # (section, key, default value) screenshot_base_key = (u'Display', u'sScreenShotBaseName', u'ScreenShot') # INI setting used to set screenshot index # (section, key, default value) screenshot_index_key = (u'Display', u'iScreenShotIndex', u'0') # The INI entries listing vanilla BSAs to load resource_archives_keys = () # Whether this game supports mod ini files aka ini fragments supports_mod_inis = True class Ess(object): """Information about WB's capabilities with regards to save file viewing and editing for this game.""" canReadBasic = True # Can read the info needed for the Save Tab display canEditMore = False # Advanced editing ext = u'.ess' # Save file extension class Bsa(object): """Information about the BSAs (Bethesda Archives) used by this game.""" # Whether or not the INI setting ResetBSATimestamps should have any # effect on this game allow_reset_timestamps = False # Part of a regex used to determine which BSAs will attach to a plugin. # The full regex prepends the base name of the plugin (e.g. for # MyMod.esp, MyMod will be prepended) and appends Bsa.bsa_extension. # Most games accept arbitrary BSA names, hence this default attachment_regex = r'(?: \- \w+)?' # The extension used for BSA files bsa_extension = u'.bsa' # Whether or not the Archive.exe tool for this game creates BSL files has_bsl = False # Maps BSA names to the date to which they should be redated. Fallback # will be used for BSAs which are not explicitly listed. Format is # ISO 8601 (year-month-day) redate_dict = defaultdict(lambda: u'2006-01-01') # All BSA versions accepted by this game. If empty, indicates that this # game does not use BSA versions and so BSA version checks will be # skipped entirely. valid_versions = set() # Maps vanilla plugin names to the BSA that contain their localization # strings vanilla_string_bsas = {} class Psc(object): """Information about script sources (only Papyrus right now) for this game.""" # Extensions for external script sources. Empty if this game doesn't # have any. source_extensions = set() # Maps directories from which BAIN should redirect script sources from # to the directories that BAIN should redirect them to. Empty if this # is not applicable to this game. source_redirects = {} class Xe(object): """Information about xEdit for this game.""" # The name that xEdit has for this game, e.g. 'TES5Edit' for Skyrim full_name = u'xEdit' # A prefix for settings keys related to this version of xEdit (e.g. # expert mode) xe_key_prefix = u'' class Bain(object): """Information about what BAIN should do for this game.""" # The allowed default data directories that BAIN can install to data_dirs = { u'ini', u'meshes', u'music', u'sound', u'textures', u'video' } # Directories in the Data folder to exclude from Clean Data keep_data_dirs = set() # Files in the Data folder to exclude from Clean Data keep_data_files = set() # File prefixes in the Data folder to exclude from Clean Data keep_data_file_prefixes = set() # Files BAIN shouldn't skip no_skip = () # Directories where specific file extensions should not be skipped no_skip_dirs = {} # Folders BAIN should never CRC check in the Data directory skip_bain_refresh = set( # Use lowercase names ) # Wrye Bash files to exclude from Clean Data wrye_bash_data_files = set() # Wrye Bash directories to exclude from Clean Data wrye_bash_data_dirs = {u'Bash Patches', u'BashTags', u'INI Tweaks'} # Plugin format stuff class Esp(object): # Wrye Bash capabilities canBash = False # Can create Bashed Patches canCBash = False # CBash can handle this game's records canEditHeader = False # Can edit basic info in the main header # record - generally has signature 'TES4' # Valid ESM/ESP header versions # These are the valid 'version' numbers for the game file headers validHeaderVersions = tuple() # used to locate string translation files stringsFiles = [ ((u'Strings', ), u'%(body)s_%(language)s.STRINGS'), ((u'Strings', ), u'%(body)s_%(language)s.DLSTRINGS'), ((u'Strings', ), u'%(body)s_%(language)s.ILSTRINGS'), ] # Signature of the main plugin header record type plugin_header_sig = b'TES4' # If True, then plugins with at least one master can use the # 0x000-0x800 range for their own records. # If False, that range is reserved for hardcoded engine records. expanded_plugin_range = False # If True, check if the main header's DATA subrecords match the on-disk # master sizes and highlight the corresponding masters with a light # background color if that is the case. Needs meaningful information in # the DATA subrecords. check_master_sizes = False # If True, generate ONAM by reading each temp CELL child when adding # the ESM flag to plugins and discard it when removing the ESM flag. generate_temp_child_onam = False # The maximum number of entries inside a leveled list for this game. # Zero means no limit. max_lvl_list_size = 0 # Bash Tags supported by this game allTags = set() # Patcher available when building a Bashed Patch (referenced by class name) # PatchMerger must come first if enabled, see # patcher.base.APatchMerger.__init__ patchers = () # CBash patchers available when building a Bashed Patch CBash_patchers = () # CBash_PatchMerger must come first if enabled! # Magic Info weaponTypes = () # Race Info, used in faces.py raceNames = {} raceShortNames = {} raceHairMale = {} raceHairFemale = {} # Record information - set in cls.init ------------------------------------ # Mergeable record types mergeClasses = () # Extra read classes: these record types will always be loaded, even if # patchers don't need them directly (for example, for MGEF info) readClasses = () writeClasses = () # Class attributes moved to constants module, set dynamically at init #--Game ESM/ESP/BSA files ## These are all of the ESM,ESP,and BSA data files that belong to the game ## These filenames need to be in lowercase, bethDataFiles = set() # initialize with literal # Function Info ----------------------------------------------------------- # CTDA Data for the game. Maps function ID to tuple with name of function # and the parameter types of the function. # 0: no param; 1: int param; 2: formid param; 3: float param # Note that each line must have the same number of parameters after the # function name - so pad out functions with fewer parameters with zeroes condition_function_data = {} # The function index for the GetVATSValue function. This function is # special, because the type of its second parameter depends on the value of # the first parameter. getvatsvalue_index = 0 # Known record types - maps integers from the save format to human-readable # names for the record types. Used in save editing code. save_rec_types = {} #--List of GMST's in the main plugin (Oblivion.esm) that have 0x00000000 # as the form id. Any GMST as such needs it Editor Id listed here. gmstEids = [] """ GLOB record tweaks used by patcher.patchers.multitweak_settings.GmstTweaker Each entry is a tuple in the following format: (DisplayText, MouseoverText, GLOB EditorID, Option1, Option2, ..., OptionN) -EditorID can be a plain string, or a tuple of multiple Editor IDs. If it's a tuple, then Value (below) must be a tuple of equal length, providing values for each GLOB Each Option is a tuple: (DisplayText, Value) - If you enclose DisplayText in brackets like this: _(u'[Default]'), then the patcher will treat this option as the default value. - If you use _(u'Custom') as the entry, the patcher will bring up a number input dialog To make a tweak Enabled by Default, enclose the tuple entry for the tweak in a list, and make a dictionary as the second list item with { 'defaultEnabled ':True}. See the UOP Vampire face fix for an example of this (in the GMST Tweaks) """ GlobalsTweaks = [] """ GMST record tweaks used by patcher.patchers.multitweak_settings.GmstTweaker Each entry is a tuple in the following format: (DisplayText, MouseoverText, GMST EditorID, Option1, Option2, ..., OptionN) - EditorID can be a plain string, or a tuple of multiple Editor IDs. If it's a tuple, then Value (below) must be a tuple of equal length, providing values for each GMST Each Option is a tuple: (DisplayText, Value) - If you enclose DisplayText in brackets like this: _(u'[Default]'), then the patcher will treat this option as the default value. - If you use _(u'Custom') as the entry, the patcher will bring up a number input dialog To make a tweak Enabled by Default, enclose the tuple entry for the tweak in a list, and make a dictionary as the second list item with { 'defaultEnabled ':True}. See the UOP Vampire facefix for an example of this (in the GMST Tweaks) """ GmstTweaks = [] #-------------------------------------------------------------------------- # ListsMerger patcher (leveled list patcher) #-------------------------------------------------------------------------- listTypes = () #-------------------------------------------------------------------------- # NamesPatcher #-------------------------------------------------------------------------- namesTypes = set() # initialize with literal #-------------------------------------------------------------------------- # ItemPrices Patcher #-------------------------------------------------------------------------- pricesTypes = {} #-------------------------------------------------------------------------- # StatsImporter #-------------------------------------------------------------------------- statsTypes = {} statsHeaders = () #-------------------------------------------------------------------------- # SoundPatcher #-------------------------------------------------------------------------- # Needs longs in SoundPatcher soundsLongsTypes = set() # initialize with literal soundsTypes = {} #-------------------------------------------------------------------------- # CellImporter #-------------------------------------------------------------------------- cellAutoKeys = set() # use a set literal cellRecAttrs = {} cellRecFlags = {} cell_float_attrs = set() #-------------------------------------------------------------------------- # GraphicsPatcher #-------------------------------------------------------------------------- graphicsTypes = {} graphicsFidTypes = {} graphicsModelAttrs = () #-------------------------------------------------------------------------- # Inventory Patcher #-------------------------------------------------------------------------- inventoryTypes = () #-------------------------------------------------------------------------- # Race Patcher #-------------------------------------------------------------------------- default_eyes = {} #-------------------------------------------------------------------------- # Keywords Patcher #-------------------------------------------------------------------------- keywords_types = () #-------------------------------------------------------------------------- # Text Patcher #-------------------------------------------------------------------------- text_long_types = set() text_types = {} #-------------------------------------------------------------------------- # Object Bounds Patcher #-------------------------------------------------------------------------- object_bounds_types = set() #-------------------------------------------------------------------------- # Contents Checker #-------------------------------------------------------------------------- cc_valid_types = {} # (targeted types, structs/groups name, entry/item name) # OR (targeted types, fid list name) cc_passes = () #-------------------------------------------------------------------------- # Scripts Patcher #-------------------------------------------------------------------------- scripts_types = set() #-------------------------------------------------------------------------- # Destructible Patcher #-------------------------------------------------------------------------- destructible_types = set() #-------------------------------------------------------------------------- # Actor Patchers #-------------------------------------------------------------------------- actor_importer_attrs = {} actor_types = () #-------------------------------------------------------------------------- # Spell Stats Patcher #-------------------------------------------------------------------------- spell_stats_attrs = () #-------------------------------------------------------------------------- # Actor Tweaker #-------------------------------------------------------------------------- actor_tweaks = set() #-------------------------------------------------------------------------- # Assorted Tweaker #-------------------------------------------------------------------------- nirnroots = _(u'Nirnroots') #-------------------------------------------------------------------------- # Names Tweaker #-------------------------------------------------------------------------- body_tags = u'' #-------------------------------------------------------------------------- # Relations Patcher #-------------------------------------------------------------------------- relations_attrs = () relations_csv_header = u'' relations_csv_row_format = u'' #-------------------------------------------------------------------------- # Enchantment Stats Patcher #-------------------------------------------------------------------------- ench_stats_attrs = () #-------------------------------------------------------------------------- # Effect Stats Patcher #-------------------------------------------------------------------------- mgef_stats_attrs = () #-------------------------------------------------------------------------- # Magic Effects - Oblivion-specific #-------------------------------------------------------------------------- # Doesn't list MGEFs that use actor values, but rather MGEFs that have a # generic name. # Ex: Absorb Attribute becomes Absorb Magicka if the effect's actorValue # field contains 9, but it is actually using an attribute rather than # an actor value # Ex: Burden uses an actual actor value (encumbrance) but it isn't listed # since its name doesn't change generic_av_effects = set() # MGEFs that are considered hostile hostile_effects = set() # Maps MGEF signatures to certain MGEF properties mgef_basevalue = dict() mgef_name = dict() mgef_school = dict() # Human-readable names for each actor value actor_values = [] # Record type to name dictionary record_type_name = {} # Set in game/*/default_tweaks.py, this is a dictionary mapping names for # 'default' INI tweaks (i.e. ones that we ship with WB and that can't be # deleted) to OrderedDicts that implement the actual tweaks. See # DefaultIniFile.__init__ for how the tweaks are parsed. default_tweaks = {} # Set in game/*/vanilla_files.py, this is a set listing every file that # exists in the Data directory of the game in a purely vanilla # installation. Set in a separate file because this can be *very* large, # and would make editing the constants a miserable experience if included # (see e.g. skyrim/vanilla_files.py). vanilla_files = set() @property def plugin_header_class(self): return brec.MreRecord.type_class[self.Esp.plugin_header_sig] # Set in game/*/patcher.py used in Mopy/bash/basher/gui_patchers.py gameSpecificPatchers = {} gameSpecificListPatchers = {} game_specific_import_patchers = {} # Import from the constants module ---------------------------------------- # Class attributes moved to constants module, set dynamically at init _constants_members = { u'GlobalsTweaks', u'GmstTweaks', u'actor_importer_attrs', u'actor_tweaks', u'actor_types', u'actor_values', u'bethDataFiles', u'body_tags', u'cc_valid_types', u'cc_passes', u'cellAutoKeys', u'cell_float_attrs', u'cellRecAttrs', u'cellRecFlags', u'condition_function_data', u'default_eyes', u'destructible_types', u'ench_stats_attrs', u'generic_av_effects', u'getvatsvalue_index', u'gmstEids', u'graphicsFidTypes', u'graphicsModelAttrs', u'graphicsTypes', u'hostile_effects', u'inventoryTypes', u'keywords_types', u'listTypes', u'mgef_basevalue', u'mgef_name', u'mgef_school', u'mgef_stats_attrs', u'namesTypes', u'nirnroots', u'object_bounds_types', u'pricesTypes', u'record_type_name', u'relations_attrs', u'relations_csv_header', u'relations_csv_row_format', u'save_rec_types', u'scripts_types', u'soundsLongsTypes', u'soundsTypes', u'spell_stats_attrs', u'statsHeaders', u'statsTypes', u'text_long_types', u'text_types', } @classmethod def init(cls): # Setting RecordHeader class variables -------------------------------- # Top types in order of the main ESM header_type = brec.RecordHeader header_type.top_grup_sigs = [] header_type.valid_header_sigs = set(header_type.top_grup_sigs + [b'GRUP', b'TES4']) # Record Types brec.MreRecord.type_class = {x.rec_sig: x for x in ()} # Simple records brec.MreRecord.simpleTypes = (set(brec.MreRecord.type_class) - {b'TES4'}) cls._validate_records() @classmethod def _dynamic_import_modules(cls, package_name): """Dynamically import package modules to avoid importing them for every game. We need to pass the package name in for importlib to work. Currently populates the GameInfo namespace with the members defined in the relevant constants.py and imports default_tweaks.py and vanilla_files.py.""" constants = importlib.import_module('.constants', package=package_name) for k in dir(constants): if k.startswith('_'): continue if k not in cls._constants_members: raise RuntimeError(u'Unexpected game constant %s' % k) setattr(cls, k, getattr(constants, k)) tweaks_module = importlib.import_module('.default_tweaks', package=package_name) cls.default_tweaks = tweaks_module.default_tweaks vf_module = importlib.import_module('.vanilla_files', package=package_name) cls.vanilla_files = vf_module.vanilla_files patchers_module = importlib.import_module('.patcher', package=package_name) cls.gameSpecificPatchers = patchers_module.gameSpecificPatchers cls.gameSpecificListPatchers = patchers_module.gameSpecificListPatchers cls.game_specific_import_patchers = \ patchers_module.game_specific_import_patchers @staticmethod def _validate_records(): """Performs validation on the record syntax for all decoded records.""" for rec_class in brec.MreRecord.type_class.itervalues(): if issubclass(rec_class, brec.MelRecord): rec_class.validate_record_syntax()
class Fallout4GameInfo(PatchGame): displayName = u'Fallout 4' fsName = u'Fallout4' altName = u'Wrye Flash' game_icon = u'fallout4_%u.png' bash_root_prefix = u'Fallout4' bak_game_name = u'Fallout4' my_games_name = u'Fallout4' appdata_name = u'Fallout4' launch_exe = u'Fallout4.exe' game_detect_includes = [u'Fallout4.exe'] game_detect_excludes = WS_COMMON version_detect_file = u'Fallout4.exe' master_file = u'Fallout4.esm' taglist_dir = u'Fallout4' loot_dir = u'Fallout4' regInstallKeys = (u'Bethesda Softworks\\Fallout4', u'Installed Path') nexusUrl = u'https://www.nexusmods.com/fallout4/' nexusName = u'Fallout 4 Nexus' nexusKey = u'bash.installers.openFallout4Nexus.continue' espm_extensions = GameInfo.espm_extensions | {u'.esl'} has_achlist = True check_esl = True plugin_name_specific_dirs = GameInfo.plugin_name_specific_dirs + [ _j(u'meshes', u'actors', u'character', u'facegendata', u'facegeom'), _j(u'meshes', u'actors', u'character', u'facecustomization') ] class Ck(GameInfo.Ck): ck_abbrev = u'CK' long_name = u'Creation Kit' exe = u'CreationKit.exe' image_name = u'creationkit%s.png' class Se(GameInfo.Se): se_abbrev = u'F4SE' long_name = u'Fallout 4 Script Extender' exe = u'f4se_loader.exe' ver_files = [u'f4se_loader.exe', u'f4se_steam_loader.dll'] plugin_dir = u'F4SE' cosave_tag = u'F4SE' cosave_ext = u'.f4se' url = u'http://f4se.silverlock.org/' url_tip = u'http://f4se.silverlock.org/' class Ini(GameInfo.Ini): default_ini_file = u'Fallout4_default.ini' dropdown_inis = [u'Fallout4.ini', u'Fallout4Prefs.ini'] resource_archives_keys = (u'sResourceIndexFileList', u'sResourceStartUpArchiveList', u'sResourceArchiveList', u'sResourceArchiveList2', u'sResourceArchiveListBeta') class Ess(GameInfo.Ess): ext = u'.fos' class Bsa(GameInfo.Bsa): bsa_extension = u'.ba2' valid_versions = {0x01} class Psc(GameInfo.Psc): source_extensions = {u'.psc'} class Xe(GameInfo.Xe): full_name = u'FO4Edit' xe_key_prefix = u'fo4View' class Bain(GameInfo.Bain): data_dirs = GameInfo.Bain.data_dirs | { u'f4se', u'interface', u'lodsettings', u'materials', u'mcm', # FO4 MCM u'misc', u'programs', u'scripts', u'seq', u'shadersfx', u'strings', u'tools', # bodyslide u'vis', } no_skip_dirs = GameInfo.Bain.no_skip_dirs.copy() # PY3: dict join no_skip_dirs.update({ # This rule is to allow mods with string translation enabled. _j(u'interface', u'translations'): [u'.txt'] }) skip_bain_refresh = {u'fo4edit backups', u'fo4edit cache'} class Esp(GameInfo.Esp): canBash = True canEditHeader = True validHeaderVersions = (0.95, 1.0) expanded_plugin_range = True max_lvl_list_size = 255 reference_types = { b'ACHR', b'PARW', b'PBAR', b'PBEA', b'PCON', b'PFLA', b'PGRE', b'PHZD', b'PMIS', b'REFR' } patchers = { u'ImportObjectBounds', u'LeveledLists', } bethDataFiles = { #--Vanilla u'fallout4.esm', u'fallout4.cdx', u'fallout4 - animations.ba2', u'fallout4 - geometry.csg', u'fallout4 - interface.ba2', u'fallout4 - materials.ba2', u'fallout4 - meshes.ba2', u'fallout4 - meshesextra.ba2', u'fallout4 - misc.ba2', u'fallout4 - nvflex.ba2', u'fallout4 - shaders.ba2', u'fallout4 - sounds.ba2', u'fallout4 - startup.ba2', u'fallout4 - textures1.ba2', u'fallout4 - textures2.ba2', u'fallout4 - textures3.ba2', u'fallout4 - textures4.ba2', u'fallout4 - textures5.ba2', u'fallout4 - textures6.ba2', u'fallout4 - textures7.ba2', u'fallout4 - textures8.ba2', u'fallout4 - textures9.ba2', u'fallout4 - voices.ba2', u'dlcrobot.esm', u'dlcrobot.cdx', u'dlcrobot - geometry.csg', u'dlcrobot - main.ba2', u'dlcrobot - textures.ba2', u'dlcrobot - voices_en.ba2', u'dlcworkshop01.esm', u'dlcworkshop01.cdx', u'dlcworkshop01 - geometry.csg', u'dlcworkshop01 - main.ba2', u'dlcworkshop01 - textures.ba2', u'dlccoast.esm', u'dlccoast.cdx', u'dlccoast - geometry.csg', u'dlccoast - main.ba2', u'dlccoast - textures.ba2', u'dlccoast - voices_en.ba2', u'dlcworkshop02.esm', u'dlcworkshop02 - main.ba2', u'dlcworkshop02 - textures.ba2', u'dlcworkshop03.esm', u'dlcworkshop03.cdx', u'dlcworkshop03 - geometry.csg', u'dlcworkshop03 - main.ba2', u'dlcworkshop03 - textures.ba2', u'dlcworkshop03 - voices_en.ba2', u'dlcnukaworld.esm', u'dlcnukaworld.cdx', u'dlcnukaworld - geometry.csg', u'dlcnukaworld - main.ba2', u'dlcnukaworld - textures.ba2', u'dlcnukaworld - voices_en.ba2', } @classmethod def init(cls): cls._dynamic_import_modules(__name__) from .records import MreGmst, MreTes4, MreLvli, MreLvln cls.mergeable_sigs = { clazz.rec_sig: clazz for clazz in (MreGmst, MreLvli, MreLvln) } # Setting RecordHeader class variables -------------------------------- header_type = brec.RecordHeader header_type.top_grup_sigs = [ b'GMST', b'KYWD', b'LCRT', b'AACT', b'TRNS', b'CMPO', b'TXST', b'GLOB', b'DMGT', b'CLAS', b'FACT', b'HDPT', b'RACE', b'SOUN', b'ASPC', b'MGEF', b'LTEX', b'ENCH', b'SPEL', b'ACTI', b'TACT', b'ARMO', b'BOOK', b'CONT', b'DOOR', b'INGR', b'LIGH', b'MISC', b'STAT', b'SCOL', b'MSTT', b'GRAS', b'TREE', b'FLOR', b'FURN', b'WEAP', b'AMMO', b'NPC_', b'PLYR', b'LVLN', b'KEYM', b'ALCH', b'IDLM', b'NOTE', b'PROJ', b'HAZD', b'BNDS', b'TERM', b'LVLI', b'WTHR', b'CLMT', b'SPGD', b'RFCT', b'REGN', b'NAVI', b'CELL', b'WRLD', b'QUST', b'IDLE', b'PACK', b'CSTY', b'LSCR', b'LVSP', b'ANIO', b'WATR', b'EFSH', b'EXPL', b'DEBR', b'IMGS', b'IMAD', b'FLST', b'PERK', b'BPTD', b'ADDN', b'AVIF', b'CAMS', b'CPTH', b'VTYP', b'MATT', b'IPCT', b'IPDS', b'ARMA', b'ECZN', b'LCTN', b'MESG', b'DOBJ', b'DFOB', b'LGTM', b'MUSC', b'FSTP', b'FSTS', b'SMBN', b'SMQN', b'SMEN', b'DLBR', b'MUST', b'DLVW', b'EQUP', b'RELA', b'SCEN', b'ASTP', b'OTFT', b'ARTO', b'MATO', b'MOVT', b'SNDR', b'SNCT', b'SOPM', b'COLL', b'CLFM', b'REVB', b'PKIN', b'RFGP', b'AMDL', b'LAYR', b'COBJ', b'OMOD', b'MSWP', b'ZOOM', b'INNR', b'KSSM', b'AECH', b'SCCO', b'AORU', b'SCSN', b'STAG', b'NOCM', b'LENS', b'GDRY', b'OVIS', ] header_type.valid_header_sigs = (set(header_type.top_grup_sigs) | { b'GRUP', b'TES4', b'REFR', b'ACHR', b'PMIS', b'PARW', b'PGRE', b'PBEA', b'PFLA', b'PCON', b'PBAR', b'PHZD', b'LAND', b'NAVM', b'DIAL', b'INFO' }) header_type.plugin_form_version = 131 brec.MreRecord.type_class = { x.rec_sig: x for x in ( MreTes4, MreGmst, MreLvli, MreLvln, ) } brec.MreRecord.simpleTypes = (set(brec.MreRecord.type_class) - {b'TES4'}) cls._validate_records()
def get_variable_path(ParserKlass, src_files, bench_name): pretty_base = "{base}.variable.pretty.txt".format(base=_b(src_files.get('profile_path', bench_name))) return _j(_d(src_files.get('profile_path', bench_name)), pretty_base)
def _profiling_overhead_agg_csv_path(self): return _j(self.directory, "overall_training_progress.profiling_overhead.agg.csv")
def plot_index_path(self): return _j(self.out_dir, self.basename)
def workers_dir(self, algo, env, num_workers): return _j(self.root_directory, algo, env, "num_workers_{n}".format(n=num_workers))
class GameInfo(object): # Main game info - should be overridden ----------------------------------- # Name of the game to use in UI. displayName = u'' ## Example: u'Skyrim' # A name used throughout the codebase for identifying the current game in # various situations, e.g. to decide which BSAs to use, which save header # types to use, etc. fsName = u'' ## Example: u'Skyrim' # Alternate display name of Wrye Bash when managing this game altName = u'' ## Example: u'Wrye Smash' # Name of the icon to use for the game, including a %u specifier for the # icon size (16/24/32) game_icon = u'' ## Example: u'skyrim_%u.png' # Name of the prefix of the '<X> Mods' folder, i.e. <X> is this string. # Preferably pick a single word without spaces here, but don't change it # once set due to backwards compatibility (duh) bash_root_prefix = u'' ## Example: u'Skyrim' # Name of the prefix for the game folder inside created backups and for # naming backups. Should not be changed once set, otherwise restoring old # backups will no longer work bak_game_name = u'' # The name of the directory, relative to Mopy/templates, in which the BSA # redirection template for this game is placed. This folder is # *deprecated*, see issue #519 template_dir = u'' # The name of the directory, relative to Mopy/Bash Patches, in which # default Bashed Patch resource files (e.g. CSV files) are stored. If # empty, indicates that WB does not come with any such files for this game bash_patches_dir = u'' # True if the game uses the 'My Documents' folder, False to just use the # game path uses_personal_folders = True # Name of the folder in My Documents\My Games that holds this game's data # (saves, INIs, etc.) my_games_name = u'' # Name of the game's AppData folder, relative to %LocalAppData% appdata_name = u'' # The exe to use when launching the game (without xSE present) launch_exe = u'' ## Example: u'TESV.exe' # Path to one or more files to look for to see if this is the right game # when joined with the game's root path (i.e. the one above the Data # folder). The combination of these files must be unique among all games. # As a rule of thumb, use the file you specified in launch_exe, unless that # file is shared by multiple games, in which case you MUST find unique # files - for an example, see Enderal and Skyrim (and the SE versions of # both). game_detect_includes = [] # Path to one or more files to look for to see if this is *not* the right # game when joined with the game's root path. Used to differentia between # versions of the game distributed on different platforms (Windows Store). game_detect_excludes = [] # Path to a file to pass to env.get_file_version to determine the game's # version. Usually the same as launch_exe, but some games need different # ones here (e.g. Enderal, which has Skyrim's version in the launch_exe, # and therefore needs a different file here). version_detect_file = u'' # The main plugin Wrye Bash should look for master_file = u'' # The directory in which mods and other data files reside. This is relative # to the game directory. mods_dir = u'Data' # The name of the directory containing the taglist for this game, relative # to 'Mopy/taglists' taglist_dir = u'' # The name of the directory that LOOT writes its masterlist into, relative # to '%LocalAppData%\LOOT' loot_dir = u'' # The name that this game has on the BOSS command line. If empty, indicates # that BOSS does not support this game boss_game_name = u'' # Registry keys to read to find the install location # These are relative to: # HKLM\Software # HKLM\Software\Wow6432Node # HKCU\Software # HKCU\Software\Wow6432Node # Example: (u'Bethesda Softworks\\Oblivion', u'Installed Path') regInstallKeys = () # URL to the Nexus site for this game nexusUrl = u'' # URL nexusName = u'' # Long Name nexusKey = u'' # Key for the "always ask this question" setting in # settings.dat # Additional game info - override as needed ------------------------------- # URL to download patches for the main game. patchURL = u'' # Tooltip to display over the URL when displayed patchTip = u'Update via Steam' # plugin extensions espm_extensions = {u'.esm', u'.esp', u'.esu'} # Load order info using_txt_file = True # bethesda net export files has_achlist = False # check if a plugin is convertible to a light master instead of checking # mergeability check_esl = False # Whether or not this game has standalone .pluggy cosaves has_standalone_pluggy = False # Information about Plugin-Name-specific Directories supported by this # game. Some examples are sound\voices\PLUGIN_NAME.esp, or the facegendata # ones. An empty list means that the game does not have any such # directories. plugin_name_specific_dirs = [_j(u'sound', u'voice')] def __init__(self, gamePath): self.gamePath = gamePath # absolute bolt Path to the game directory self.has_esl = u'.esl' in self.espm_extensions class Ws(object): """Information about this game on the Windows Store.""" # A list of directory names for different language versions that ship # with this game. Each one acts as a separate game installation under # the main Windows Store path. If empty, indicates that the Windows # Store location is the game installtion game_language_dirs = [] # The publisher name for common games. Currently only 'Bethesda' is # allowed for Bethesda games. If specified, publisher_id is not # required publisher_name = u'' # The publisher ID for the publisher of the game. Required except for # common publishers supported above. For example, Bethesda's publisher # ID is '3275kfvn8vcwc' publisher_id = u'' # The internal name used by the Windows Store to identify the game. # For example, Morrowind is 'BethesdaSofworks.TESMorrowind-PC' win_store_name = u'' class Ck(object): """Information about the official plugin editor (generally called some variation of 'Creation Kit') for this game.""" # Abbreviated name ck_abbrev = u'' # Full name long_name = u'' # Executable to run exe = u'*DNE*' # Argument to pass to the script extender to load the CK. If None, # indicates that this game's script extender does not have this feature se_args = None # Image name template for the status bar image_name = u'' class Se(object): """Information about the Script Extender for this game.""" # Abbreviated name. If this is empty, it signals that no xSE is # available for this game. Note that this should NEVER be used to # program other xSE behavior - create new variables like plugin_dir and # cosave_ext instead. se_abbrev = u'' # Full name long_name = u'' # Exe to run exe = u'' # List of file names to use for version detection. Tried in order until # one exists. Needed because it's technically not required to install # the EXE. ver_files = [] # One level above the directory in which xSE plugins should be placed # (e.g. when plugins should be in Data\OBSE\Plugins, this should be # u'OBSE') plugin_dir = u'' # The magic tag that the cosaves use (e.g. u'SKSE'). If this is empty, # it signals that this script extender has no cosaves. cosave_tag = u'' # The extension that the cosaves use (e.g. u'.skse') cosave_ext = u'' # URL to download from url = u'' # Tooltip for mouse over the URL url_tip = u'' # A list of xSE plugins that fix the plugin/BSA handle problem. Empty # if that does not apply to this game. limit_fixer_plugins = [] class Sd(object): """Information about Script Dragon for this game.""" # Abbreviated name. If this is empty, it signals that no Script Dragon # is available for this game. sd_abbrev = u'' # Full name long_name = u'' # The directory, relative to the Data folder, into which Script Dragon # plugins will be installed. install_dir = u'' class Sp(object): """Information about SkyProc patchers for this game.""" # Abbreviated name. If this is empty, it signals that this game does # not support SkyProc patchers. sp_abbrev = u'' # Full name long_name = u'' # The directory, relative to the Data folder, into which SkyProc # patchers will be installed. install_dir = u'' class Ge(object): """Information about the Graphics Extender for this game.""" # Abbreviated name. If this is empty, it signals that no graphics # extender is available for this game. ge_abbrev = u'' # Full name long_name = u'' # exe is treated specially here. If it is a string, then it should # be the path relative to the root directory of the game, if it is # a list, each list element should be an iterable to pass to Path.join # relative to the root directory of the game. In this case, # each filename will be tested in reverse order. This was required # for Oblivion, as the newer OBGE has a different filename than the # older OBGE exe = u'' # URL to download from url = u'' # Tooltip for mouse over the URL url_tip = u'' class Laa(object): """Information about the LAA (Large Address Aware) launcher for this game.""" # Display name of the launcher laa_name = u'' # Executable to run exe = u'*DNE*' # Whether the launcher will automatically launch the SE launchesSE = False class Ini(object): """Information about this game's INI handling.""" # True means new lines are allowed to be added via INI tweaks # (by default) allow_new_lines = True # INI Entry to enable BSA Redirection - two empty strings if this game # does not need BSA redirection bsa_redirection_key = (u'', u'') # Name of game's default ini file. default_ini_file = u'' # INI files that should show up in the INI Edits tab. Note that the # first one *must* be the main INI! # Example: [u'Oblivion.ini'] dropdown_inis = [] # INI setting used to setup Save Profiles # (section, key) save_profiles_key = (u'General', u'SLocalSavePath') # Base dir for the save_profiles_key setting above save_prefix = u'Saves' # INI setting used to enable or disable screenshots # (section, key, default value) screenshot_enabled_key = (u'Display', u'bAllowScreenShot', u'1') # INI setting used to set base screenshot name # (section, key, default value) screenshot_base_key = (u'Display', u'sScreenShotBaseName', u'ScreenShot') # INI setting used to set screenshot index # (section, key, default value) screenshot_index_key = (u'Display', u'iScreenShotIndex', u'0') # The INI entries listing vanilla BSAs to load resource_archives_keys = () # An INI key listing BSAs that will override all plugin BSAs. Blank if # it doesn't exist for this game resource_override_key = u'' # The default value for resource_override_key if it's missing from the # game INI resource_override_defaults = [] # Whether this game supports mod ini files aka ini fragments supports_mod_inis = True class Ess(object): """Information about WB's capabilities with regards to save file viewing and editing for this game.""" # Can read the info needed for the Save Tab display canReadBasic = True # Advanced editing canEditMore = False # Save file extension ext = u'.ess' # If True, then this game will reliably and safely remove a missing # master from an existing save if you just load the game without that # master can_safely_remove_masters = False class Bsa(object): """Information about the BSAs (Bethesda Archives) used by this game.""" # Whether or not the INI setting ResetBSATimestamps should have any # effect on this game allow_reset_timestamps = False # Part of a regex used to determine which BSAs will attach to a plugin. # The full regex prepends the base name of the plugin (e.g. for # MyMod.esp, MyMod will be prepended) and appends Bsa.bsa_extension. # Most games accept arbitrary BSA names, hence this default attachment_regex = r'(?: \- \w+)?' # The extension used for BSA files bsa_extension = u'.bsa' # Whether or not the Archive.exe tool for this game creates BSL files has_bsl = False # Maps BSA names to the date to which they should be redated. Fallback # will be used for BSAs which are not explicitly listed. Format is # ISO 8601 (year-month-day). Generally used to redate the vanilla BSAs # before all mod BSAs, and all BSAs before loose files by choosing # dates older than the game's release date. redate_dict = defaultdict(lambda: u'2006-01-01') # All BSA versions accepted by this game. If empty, indicates that this # game does not use BSA versions and so BSA version checks will be # skipped entirely. valid_versions = set() class Psc(object): """Information about script sources (only Papyrus right now) for this game.""" # Extensions for external script sources. Empty if this game doesn't # have any. source_extensions = set() # Maps directories from which BAIN should redirect script sources from # to the directories that BAIN should redirect them to. Empty if this # is not applicable to this game. source_redirects = {} class Xe(object): """Information about xEdit for this game.""" # The name that xEdit has for this game, e.g. 'TES5Edit' for Skyrim full_name = u'xEdit' # A prefix for settings keys related to this version of xEdit (e.g. # expert mode) xe_key_prefix = u'' class Bain(object): """Information about what BAIN should do for this game.""" # The allowed default data directories that BAIN can install to data_dirs = { u'ini', u'meshes', u'music', u'sound', u'textures', u'video' } # Directories in the Data folder to exclude from Clean Data keep_data_dirs = set() # Files in the Data folder to exclude from Clean Data keep_data_files = set() # File prefixes in the Data folder to exclude from Clean Data keep_data_file_prefixes = set() # Files BAIN shouldn't skip no_skip = () # Directories where specific file extensions should not be skipped no_skip_dirs = { # BashTags files are obviously not docs, so don't skip them u'bashtags': [u'.txt'], } # Folders BAIN should never CRC check in the Data directory skip_bain_refresh = set( # Use lowercase names ) # Wrye Bash files to exclude from Clean Data wrye_bash_data_files = set() # Wrye Bash directories to exclude from Clean Data wrye_bash_data_dirs = {u'Bash Patches', u'BashTags', u'INI Tweaks'} # Plugin format stuff class Esp(object): # Wrye Bash capabilities # Can create Bashed Patches canBash = False # Can edit basic info in the main header record - generally has # signature b'TES4' canEditHeader = False # Valid ESM/ESP header versions. These are the valid 'version' numbers # for the game file headers validHeaderVersions = tuple() # used to locate string translation files stringsFiles = [ u'%(body)s_%(language)s.STRINGS', u'%(body)s_%(language)s.DLSTRINGS', u'%(body)s_%(language)s.ILSTRINGS', ] # Signature of the main plugin header record type plugin_header_sig = b'TES4' # If True, then plugins with at least one master can use the # 0x000-0x800 range for their own records. # If False, that range is reserved for hardcoded engine records. expanded_plugin_range = False # If True, check if the main header's DATA subrecords match the on-disk # master sizes and highlight the corresponding masters with a light # background color if that is the case. Needs meaningful information in # the DATA subrecords. check_master_sizes = False # If True, generate ONAM by reading each temp CELL child when adding # the ESM flag to plugins and discard it when removing the ESM flag. generate_temp_child_onam = False # The maximum number of entries inside a leveled list for this game. # Zero means no limit. max_lvl_list_size = 0 # A tuple containing all biped flag names (in order) for this game biped_flag_names = () # The maximum number of masters that a plugin can have for this game. master_limit = 255 # 256 - 1 for the plugin itself # All 'reference' types, i.e. record types that occur in CELL/WLRD # groups and place some sort of thing into the cell (e.g. ACHR, REFR, # PMIS, etc.) reference_types = set() # Class attributes moved to constants module, set dynamically at init #--Game ESM/ESP/BSA files ## These are all of the ESM,ESP,and BSA data files that belong to the game ## These filenames need to be in lowercase, bethDataFiles = set() # initialize with literal # Known record types - maps integers from the save format to human-readable # names for the record types. Used in save editing code. save_rec_types = {} # Set in game/*/default_tweaks.py, this is a dictionary mapping names for # 'default' INI tweaks (i.e. ones that we ship with WB and that can't be # deleted) to OrderedDicts that implement the actual tweaks. See # DefaultIniFile.__init__ for how the tweaks are parsed. default_tweaks = {} # Set in game/*/vanilla_files.py, this is a set listing every file that # exists in the Data directory of the game in a purely vanilla # installation. Set in a separate file because this can be *very* large, # and would make editing the constants a miserable experience if included # (see e.g. skyrim/vanilla_files.py). vanilla_files = set() @property def plugin_header_class(self): return brec.MreRecord.type_class[self.Esp.plugin_header_sig] @classmethod def init(cls): # Setting RecordHeader class variables -------------------------------- # Top types in order of the main ESM header_type = brec.RecordHeader header_type.top_grup_sigs = [] header_type.valid_header_sigs = set(header_type.top_grup_sigs + [b'GRUP', b'TES4']) # Record Types brec.MreRecord.type_class = {x.rec_sig: x for x in ()} # Simple records brec.MreRecord.simpleTypes = (set(brec.MreRecord.type_class) - {b'TES4'}) cls._validate_records() @classmethod def _dynamic_import_modules(cls, package_name): """Dynamically import package modules to avoid importing them for every game. We need to pass the package name in for importlib to work. Currently populates the GameInfo namespace with the members defined in the relevant constants.py and imports default_tweaks.py and vanilla_files.py.""" tweaks_module = importlib.import_module(u'.default_tweaks', package=package_name) cls.default_tweaks = tweaks_module.default_tweaks vf_module = importlib.import_module(u'.vanilla_files', package=package_name) cls.vanilla_files = vf_module.vanilla_files @staticmethod def _validate_records(): """Performs validation on the record syntax for all decoded records.""" sr_to_r = brec.MreRecord.subrec_sig_to_record_sig for rec_class in brec.MreRecord.type_class.itervalues(): if issubclass(rec_class, brec.MelRecord): rec_class.validate_record_syntax() for sr_sig in rec_class.melSet.loaders: sr_to_r[sr_sig].add(rec_class.rec_sig) @classmethod def supported_games(cls): game_types = set(cls.__subclasses__()) game_types.update( chain.from_iterable(c.__subclasses__() for c in list(game_types))) return game_types @classmethod def test_game_path(cls, test_path): """Helper method to determine if required game detection files are present, and no excluded files are present, in the test path.""" return (all( test_path.join(p).exists() for p in cls.game_detect_includes) and not any( test_path.join(p).exists() for p in cls.game_detect_excludes))
from os.path import join as _j, abspath as _a, exists as _e, dirname as _d, basename as _b from os import environ as ENV import shutil import re import ctypes.util import sys import os import textwrap # NOTE: Don't import logger here since rlscope_logging needs py_config. # from rlscope.profiler.rlscope_logging import logger import rlscope INSTALL_ROOT = _d(os.path.realpath(rlscope.__file__)) CPP_LIB = _j(INSTALL_ROOT, 'cpp', 'lib') CPP_BIN = _j(INSTALL_ROOT, 'cpp', 'bin') CPP_INCLUDE = _j(INSTALL_ROOT, 'cpp', 'include') USE_NUMBA = False nb = None if USE_NUMBA: import numba as nb ROOT = _d(_d(_a(__file__))) RLSCOPE_DIR = ROOT GIT_REPO_URL = "https://github.com/UofT-EcoSystem/rlscope" RLSCOPE_TEST_DIR = _j(RLSCOPE_DIR, 'test_results')
class OblivionGameInfo(GameInfo): displayName = u'Oblivion' fsName = u'Oblivion' altName = u'Wrye Bash' bash_root_prefix = u'Oblivion' launch_exe = u'Oblivion.exe' game_detect_file = _j(u'Data', u'Oblivion.esm') version_detect_file = u'Oblivion.exe' master_file = u'Oblivion.esm' pklfile = u'Oblivion_ids.pkl' masterlist_dir = u'Oblivion' regInstallKeys = (u'Bethesda Softworks\\Oblivion', u'Installed Path') nexusUrl = u'https://www.nexusmods.com/oblivion/' nexusName = u'Oblivion Nexus' nexusKey = 'bash.installers.openOblivionNexus.continue' patchURL = u'http://www.elderscrolls.com/downloads/updates_patches.htm' patchTip = u'http://www.elderscrolls.com/' using_txt_file = False has_standalone_pluggy = True class Ck(GameInfo.Ck): ck_abbrev = u'TESCS' long_name = u'Construction Set' exe = u'TESConstructionSet.exe' se_args = u'-editor' image_name = u'tescs%s.png' class Se(GameInfo.Se): se_abbrev = u'OBSE' long_name = u'Oblivion Script Extender' exe = u'obse_loader.exe' # Not sure why we need obse_1_2_416.dll, was there before refactoring ver_files = [ u'obse_loader.exe', u'obse_steam_loader.dll', u'obse_1_2_416.dll' ] plugin_dir = u'OBSE' cosave_tag = u'OBSE' cosave_ext = u'.obse' url = u'http://obse.silverlock.org/' url_tip = u'http://obse.silverlock.org/' class Ge(GameInfo.Ge): ge_abbrev = u'OBGE' long_name = u'Oblivion Graphics Extender' exe = [ (u'obse', u'plugins', u'obge.dll'), (u'obse', u'plugins', u'obgev2.dll'), (u'obse', u'plugins', u'oblivionreloaded.dll'), ] url = u'https://www.nexusmods.com/oblivion/mods/30054' url_tip = u'https://www.nexusmods.com/oblivion' class Ini(GameInfo.Ini): allow_new_lines = False bsa_redirection_key = (u'Archive', u'sArchiveList') default_ini_file = u'Oblivion_default.ini' dropdown_inis = [u'Oblivion.ini'] supports_mod_inis = False class Ess(GameInfo.Ess): canEditMore = True class Bsa(GameInfo.Bsa): allow_reset_timestamps = True # Oblivion accepts the base name and literally *anything* after # that. E.g. MyModMeshes.bsa will load from a MyMod.esp plugin attachment_regex = u'.*' valid_versions = {0x67} class Xe(GameInfo.Xe): full_name = u'TES4Edit' xe_key_prefix = u'tes4View' class Bain(GameInfo.Bain): data_dirs = GameInfo.Bain.data_dirs | { u'_tejon', u'distantlod', u'facegen', u'fonts', u'menus', u'obse', u'pluggy', u'scripts', u'shaders', u'streamline', u'trees', } keep_data_dirs = { _j(u'OBSE', u'Plugins', u'ComponentDLLs', u'CSE'), u'LSData' } keep_data_files = { _j(u'OBSE', u'Plugins', u'Construction Set Extender.dll'), _j(u'OBSE', u'Plugins', u'Construction Set Extender.ini'), } keep_data_file_prefixes = { _j(u'Meshes', u'Characters', u'_Male', u'specialanims', u'0FemaleVariableWalk_'), } skip_bain_refresh = { u'tes4edit backups', u'tes4edit cache', u'bgsee', u'conscribe logs', } wrye_bash_data_files = {u'ArchiveInvalidationInvalidated!.bsa'} class Esp(GameInfo.Esp): canBash = True canCBash = True canEditHeader = True validHeaderVersions = (0.8, 1.0) stringsFiles = [] allTags = { u'Actors.ACBS', u'Actors.AIData', u'Actors.AIPackages', u'Actors.AIPackagesForceAdd', u'Actors.Anims', u'Actors.CombatStyle', u'Actors.DeathItem', u'Actors.RecordFlags', u'Actors.Skeleton', u'Actors.Spells', u'Actors.SpellsForceAdd', u'Actors.Stats', u'Body-F', u'Body-M', u'Body-Size-F', u'Body-Size-M', u'C.Climate', u'C.Light', u'C.Music', u'C.Name', u'C.Owner', u'C.RecordFlags', u'C.Regions', u'C.Water', u'Creatures.Blood', u'Creatures.Type', u'Deactivate', u'Delev', u'EffectStats', u'EnchantmentStats', u'Eyes', u'Factions', u'Filter', u'Graphics', u'Hair', u'IIM', u'Invent.Add', u'Invent.Change', u'Invent.Remove', u'MustBeActiveIfImported', u'Names', u'NoMerge', u'NPC.Class', u'NPC.Eyes', u'NPC.FaceGen', u'NPC.Hair', u'NPC.Race', u'NpcFacesForceFullImport', u'R.AddSpells', u'R.Attributes-F', u'R.Attributes-M', u'R.ChangeSpells', u'R.Description', u'R.Ears', u'R.Head', u'R.Mouth', u'R.Relations', u'R.Skills', u'R.Teeth', u'Relations.Add', u'Relations.Change', u'Relations.Remove', u'Relev', u'Roads', u'Scripts', u'Sound', u'SpellStats', u'Stats', u'Text', u'Voice-F', u'Voice-M', } patchers = ( u'PatchMerger', # PatchMerger must come first! u'ActorImporter', u'AlchemicalCatalogs', u'AliasesPatcher', u'AssortedTweaker', u'CellImporter', u'ClothesTweaker', u'CoblExhaustion', u'ContentsChecker', u'DeathItemPatcher', u'GmstTweaker', u'GraphicsPatcher', u'ImportActorsSpells', u'ImportEffectsStats', u'ImportEnchantmentStats', u'ImportFactions', u'ImportInventory', u'ImportRelations', u'ImportScripts', u'KFFZPatcher', u'ListsMerger', u'MFactMarker', u'NamesPatcher', u'NamesTweaker', u'NPCAIPackagePatcher', u'NpcFacePatcher', u'RacePatcher', u'RoadImporter', u'SEWorldEnforcer', u'SoundPatcher', u'SpellsPatcher', u'StatsPatcher', u'TextImporter', u'TweakActors', u'UpdateReferences', ) CBash_patchers = ( u'CBash_PatchMerger', # PatchMerger must come first! u'CBash_ActorImporter', u'CBash_AlchemicalCatalogs', u'CBash_AliasesPatcher', u'CBash_AssortedTweaker', u'CBash_CellImporter', u'CBash_ClothesTweaker', u'CBash_CoblExhaustion', u'CBash_ContentsChecker', u'CBash_DeathItemPatcher', u'CBash_GmstTweaker', u'CBash_GraphicsPatcher', u'CBash_ImportActorsSpells', u'CBash_ImportFactions', u'CBash_ImportInventory', u'CBash_ImportRelations', u'CBash_ImportScripts', u'CBash_KFFZPatcher', u'CBash_ListsMerger', u'CBash_MFactMarker', u'CBash_NamesPatcher', u'CBash_NamesTweaker', u'CBash_NPCAIPackagePatcher', u'CBash_NpcFacePatcher', u'CBash_RacePatcher', u'CBash_RoadImporter', u'CBash_SEWorldEnforcer', u'CBash_SoundPatcher', u'CBash_SpellsPatcher', u'CBash_StatsPatcher', u'CBash_TweakActors', u'CBash_UpdateReferences', ) weaponTypes = ( _(u'Blade (1 Handed)'), _(u'Blade (2 Handed)'), _(u'Blunt (1 Handed)'), _(u'Blunt (2 Handed)'), _(u'Staff'), _(u'Bow'), ) raceNames = { 0x23fe9: _(u'Argonian'), 0x224fc: _(u'Breton'), 0x191c1: _(u'Dark Elf'), 0x19204: _(u'High Elf'), 0x00907: _(u'Imperial'), 0x22c37: _(u'Khajiit'), 0x224fd: _(u'Nord'), 0x191c0: _(u'Orc'), 0x00d43: _(u'Redguard'), 0x00019: _(u'Vampire'), 0x223c8: _(u'Wood Elf'), } raceShortNames = { 0x23fe9: u'Arg', 0x224fc: u'Bre', 0x191c1: u'Dun', 0x19204: u'Alt', 0x00907: u'Imp', 0x22c37: u'Kha', 0x224fd: u'Nor', 0x191c0: u'Orc', 0x00d43: u'Red', 0x223c8: u'Bos', } raceHairMale = { 0x23fe9: 0x64f32, #--Arg 0x224fc: 0x90475, #--Bre 0x191c1: 0x64214, #--Dun 0x19204: 0x7b792, #--Alt 0x00907: 0x90475, #--Imp 0x22c37: 0x653d4, #--Kha 0x224fd: 0x1da82, #--Nor 0x191c0: 0x66a27, #--Orc 0x00d43: 0x64215, #--Red 0x223c8: 0x690bc, #--Bos } raceHairFemale = { 0x23fe9: 0x64f33, #--Arg 0x224fc: 0x1da83, #--Bre 0x191c1: 0x1da83, #--Dun 0x19204: 0x690c2, #--Alt 0x00907: 0x1da83, #--Imp 0x22c37: 0x653d0, #--Kha 0x224fd: 0x1da83, #--Nor 0x191c0: 0x64218, #--Orc 0x00d43: 0x64210, #--Red 0x223c8: 0x69473, #--Bos } @classmethod def init(cls): cls._dynamic_import_modules(__name__) from .records import MreActi, MreAlch, MreAmmo, MreAnio, MreAppa, \ MreArmo, MreBook, MreBsgn, MreClas, MreClot, MreCont, MreCrea, \ MreDoor, MreEfsh, MreEnch, MreEyes, MreFact, MreFlor, MreFurn, \ MreGras, MreHair, MreIngr, MreKeym, MreLigh, MreLscr, MreLvlc, \ MreLvli, MreLvsp, MreMgef, MreMisc, MreNpc, MrePack, MreQust, \ MreRace, MreScpt, MreSgst, MreSlgm, MreSoun, MreSpel, MreStat, \ MreTree, MreWatr, MreWeap, MreWthr, MreClmt, MreCsty, MreIdle, \ MreLtex, MreRegn, MreSbsp, MreSkil, MreAchr, MreAcre, MreCell, \ MreGmst, MreRefr, MreRoad, MreTes4, MreWrld, MreDial, MreInfo, \ MrePgrd cls.mergeClasses = ( MreActi, MreAlch, MreAmmo, MreAnio, MreAppa, MreArmo, MreBook, MreBsgn, MreClas, MreClot, MreCont, MreCrea, MreDoor, MreEfsh, MreEnch, MreEyes, MreFact, MreFlor, MreFurn, MreGlob, MreGras, MreHair, MreIngr, MreKeym, MreLigh, MreLscr, MreLvlc, MreLvli, MreLvsp, MreMgef, MreMisc, MreNpc, MrePack, MreQust, MreRace, MreScpt, MreSgst, MreSlgm, MreSoun, MreSpel, MreStat, MreTree, MreWatr, MreWeap, MreWthr, MreClmt, MreCsty, MreIdle, MreLtex, MreRegn, MreSbsp, MreSkil, MreAchr, MreAcre, MreCell, MreGmst, MreRefr, MreRoad, MreWrld, MreDial, MreInfo, MreLand, MrePgrd, ) cls.readClasses = ( MreMgef, MreScpt, ) cls.writeClasses = (MreMgef, ) # Setting RecordHeader class variables - Oblivion is special header_type = brec.RecordHeader header_type.rec_header_size = 20 header_type.rec_pack_format = [u'=4s', u'I', u'I', u'I', u'I'] header_type.rec_pack_format_str = u''.join(header_type.rec_pack_format) header_type.header_unpack = struct.Struct( header_type.rec_pack_format_str).unpack header_type.pack_formats = {0: u'=4sI4s2I'} header_type.pack_formats.update( {x: u'=4s4I' for x in {1, 6, 7, 8, 9, 10}}) header_type.pack_formats.update({x: u'=4sIi2I' for x in {2, 3}}) header_type.pack_formats.update({x: u'=4sIhh2I' for x in {4, 5}}) # Similar to other games header_type.top_grup_sigs = [ b'GMST', b'GLOB', b'CLAS', b'FACT', b'HAIR', b'EYES', b'RACE', b'SOUN', b'SKIL', b'MGEF', b'SCPT', b'LTEX', b'ENCH', b'SPEL', b'BSGN', b'ACTI', b'APPA', b'ARMO', b'BOOK', b'CLOT', b'CONT', b'DOOR', b'INGR', b'LIGH', b'MISC', b'STAT', b'GRAS', b'TREE', b'FLOR', b'FURN', b'WEAP', b'AMMO', b'NPC_', b'CREA', b'LVLC', b'SLGM', b'KEYM', b'ALCH', b'SBSP', b'SGST', b'LVLI', b'WTHR', b'CLMT', b'REGN', b'CELL', b'WRLD', b'DIAL', b'QUST', b'IDLE', b'PACK', b'CSTY', b'LSCR', b'LVSP', b'ANIO', b'WATR', b'EFSH', ] header_type.valid_header_sigs = set(header_type.top_grup_sigs + [ b'GRUP', b'TES4', b'ROAD', b'REFR', b'ACHR', b'ACRE', b'PGRD', b'LAND', b'INFO' ]) brec.MreRecord.type_class = { x.rec_sig: x for x in (MreAchr, MreAcre, MreActi, MreAlch, MreAmmo, MreAnio, MreAppa, MreArmo, MreBook, MreBsgn, MreCell, MreClas, MreClot, MreCont, MreCrea, MreDoor, MreEfsh, MreEnch, MreEyes, MreFact, MreFlor, MreFurn, MreGlob, MreGmst, MreGras, MreHair, MreIngr, MreKeym, MreLigh, MreLscr, MreLvlc, MreLvli, MreLvsp, MreMgef, MreMisc, MreNpc, MrePack, MreQust, MreRace, MreRefr, MreRoad, MreScpt, MreSgst, MreSkil, MreSlgm, MreSoun, MreSpel, MreStat, MreTree, MreTes4, MreWatr, MreWeap, MreWrld, MreWthr, MreClmt, MreCsty, MreIdle, MreLtex, MreRegn, MreSbsp, MreDial, MreInfo, MreLand, MrePgrd) } brec.MreRecord.simpleTypes = (set(brec.MreRecord.type_class) - { b'TES4', b'ACHR', b'ACRE', b'REFR', b'CELL', b'PGRD', b'ROAD', b'LAND', b'WRLD', b'INFO', b'DIAL' }) cls._validate_records()