Skip to content

Instantly share code, notes, and snippets.

@EntranceJew
Last active May 18, 2024 21:47
Show Gist options
  • Save EntranceJew/fda074b3541a200477f4117ca2950e16 to your computer and use it in GitHub Desktop.
Save EntranceJew/fda074b3541a200477f4117ca2950e16 to your computer and use it in GitHub Desktop.
sort those archives
param(
[string]$mo2MyGames = (Join-Path -Path ([environment]::GetFolderPath("MyDocuments")) -ChildPath "My Games\Fallout 76"),
[string]$targetIni = "Fallout76Custom.ini",
[string]$mo2Instance="$env:LOCALAPPDATA\ModOrganizer\Fallout 76",
[string]$mo2Profile="Default",
[string]$mo2GameFolder = "${env:ProgramFiles(x86)}\Bethesda.net Launcher\games\Fallout76"
)
<#
THE PROGRAM, BROKEN DOWN:
1) determine the load order for mods
2) determine associated archives for each mod
3) write to the Fallout76Custom ini
TODO:
1) if we ever get the ability to determine config information from $env then do that
#>
#region Function Definitions
function Test-Installed($cmdname) {
return [bool](Get-Module -ListAvailable -Name $cmdname -ErrorAction SilentlyContinue)
}
function Test-Imported($cmdname) {
return [bool](Get-Command -Name $cmdname -ErrorAction SilentlyContinue)
}
#endregion
#region Collect Dependencies
if (-Not (Test-Installed "PsGet")){
Write-Host "PsGet was not installed, installing"
(new-object Net.WebClient).DownloadString("http://psget.net/GetPsGet.ps1") | Invoke-Expression
}
if (-Not (Test-Imported "Install-Module")) {
Write-Host "Install-Module was not imported, this may result in the script not executing correctly"
Import-Module -Name "PsGet"
}
if (-Not (Test-Installed "PsIni")) {
Write-Host "could not find PsIni, installing"
Install-Module -Name "PsIni"
}
if (-Not (Test-Imported "Get-IniContent")) {
Write-Host "Get-IniContent was not imported, this may result in the script not executing correctly"
Import-Module -Name "PsIni"
}
#endregion
<# get the loaded mod folder names, in order #>
$mods = @(Get-Content -Path "$mo2Instance\profiles\$mo2Profile\modlist.txt" | Where-Object {$_ -match '^\+.*'} | ForEach-Object {$_.substring(1)})
[array]::Reverse($mods)
<# load the existing ini #>
$ini = Get-IniContent "$mo2Instance\profiles\$mo2Profile\$targetIni"
if ( -Not ($ini.Contains('Archive'))) {
$ini['Archive'] = @{};
}
$arcs = @{
"sResourceIndexFileList" = @();
"sResourceStartUpArchiveList" = @();
"SResourceArchiveMemoryCacheList" = @();
"SResourceArchiveList" = @();
"SResourceArchiveList2" = @();
"sResourceArchive2List" = @();
}
<# get the archives #>
$archives = @(Get-ChildItem -Path "$mo2GameFolder\Data\SeventySix - *.ba2" | Select-Object -ExpandProperty 'Name');
foreach ($mod in $mods){
$archives += @(Get-ChildItem -Path "$mo2Instance\mods\$mod" -Include "*.ba2" -Recurse | Select-Object -ExpandProperty 'Name');
}
$ballpit = @();
foreach ($file in $archives){
Write-Output "sorting: $file"
if ($file -match " - Textures(\d{2})\.ba2$") {
$arcs['sResourceIndexFileList'] += $file;
}
if ($file -match " - (Interface|Localization|Shaders|Startup)\.ba2$") {
$arcs['sResourceStartUpArchiveList'] += $file;
}
if ($file -match " - (Interface|Materials|MiscClient|Shaders)\.ba2$") {
$arcs['SResourceArchiveMemoryCacheList'] += $file;
}
if ($file -match " - (GeneratedMeshes|Materials|Meshes(\d{2}|\w+)?|MiscClient|Sounds\d{2}|Startup|Voices)\.ba2$") {
$ballpit += $file;
} elseif ($file -match " - (Animations|Enlighten(Interiors|Exteriors\d{2})|GeneratedTextures)\.ba2$") {
$ballpit += $file;
} elseif ($file -match " - ATX_.*\.ba2$") {
# if it is named after DLC, it has to go here
$ballpit += $file;
} else {
# if it did not fit any description above, it gets tacked on at the end
$ballpit += $file;
}
}
<# smash a bunch of archives together in the 3 strings we have to do this with #>
$runsum = 0;
$maxLength = 1024;
$archiveKeys = @('SResourceArchiveList', 'SResourceArchiveList2', 'sResourceArchive2List')
$archiveIndex = 0;
foreach ($ball in $ballpit){
if ($runsum+$ball.length+1 -le $maxLength) {
$runsum += $ball.length+1;
$arcs[$archiveKeys[$archiveIndex]] += $ball;
} else {
if($archiveIndex -lt $archiveKeys.Length-1) {
$archiveIndex += 1;
$runsum = 0;
continue;
} else {
$arcs[$archiveKeys[$archiveIndex]] += $ball;
}
}
}
<# write it out #>
foreach ($kvp in $arcs.GetEnumerator()) {
$ini['Archive'][$kvp.Key] = ($kvp.Value -join ',');
}
Remove-Item -Path "$mo2Instance\profiles\$mo2Profile\$targetIni"
Out-IniFile -InputObject $ini -FilePath "$mo2Instance\profiles\$mo2Profile\$targetIni"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment