Created
October 11, 2022 09:36
-
-
Save SuperFlue/b8c811a61b90d5ab4bb6ea04a2938a4e to your computer and use it in GitHub Desktop.
Terra Invicta PowerShell save editor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Quick save editor for Terra Invicta in PowerShell | |
# Released under MIT license by <Superflue@github> | |
# Use PowerShell ISE or VSCode to more easily tweak stuff. | |
# Just place a breakpoint (F9) on the line pointed out at the bottom of the script | |
# And then you can use the examples in the if statement as a start | |
# This script handles the compressed saves (gzip) | |
# For simplicity we just hardcode the name of the save to edit (just call it "editsave") | |
# And the output is called "modifiedsave" | |
# This is just a simple way to avoid accidentally breaking an important save | |
$TargetSave = "$env:userprofile\Documents\My Games\TerraInvicta\Saves\editsave" | |
$ModifiedSave = "$env:userprofile\Documents\My Games\TerraInvicta\Saves\modifiedsave" | |
# We unpack the gzipped savefile here | |
$TempFile = "$env:temp\terrainvictasavetemp" | |
# Functions to unpack a GZIP | |
function Unpack-Gzip ([string]$CompressedFileName, [string]$DecompressedFileName) { | |
$CompressedFile = [System.IO.FileStream]::new($CompressedFileName, [System.IO.FileMode]::Open) | |
$DecompressedFile = [System.IO.FileStream]::new($DecompressedFileName, [System.IO.FileMode]::Create) | |
$Decompressor = [System.IO.Compression.GZipStream]::new($CompressedFile, [System.IO.Compression.CompressionMode]::Decompress) | |
$Decompressor.CopyTo($DecompressedFile) | |
$Decompressor.Dispose() | |
$CompressedFile.Close() | |
$DecompressedFile.Close() | |
} | |
# Function to pack a GZIP | |
function Pack-Gzip ([string]$TargetFileName, [string]$CompressedFileName) { | |
$TargetFile = [System.IO.FileStream]::new($TargetFileName, [System.IO.FileMode]::Open) | |
$CompressedFile = [System.IO.FileStream]::new($CompressedFileName, [System.IO.FileMode]::OpenOrCreate) | |
$Compressor = [System.IO.Compression.GZipStream]::new($CompressedFile, [System.IO.Compression.CompressionMode]::Compress) | |
$TargetFile.CopyTo($Compressor) | |
$Compressor.Dispose() | |
$TargetFile.Close() | |
$CompressedFile.Close() | |
} | |
# PowerShell 6 and upwards handles saving files without Byte Order Mark (BOM) | |
# But Powershell 5 does not, so we make a quick function to save properly | |
function Save-Utf8NoBom ([string]$textcontent,[string]$TargetFile) { | |
[System.IO.File]::WriteAllLines($TargetFile, $textcontent, [System.Text.UTF8Encoding]::new($False)) | |
} | |
# Quick function to just convert daily income to year values | |
# This is meant for the "baseIncomes_year" value | |
# So if you want an income of about 10 cash per day, you can use this | |
function YearValue ([float]$DayIncome) { | |
return [float]([float]$DayIncome * 365) | |
} | |
# Unpack savegame to temp file | |
Unpack-Gzip "$TargetSave.gz" "$TempFile" | |
# Convert savedata | |
$SaveData = Get-Content -Path $TempFile | ConvertFrom-Json | |
# Get correct player faction ID | |
$PlayerfactionID = $SaveData.gamestates.'PavonisInteractive.TerraInvicta.TIPlayerState'.Where({ $_.value -match "isAI=False" }).value.faction | |
# Get Faction data | |
$FactionData = $SaveData.gamestates.'PavonisInteractive.TerraInvicta.TIFactionState'.Where({ $_.Key -match $PlayerfactionID }).value | |
# Councilors get the player's councilors | |
$CouncilID = $FactionData.councilors.Value -join "|" | |
$PlayerCouncilors = $SaveData.gamestates.'PavonisInteractive.TerraInvicta.TICouncilorState'.Where({ $_.Key -match $CouncilID }) | |
# Putting the edit code in a if tag just to make it easier to work with | |
# But at the same time avoiding accitentally running commands your dont want | |
# When you are in debug (hitting the breakpoint) you can select a line (or multiple) and press F8 to run | |
if ($false) { | |
# List attributes for council | |
$PlayerCouncilors.Value.attributes | |
# Simple way to set all councilors specific stat to a specified level | |
$PlayerCouncilors.Value.attributes.ForEach({$_.Loyalty = 25}) | |
$PlayerCouncilors.Value.attributes.ForEach({$_.Administration = 25}) | |
# set councilors XP value | |
$PlayerCouncilors.Value.ForEach({$_.xp = 900}) | |
# This block below sets all couniclors stats to a minimum level | |
# If the stat level is above the minimum, they wont be changed | |
$minlvl = 25 | |
$Attributes = @( | |
"Persuasion" | |
"Espionage" | |
"Command" | |
"Investigation" | |
"Science" | |
"Administration" | |
"Security" | |
"Loyalty" | |
"ApparentLoyalty" | |
) | |
$MinimumLevel = { | |
if($psitem.$attrib -lt $minlvl){ | |
$psitem.$attrib = $minlvl | |
} | |
} | |
foreach ($attrib in $Attributes){ | |
$PlayerCouncilors.Value.attributes.ForEach($MinimumLevel) | |
} | |
# Resources stuff | |
# Modify income | |
# Most values are per year income. | |
# You can use the "YearValue" function to quickly get the right value for your wanted daily income | |
# MC and Projects are "constant" values and are not calculated by year | |
$FactionData.baseIncomes_year | |
$FactionData.baseIncomes_year.Influence = (YearValue 2) | |
$FactionData.baseIncomes_year.Money = (YearValue 1) | |
$FactionData.baseIncomes_year.Operations = (YearValue 1) | |
$FactionData.baseIncomes_year.Research = (YearValue 90) | |
$FactionData.baseIncomes_year.Boost = (YearValue 1) | |
$FactionData.baseIncomes_year.Projects = 4 | |
$FactionData.baseIncomes_year.MissionControl = 40 | |
$FactionData.baseIncomes_year | |
# Set resources to specific level | |
$FactionData.resources | |
$FactionData.resources.Money = 9000000 | |
$FactionData.resources.Influence = 80000 | |
$FactionData.resources.Boost = 700 | |
$FactionData.resources.Operations = 200 | |
$FactionData.resources | |
} | |
# Place breakpoint on line below with F9 and press F5 to run | |
#$SaveData | ConvertTo-Json -Depth 100 | Out-File $TempFile -Encoding utf8NoBOM | |
Save-Utf8NoBom -textcontent ($SaveData | ConvertTo-Json -Depth 100) -TargetFile $TempFile | |
# When you done modifying, just press F5 again to finish | |
# Pack the save up in gzip again | |
Pack-Gzip "$TempFile" "$ModifiedSave.gz" | |
# Remove temp file | |
#Remove-Item $TempFile |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment