|
7 | 7 | import os |
8 | 8 | import sys |
9 | 9 |
|
10 | | -# Set the default home and mod directories |
11 | | -HOME_DIR = os.path.expanduser("~") + "\\Documents\\My Games\\Fallout 76" |
| 10 | +# Set the default filename |
12 | 11 | FILENAME = "Fallout76Custom.ini" |
13 | 12 |
|
| 13 | + |
| 14 | +def find_fallout76_directory(): |
| 15 | + """ |
| 16 | + Find the Fallout 76 directory by checking multiple possible locations. |
| 17 | + Returns the path if found, otherwise returns the default path. |
| 18 | + """ |
| 19 | + user_home = os.path.expanduser("~") |
| 20 | + |
| 21 | + # Possible locations to check (in order of preference) |
| 22 | + possible_paths = [ |
| 23 | + # OneDrive Documents location |
| 24 | + os.path.join(user_home, "OneDrive", "Documents", "My Games", "Fallout 76"), |
| 25 | + # Standard Documents location |
| 26 | + os.path.join(user_home, "Documents", "My Games", "Fallout 76"), |
| 27 | + # Alternative OneDrive path structure |
| 28 | + os.path.join( |
| 29 | + user_home, "OneDrive - Personal", "Documents", "My Games", "Fallout 76" |
| 30 | + ), |
| 31 | + # Check if OneDrive redirected the entire Documents folder |
| 32 | + os.path.join(user_home, "OneDrive", "My Games", "Fallout 76"), |
| 33 | + # Business OneDrive |
| 34 | + os.path.join( |
| 35 | + user_home, "OneDrive - Business", "Documents", "My Games", "Fallout 76" |
| 36 | + ), |
| 37 | + ] |
| 38 | + |
| 39 | + # Check each possible path |
| 40 | + for path in possible_paths: |
| 41 | + if os.path.exists(path): |
| 42 | + print(f"Found Fallout 76 directory at: {path}") |
| 43 | + return path |
| 44 | + |
| 45 | + # If none found, return the standard path (will be created if needed) |
| 46 | + default_path = os.path.join(user_home, "Documents", "My Games", "Fallout 76") |
| 47 | + print(f"Using default Fallout 76 directory: {default_path}") |
| 48 | + return default_path |
| 49 | + |
| 50 | + |
| 51 | +# Set the default home directory using the finder function |
| 52 | +HOME_DIR = find_fallout76_directory() |
| 53 | + |
14 | 54 | # Get arguments from the user |
15 | 55 | parser = argparse.ArgumentParser( |
16 | 56 | description="This program will automatically create the " |
17 | | - "Fallout76Custom.ini file for you. In most cases the " |
18 | | - "default arguments will be fine." |
| 57 | + "Fallout76Custom.ini file for you. In most cases the " |
| 58 | + "default arguments will be fine." |
19 | 59 | ) |
20 | 60 | parser.add_argument( |
21 | 61 | "--datafolder", |
22 | 62 | default=".", |
23 | | - help="Specify Fallout 76's data folder location (Default: current directory)" |
| 63 | + help="Specify Fallout 76's data folder location (Default: current directory)", |
24 | 64 | ) |
25 | 65 | parser.add_argument( |
26 | 66 | "--inifolder", |
27 | 67 | default=HOME_DIR, |
28 | | - help="Specify the folder where Fallout76Custom.ini lives (Default: {})".format(HOME_DIR) |
| 68 | + help="Specify the folder where Fallout76Custom.ini lives (Default: {})".format( |
| 69 | + HOME_DIR |
| 70 | + ), |
29 | 71 | ) |
30 | 72 | parser.add_argument( |
31 | 73 | "--inifilename", |
32 | 74 | default=FILENAME, |
33 | | - help="Specify the filename for the ini (Default: {})".format(FILENAME) |
| 75 | + help="Specify the filename for the ini (Default: {})".format(FILENAME), |
34 | 76 | ) |
35 | 77 | parser.add_argument( |
36 | 78 | "--runasadmin", |
37 | 79 | action="store_true", |
38 | | - help="Runs as an admin. Use when Fallout 76 is installed in UAC location." |
| 80 | + help="Runs as an admin. Use when Fallout 76 is installed in UAC location.", |
39 | 81 | ) |
40 | 82 | parser.add_argument( |
41 | 83 | "--copyinicontents", help="Copy a file's contents into your custom .ini" |
|
123 | 165 | ] |
124 | 166 | # The array index from the RESOURCE_MAP for sResourceArchive2List |
125 | 167 | SR_2LIST_INDEX = 3 |
| 168 | +MOD_TO_PLACE_LAST = "InventOmaticStash-UO.ba2" |
126 | 169 |
|
127 | 170 | # Re-run the program with admin rights if needed |
128 | 171 | if is_admin: |
129 | | - ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, __file__, None, 1) |
| 172 | + ctypes.windll.shell32.ShellExecuteW( |
| 173 | + None, "runas", sys.executable, __file__, None, 1 |
| 174 | + ) |
130 | 175 | sys.exit(0) |
131 | 176 |
|
132 | 177 | # Create any missing folders |
133 | 178 | os.makedirs(os.path.dirname(ini_file_path), exist_ok=True) |
134 | 179 |
|
| 180 | +# Validate that the data folder exists |
| 181 | +if not os.path.exists(mods_dir): |
| 182 | + print(f"Error: Data folder '{mods_dir}' does not exist!") |
| 183 | + sys.exit(1) |
| 184 | + |
| 185 | +print(f"Scanning for mods in: {mods_dir}") |
| 186 | +print(f"Creating ini file at: {ini_file_path}") |
| 187 | + |
135 | 188 | # Open the Custom.ini file for writing |
136 | | -with open(ini_file_path, "w+") as custom_ini_file: |
137 | | - # Write the section header to the file |
138 | | - custom_ini_file.write("[Archive]\r\n") |
139 | | - |
140 | | - # Loop through the resource map and add mods to the correct places |
141 | | - for _, _, filenames in os.walk(mods_dir): |
142 | | - for file in filenames: |
143 | | - # Make sure the file is not an official file (starts with "SeventySix") |
144 | | - # and is a ba2 (file extension) |
145 | | - if not file.startswith("SeventySix") and file.lower().endswith(".ba2"): |
146 | | - found = False |
147 | | - for resource in RESOURCE_MAP: |
148 | | - if file in resource["mods"]: |
149 | | - resource["found_mods"].append(file) |
150 | | - found = True |
151 | | - break |
152 | | - # If a mod doesn't appear in the one of the other mod lists, add it to the default |
153 | | - if not found: |
154 | | - RESOURCE_MAP[SR_2LIST_INDEX]["found_mods"].append(file) |
155 | | - break |
156 | | - |
157 | | - # Loop through the resource map and add the correct lines to the ini file |
158 | | - for resource in RESOURCE_MAP: |
159 | | - if resource["found_mods"]: |
160 | | - found_mods = set(resource["found_mods"]) |
161 | | - mods = resource["mods"] |
162 | | - mod_list = ", ".join(mod for mod in mods if mod in found_mods) |
163 | | - |
164 | | - # Get any mods that don't show up in the mods list (for the default list) |
165 | | - diff_list = [item for item in found_mods if item not in mods] |
166 | | - if diff_list: |
167 | | - diff_list.sort() |
168 | | - diff_list = ", " + ", ".join(diff_list) |
169 | | - else: |
170 | | - diff_list = "" |
| 189 | +try: |
| 190 | + with open(ini_file_path, "w+", encoding="utf-8") as custom_ini_file: |
| 191 | + # Write the section header to the file |
| 192 | + custom_ini_file.write("[Archive]\r\n") |
| 193 | + |
| 194 | + # Loop through the resource map and add mods to the correct places |
| 195 | + for _, _, filenames in os.walk(mods_dir): |
| 196 | + for file in filenames: |
| 197 | + # Make sure the file is not an official file (starts with "SeventySix") |
| 198 | + # and is a ba2 (file extension) |
| 199 | + if not file.startswith("SeventySix") and file.lower().endswith(".ba2"): |
| 200 | + found = False |
| 201 | + for resource in RESOURCE_MAP: |
| 202 | + if file in resource["mods"]: |
| 203 | + resource["found_mods"].append(file) |
| 204 | + found = True |
| 205 | + break |
| 206 | + # If a mod doesn't appear in the one of the other mod lists, add it to the default |
| 207 | + if not found: |
| 208 | + RESOURCE_MAP[SR_2LIST_INDEX]["found_mods"].append(file) |
| 209 | + break |
| 210 | + |
| 211 | + # Loop through the resource map and add the correct lines to the ini file |
| 212 | + for resource in RESOURCE_MAP: |
| 213 | + if resource["found_mods"]: |
| 214 | + found_mods = set(resource["found_mods"]) |
| 215 | + mods = resource["mods"] |
| 216 | + mod_list = ", ".join(mod for mod in mods if mod in found_mods) |
| 217 | + |
| 218 | + # Get any mods that don't show up in the mods list (for the default list) |
| 219 | + diff_list = [item for item in found_mods if item not in mods] |
| 220 | + if diff_list: |
| 221 | + diff_list.sort() |
| 222 | + |
| 223 | + # Ensure MOD_TO_PLACE_LAST is at the end of the list |
| 224 | + if MOD_TO_PLACE_LAST in diff_list: |
| 225 | + diff_list.remove(MOD_TO_PLACE_LAST) |
| 226 | + diff_list.append(MOD_TO_PLACE_LAST) |
171 | 227 |
|
172 | | - # Make the default list a string |
173 | | - default_mods = ", ".join(resource["default_mods"]) |
| 228 | + diff_list = ", " + ", ".join(diff_list) |
| 229 | + else: |
| 230 | + diff_list = "" |
174 | 231 |
|
175 | | - # Write the resource line to the ini file without leading comma |
176 | | - line_content = "{}{}".format(default_mods, mod_list + diff_list) |
177 | | - if line_content.startswith(", "): |
178 | | - line_content = line_content[2:] |
| 232 | + # Make the default list a string |
| 233 | + default_mods = ", ".join(resource["default_mods"]) |
| 234 | + |
| 235 | + # Write the resource line to the ini file without leading comma |
| 236 | + line_content = "{}{}".format(default_mods, mod_list + diff_list) |
| 237 | + if line_content.startswith(", "): |
| 238 | + line_content = line_content[2:] |
| 239 | + |
| 240 | + custom_ini_file.write( |
| 241 | + "{} = {}\r\n".format(resource["filename"], line_content) |
| 242 | + ) |
| 243 | + |
| 244 | + # Copy contents of a custom file into the custom.ini |
| 245 | + if import_ini: |
| 246 | + if os.path.exists(import_ini): |
| 247 | + with open(import_ini, "r", encoding="utf-8") as import_file: |
| 248 | + custom_ini_file.write(import_file.read()) |
| 249 | + print(f"Imported contents from: {import_ini}") |
| 250 | + else: |
| 251 | + print(f"Warning: Import file '{import_ini}' not found!") |
179 | 252 |
|
180 | | - custom_ini_file.write( |
181 | | - "{} = {}\r\n".format(resource["filename"], line_content) |
182 | | - ) |
| 253 | + print(f"Successfully created {ini_file_path}") |
183 | 254 |
|
184 | | - # Copy contents of a custom file into the custom.ini |
185 | | - if import_ini: |
186 | | - with open(import_ini, "r") as import_file: |
187 | | - custom_ini_file.write(import_file.read()) |
| 255 | +except PermissionError: |
| 256 | + print( |
| 257 | + f"Error: Permission denied writing to '{ini_file_path}'. Try running with --runasadmin" |
| 258 | + ) |
| 259 | + sys.exit(1) |
| 260 | +except Exception as e: |
| 261 | + print(f"Error creating ini file: {e}") |
| 262 | + sys.exit(1) |
0 commit comments