Skip to content

Commit

Permalink
updates
Browse files Browse the repository at this point in the history
fast, better, some issues still exist.
Going back through been a while since I have touched this again.

Updated for new Patch (autosellrarity)
Added a notification on import (with the ability to turn it off)
Updated profile saves to no longer update character saves.
Fixed Vault Key data locations.

As always contact me if you find any issues.
  • Loading branch information
xcier committed Sep 23, 2024
1 parent 50a8a7b commit 79085e9
Show file tree
Hide file tree
Showing 19 changed files with 17,815 additions and 16,825 deletions.
12 changes: 0 additions & 12 deletions .github/FUNDING.yml

This file was deleted.

19 changes: 16 additions & 3 deletions BL3SaveEditor/Helpers/Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,19 @@ public object ConvertBack(object value, Type targetType, object parameter, Cultu
}
}

public class StringToBooleanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return !string.IsNullOrEmpty(value as string);
}

public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}

/// <summary>
/// A WPF value converter which converts a UInt32 amount of seconds to a TimeSpan (and back and forth)
/// </summary>
Expand Down Expand Up @@ -447,9 +460,9 @@ public class KeyToIntegerConverter : IValueConverter {
public static Dictionary<string, uint> stringToHash = new Dictionary<string, uint>() {
{ "GoldenKeys", DataPathTranslations.GoldenKeyHash },
{ "DiamondKeys", DataPathTranslations.DiamondKeyHash },
{ "VaultCard1", DataPathTranslations.VaultCard1Hash },
{ "VaultCard2", DataPathTranslations.VaultCard2Hash },
{ "VaultCard3", DataPathTranslations.VaultCard3Hash }
{ "VaultCard1", 3707609395 },
{ "VaultCard2", 182401352 },
{ "VaultCard3", 3896398502 }
};

public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
Expand Down
122 changes: 65 additions & 57 deletions BL3SaveEditor/MainWindow.xaml

Large diffs are not rendered by default.

360 changes: 278 additions & 82 deletions BL3SaveEditor/MainWindow.xaml.cs

Large diffs are not rendered by default.

Binary file modified BL3SaveEditor/Starters/Zane.sav
Binary file not shown.
4 changes: 2 additions & 2 deletions BL3Tools/BL3Tools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,9 @@ public static bool WriteFileToDisk(string filePath, UE3Save saveGame, bool bBack
return true;
}
}
catch(Exception ex)
catch (Exception)
{
return false;
// Intentionally left empty
}
FileStream fs = new FileStream(filePath, FileMode.Create);
IOWrapper io = new IOWrapper(fs, Endian.Little, 0x0000000);
Expand Down
18 changes: 9 additions & 9 deletions BL3Tools/GameData/DataPathTranslations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,18 @@ public static class DataPathTranslations {
public static readonly string DiamondKeyCurrencyPath = "/Game/Gear/_Shared/_Design/InventoryCategories/InventoryCategory_DiamondKey.InventoryCategory_DiamondKey";
public static readonly string MoneyCurrencyPath = "/Game/Gear/_Shared/_Design/InventoryCategories/InventoryCategory_Money.InventoryCategory_Money";
public static readonly string EridiumCurrencyPath = "/Game/Gear/_Shared/_Design/InventoryCategories/InventoryCategory_Eridium.InventoryCategory_Eridium";
public static readonly string VaultCard1Path = "/Game/Gear/_Shared/_Design/InventoryCategories/InventoryCategory_VaultCard1Key.InventoryCategory_VaultCard1Key";
public static readonly string VaultCard2Path = "/Game/Gear/_Shared/_Design/InventoryCategories/InventoryCategory_VaultCard2Key.InventoryCategory_VaultCard2Key";
public static readonly string VaultCard3Path = "/Game/Gear/_Shared/_Design/InventoryCategories/InventoryCategory_VaultCard3Key.InventoryCategory_VaultCard3Key";
public static readonly string VaultCard1Path = "/Game/Gear/_Shared/_Design/InventoryCategories/InventoryCategory_VaultCard1Key";
public static readonly string VaultCard2Path = "/Game/Gear/_Shared/_Design/InventoryCategories/InventoryCategory_VaultCard2Key";
public static readonly string VaultCard3Path = "/Game/Gear/_Shared/_Design/InventoryCategories/InventoryCategory_VaultCard3Key";


public static uint GoldenKeyHash { get; private set; }
public static uint DiamondKeyHash { get; private set; }
public static uint VaultCard1Hash { get; private set; } = 3707609395;
public static uint VaultCard2Hash { get; private set; } = 182401352;
public static uint VaultCard3Hash { get; private set; } = 3896398502;
public static uint MoneyHash { get; private set; }
public static uint EridiumHash { get; private set; }
public static uint VaultCard1Hash { get; private set; }
public static uint VaultCard2Hash { get; private set; }
public static uint VaultCard3Hash { get; private set; }

private static readonly string embeddedFastTravelDatabasePath = "BL3Tools.GameData.Mappings.fast_travel_to_name.json";

Expand Down Expand Up @@ -82,11 +82,11 @@ public static void Initialize() {

GoldenKeyHash = CRC32.Get(GoldenKeyCurrencyPath);
DiamondKeyHash = CRC32.Get(DiamondKeyCurrencyPath);
MoneyHash = CRC32.Get(MoneyCurrencyPath);
EridiumHash = CRC32.Get(EridiumCurrencyPath);
VaultCard1Hash = CRC32.Get(VaultCard1Path);
VaultCard2Hash = CRC32.Get(VaultCard2Path);
VaultCard3Hash = CRC32.Get(VaultCard3Path);
VaultCard3Hash = CRC32.Get(VaultCard2Path);
MoneyHash = CRC32.Get(MoneyCurrencyPath);
EridiumHash = CRC32.Get(EridiumCurrencyPath);

Console.WriteLine("Initialized CRC32 hashes of customization & currency data");

Expand Down
37 changes: 10 additions & 27 deletions BL3Tools/GameData/Experience.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@
using System.Text;
using System.Threading.Tasks;

namespace BL3Tools.GameData
{
namespace BL3Tools.GameData {

public static class PlayerXP
{
public static class PlayerXP {

// PlayerExperienceFormula={Multiplier: 60.0, Power: 2.799999952316284, Offset: 7.329999923706055}
private const float expMultiplier = 60.0f;
Expand All @@ -21,18 +19,15 @@ public static class PlayerXP

private static Dictionary<int, int> xpLevelTable = new Dictionary<int, int>();

private static int ComputeEXPLevel(int level)
{
private static int ComputeEXPLevel(int level) {
return (int)Math.Floor((Math.Pow(level, expPower) + expOffset) * expMultiplier);
}

static PlayerXP()
{
static PlayerXP() {
_XPReduction = ComputeEXPLevel(_XPMinimumLevel);

// Add to the dictionary
for (int lvl = 1; lvl <= _XPMaximumLevel; lvl++)
{
for (int lvl = 1; lvl <= _XPMaximumLevel; lvl++) {
xpLevelTable.Add(lvl, GetPointsForXPLevel(lvl));
}

Expand All @@ -43,29 +38,18 @@ static PlayerXP()
/// </summary>
/// <param name="lvl">EXP Level</param>
/// <returns>The amount of EXP points for the associated amount of points</returns>
public static int GetPointsForXPLevel(int lvl)
{
public static int GetPointsForXPLevel(int lvl) {
if (lvl <= _XPMinimumLevel) return 0;

int expPoints = ComputeEXPLevel(lvl) - _XPReduction;

// Check if the level is the maximum level
if (lvl == _XPMaximumLevel)
{
// Add 1 to the experience points
expPoints += 1;
}

return expPoints;
return ComputeEXPLevel(lvl) - _XPReduction;
}

/// <summary>
/// Gets the respective level for a given amount of XP points
/// </summary>
/// <param name="points">Amount of XP Points</param>
/// <returns>The level associated with the points</returns>
public static int GetLevelForPoints(int points)
{
public static int GetLevelForPoints(int points) {
if (points < 0) return _XPMinimumLevel;
if (points >= xpLevelTable.Last().Value) return _XPMaximumLevel;

Expand All @@ -74,9 +58,8 @@ public static int GetLevelForPoints(int points)
}
}

public static class MayhemLevel
{
public static class MayhemLevel {
public static readonly int MinimumLevel = 0;
public static readonly int MaximumLevel = 10;
}
}
}
26 changes: 11 additions & 15 deletions BL3Tools/GameData/Items/Borderlands3Serial.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,19 +164,17 @@ public static Borderlands3Serial DecryptSerial(string serial) {
/// </summary>
/// <param name="serial">A byte array of the given serial</param>
/// <returns>An object representing the passed in <paramref name="serial"/></returns>
public static Borderlands3Serial DecryptSerial(byte[] serial)
{
public static Borderlands3Serial DecryptSerial(byte[] serial) {
byte serialVersion = serial[0];

// Some simple checks for version numbers and such
if (serialVersion != 3 && serialVersion != 4)
{
if (serialVersion != 3 && serialVersion != 4) {
throw new BL3Tools.BL3Exceptions.SerialParseException(Convert.ToBase64String(serial), serialVersion);
}

IOWrapper serialIO = new IOWrapper(serial, Endian.Big, 1);
uint originalSeed = serialIO.ReadUInt32();

// Copy the decrypted serial into a new buffer
int decryptedSize = (int)(serial.Length - serialIO.Position);
byte[] decrypted = new byte[decryptedSize];
Expand All @@ -186,7 +184,7 @@ public static Borderlands3Serial DecryptSerial(byte[] serial)
BogoDecrypt(originalSeed, decrypted, 0, decryptedSize);

IOWrapper decryptedSerialIO = new IOWrapper(decrypted, Endian.Big, 0);

// Read in the original checksum
ushort originalChecksum = decryptedSerialIO.ReadUInt16();

Expand All @@ -195,10 +193,10 @@ public static Borderlands3Serial DecryptSerial(byte[] serial)
byte[] remaining = decryptedSerialIO.ReadToEnd().Reverse().ToArray();

byte[] checksumBuffer = Helpers.ConcatArrays(new byte[] {
serial[0], // Serial Version
serial[1], serial[2], serial[3], serial[4], // Seed
0xFF, 0xFF // When calculating, the preset checksum is 0xFF
}, remaining); // Append the remaining (unencrypted) data
serial[0], // Serial Version
serial[1], serial[2], serial[3], serial[4], // Seed
0xFF, 0xFF // When calculating, the preset checksum is 0xFF
}, remaining); // Append the remaining (unencrypted) data

decryptedSerialIO.JumpBack();

Expand All @@ -207,24 +205,22 @@ public static Borderlands3Serial DecryptSerial(byte[] serial)
var hash = CRC.GetHashUInt32;
var computedChecksum = (ushort)(((hash) >> 16) ^ ((hash & 0xFFFF) >> 0));

if (computedChecksum != originalChecksum)
if(computedChecksum != originalChecksum)
throw new BL3Tools.BL3Exceptions.SerialParseException(Convert.ToBase64String(serial), serialVersion, originalChecksum, computedChecksum);


BitReader reader = new BitReader(decryptedSerialIO);

int randomData = reader.ReadInt32(8);

// It might not explicitly matter that if this data isn't 128, so for now it stays as a Debug assertion.
Debug.Assert(randomData == 128);


int SerialDatabaseVersion = reader.ReadInt32(7);
if (SerialDatabaseVersion > InventorySerialDatabase.MaximumVersion)
throw new BL3Tools.BL3Exceptions.SerialParseException(Convert.ToBase64String(serial), serialVersion, SerialDatabaseVersion);

if (reader.BitsRemaining() < InventorySerialDatabase.GetBitsToEat("InventoryBalanceData", SerialDatabaseVersion))
{
throw new BL3Tools.BL3Exceptions.SerialParseException($"Not enough bits remaining to read balance. BitsRemaining: {reader.BitsRemaining()}, Required: {InventorySerialDatabase.GetBitsToEat("InventoryBalanceData", SerialDatabaseVersion)}");
}
string balance = EatBitsForCategory(reader, "InventoryBalanceData", SerialDatabaseVersion);
string inventoryData = EatBitsForCategory(reader, "InventoryData", SerialDatabaseVersion);
string manufacturer = EatBitsForCategory(reader, "ManufacturerData", SerialDatabaseVersion);
Expand Down
76 changes: 33 additions & 43 deletions BL3Tools/GameData/Items/InventoryKeyDB.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,67 +40,57 @@ static InventoryKeyDB() {
/// </summary>
/// <param name="JSONString">A JSON string representing the InventorySerialDB</param>
/// <returns>Whether or not the loading succeeded</returns>
public static bool LoadInventoryKeyDatabase(string JSONString) {
var lastDB = KeyDatabase;
try {
public static bool LoadInventoryKeyDatabase(string JSONString)
{
try
{
JObject db = JObject.FromObject(JsonConvert.DeserializeObject(JSONString));
KeyDictionary = db.ToObject<Dictionary<string, string>>();
KeyDatabase = db;

var invKeys = KeyDictionary.Values.Distinct();
// Pre-filter keys to avoid redundant `Where` calls
var invKeys = KeyDictionary.Values.Distinct().ToList();

ItemTypeToKey = new Dictionary<string, List<string>>() {
{ "Grenades", invKeys.Where(x => x.Contains("_GrenadeMod_")).ToList() },
{ "Shields", invKeys.Where(x => x.Contains("_Shield_")).ToList() },
{ "Class Mods", invKeys.Where(x => x.Contains("_ClassMod_")).ToList() },
{ "Artifacts", invKeys.Where(x => x.Contains("_Artifact_")).ToList() },
{ "Assault Rifles", invKeys.Where(x => x.Contains("_AR_")).ToList() },
{ "Pistols", invKeys.Where(x => x.Contains("_Pistol_") || x.Contains("_PS_")).ToList() },
{ "SMGs", invKeys.Where(x => x.Contains("_SM_") || x.Contains("_SMG")).ToList() },
{ "Heavy Weapons", invKeys.Where(x => x.Contains("_HW_")).ToList() },
{ "Shotguns", invKeys.Where(x => x.Contains("_SG_") || x.Contains("_Shotgun_")).ToList() },
{ "Sniper Rifles", invKeys.Where(x => x.Contains("_SR_")).ToList() },
{ "Eridian Fabricator", invKeys.Where(x => x.Contains("EridianFabricator")).ToList() },
{ "Customizations", invKeys.Where(x => x.Contains("Customization")).ToList() }
};
{ "Grenades", invKeys.Where(x => x.Contains("_GrenadeMod_")).ToList() },
{ "Shields", invKeys.Where(x => x.Contains("_Shield_")).ToList() },
{ "Class Mods", invKeys.Where(x => x.Contains("_ClassMod_")).ToList() },
{ "Artifacts", invKeys.Where(x => x.Contains("_Artifact_")).ToList() },
{ "Assault Rifles", invKeys.Where(x => x.Contains("_AR_")).ToList() },
{ "Pistols", invKeys.Where(x => x.Contains("_Pistol_") || x.Contains("_PS_")).ToList() },
{ "SMGs", invKeys.Where(x => x.Contains("_SM_") || x.Contains("_SMG")).ToList() },
{ "Heavy Weapons", invKeys.Where(x => x.Contains("_HW_")).ToList() },
{ "Shotguns", invKeys.Where(x => x.Contains("_SG_") || x.Contains("_Shotgun_")).ToList() },
{ "Sniper Rifles", invKeys.Where(x => x.Contains("_SR_")).ToList() },
{ "Eridian Fabricator", invKeys.Where(x => x.Contains("EridianFabricator")).ToList() },
{ "Customizations", invKeys.Where(x => x.Contains("Customization")).ToList() }
};

return true;
}
catch (Exception) {
KeyDatabase = lastDB;
catch (Exception)
{
// On failure, retain the previous database state
return false;
}

return false;
}


public static string GetKeyForBalance(string balance)
{
// Check if balance is null
if (balance == null)
{
// Log or handle the null balance scenario
return null;
}
// Cache the result of Split operation
var balanceSuffix = balance.Split('/').LastOrDefault();
if (!balance.Contains("."))
balance = $"{balance}.{balanceSuffix}";

// Check if the name exists by default
if (!balance.Contains(".")) balance = $"{balance}.{balance.Split('/').LastOrDefault()}";
if (KeyDictionary.TryGetValue(balance, out var key))
return key;

// Ensure KeyDictionary is initialized
if (KeyDictionary != null)
{
// Check if the balance key exists in the dictionary
if (KeyDictionary.ContainsKey(balance))
return KeyDictionary[balance];
else if (KeyDictionary.ContainsKey(balance.ToLower()))
return KeyDictionary[balance.ToLower()];
}
else
{
// Log or handle the uninitialized KeyDictionary scenario
}
// Avoid lowercasing the string twice
var lowerBalance = balance.ToLower();
if (KeyDictionary.TryGetValue(lowerBalance, out key))
return key;

// If balance key is not found, return null
return null;
}
}
Expand Down
Loading

0 comments on commit 79085e9

Please sign in to comment.