Skip to content

Commit 1afc48a

Browse files
committed
Updated Script
Check changelog.md
1 parent 001642e commit 1afc48a

3 files changed

Lines changed: 166 additions & 59 deletions

File tree

README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,19 @@ I just update this from time to time to be updated along side Fallout 76 - <a hr
1212
* Run the file from the command line or vortex using:
1313
* for the .py: `py createCustomIni.py`
1414
* for the .exe: `createCustomIni.exe`
15+
* The script will automatically detect your Fallout 76 directory (including OneDrive locations)
1516
* Verify the Fallout76Custom.ini looks correct the first few times... maybe....
1617

18+
## Features
19+
* **Smart Path Detection**: Automatically finds your Fallout 76 directory whether it's in standard Documents or OneDrive
20+
* **OneDrive Support**: Works with OneDrive Personal, Business, and redirected Documents folders
21+
* **Error Handling**: Better error messages and validation for common issues
22+
* **UTF-8 Support**: Proper encoding support for international characters in mod names
23+
1724
## Options
1825
* __-h__ __--help__ Show the help message
1926
* __--datafolder__ Specify fallout76\'s data folder location (Default: current directory)
20-
* __--inifolder__ Specify the folder where Fallout76Custom.ini lives (Default: C:\Users\[*current_user*]\Documents\My Games\Fallout 76)
27+
* __--inifolder__ Specify the folder where Fallout76Custom.ini lives (Default: Auto-detected from Documents or OneDrive)
2128
* __--inifilename__ Specify the filename for the ini (Default: Fallout76Custom.ini)
2229
* __--runasadmin__ Run the program as administrator, will ask for permission
2330
* __--copyinicontents__ Copy a file's contents in to your .ini

changelog.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,31 @@
11
# Changelog
22

3-
## Formatting and Styling
3+
## Latest Updates - Smart Path Detection & Robustness Improvements
4+
5+
### Path Detection Enhancement
6+
- **Smart Directory Finding**: Added `find_fallout76_directory()` function that automatically detects Fallout 76 directory location
7+
- **OneDrive Support**: Now supports multiple OneDrive configurations:
8+
- OneDrive Personal (`OneDrive\Documents\My Games\Fallout 76`)
9+
- OneDrive Business (`OneDrive - Business\Documents\My Games\Fallout 76`)
10+
- OneDrive with redirected Documents folder
11+
- Standard Documents location as fallback
12+
- **User Feedback**: Added console output showing which directory was found/used
13+
14+
### Error Handling & Robustness
15+
- **Input Validation**: Added validation to check if data folder exists before processing
16+
- **Permission Handling**: Better error messages for permission issues with suggestion to use `--runasadmin`
17+
- **UTF-8 Encoding**: Explicit UTF-8 encoding for file operations to handle international characters
18+
- **Import File Validation**: Check if import file exists before attempting to read it
19+
- **Graceful Error Handling**: Comprehensive try-catch blocks with informative error messages
20+
21+
### User Experience Improvements
22+
- **Progress Feedback**: Added console output showing scan progress and file creation status
23+
- **Better Error Messages**: More descriptive error messages with actionable suggestions
24+
- **Success Confirmation**: Clear confirmation when ini file is successfully created
25+
26+
---
27+
28+
## Previous Updates - Formatting and Styling
429
- Reformatted docstring for consistency.
530
- Replaced single quotes with double quotes for string literals.
631
- Improved readability by reorganizing the argument parser setup.

createCustomIni.py

Lines changed: 132 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -7,35 +7,77 @@
77
import os
88
import sys
99

10-
# Set the default home and mod directories
11-
HOME_DIR = os.path.expanduser("~") + "\\Documents\\My Games\\Fallout 76"
10+
# Set the default filename
1211
FILENAME = "Fallout76Custom.ini"
1312

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+
1454
# Get arguments from the user
1555
parser = argparse.ArgumentParser(
1656
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."
1959
)
2060
parser.add_argument(
2161
"--datafolder",
2262
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)",
2464
)
2565
parser.add_argument(
2666
"--inifolder",
2767
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+
),
2971
)
3072
parser.add_argument(
3173
"--inifilename",
3274
default=FILENAME,
33-
help="Specify the filename for the ini (Default: {})".format(FILENAME)
75+
help="Specify the filename for the ini (Default: {})".format(FILENAME),
3476
)
3577
parser.add_argument(
3678
"--runasadmin",
3779
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.",
3981
)
4082
parser.add_argument(
4183
"--copyinicontents", help="Copy a file's contents into your custom .ini"
@@ -123,65 +165,98 @@
123165
]
124166
# The array index from the RESOURCE_MAP for sResourceArchive2List
125167
SR_2LIST_INDEX = 3
168+
MOD_TO_PLACE_LAST = "InventOmaticStash-UO.ba2"
126169

127170
# Re-run the program with admin rights if needed
128171
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+
)
130175
sys.exit(0)
131176

132177
# Create any missing folders
133178
os.makedirs(os.path.dirname(ini_file_path), exist_ok=True)
134179

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+
135188
# 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)
171227

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 = ""
174231

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!")
179252

180-
custom_ini_file.write(
181-
"{} = {}\r\n".format(resource["filename"], line_content)
182-
)
253+
print(f"Successfully created {ini_file_path}")
183254

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

Comments
 (0)