diff --git a/BondageClub/Assets/Female3DCG/Female3DCG.js b/BondageClub/Assets/Female3DCG/Female3DCG.js
index 9574081ad8..05b953476c 100644
--- a/BondageClub/Assets/Female3DCG/Female3DCG.js
+++ b/BondageClub/Assets/Female3DCG/Female3DCG.js
@@ -5679,8 +5679,8 @@ var AssetFemale3DCG = [
 		Zone: [[10, 0, 90, 200]],
 		Asset: [
 			{ Name: "MetalPadlock", Value: 15, Time: 10, Wear: false, Effect: [], IsLock: true},
-			{ Name: "IntricatePadlock", Value: 50, Time: 30, Wear: false, Effect: [], IsLock: true, PickDifficulty: 7, ExclusiveUnlock: true, AllowType: ["LockPickSeed"]},
-			{ Name: "HighSecurityPadlock", Value: 60, Time: 10, Wear: false, Effect: [], IsLock: true, PickDifficulty: 10, ExclusiveUnlock: true, AllowType: ["LockPickSeed"]},
+			{ Name: "IntricatePadlock", Value: 50, Time: 30, Wear: false, Effect: [], IsLock: true, PickDifficulty: 7, ExclusiveUnlock: true, },
+			{ Name: "HighSecurityPadlock", Value: 60, Time: 10, Wear: false, Effect: [], IsLock: true, PickDifficulty: 10, ExclusiveUnlock: true, },
 			{ Name: "TimerPadlock", Value: 80, Wear: false, Effect: [], IsLock: true, MaxTimer: 300, RemoveTimer: 300 },
 			{ Name: "CombinationPadlock", Value: 100, Random: false, Wear: false, Effect: [], IsLock: true, AllowType: ["CombinationNumber"]},
 			{ Name: "PasswordPadlock", Value: 100, BuyGroup: "PasswordPadlock", Random: false, Wear: false, Effect: [], IsLock: true, AllowType: ["Password", "Hint", "LockSet"]},
diff --git a/BondageClub/Scripts/Struggle.js b/BondageClub/Scripts/Struggle.js
index 70641412a7..2051fa4cc8 100644
--- a/BondageClub/Scripts/Struggle.js
+++ b/BondageClub/Scripts/Struggle.js
@@ -1197,6 +1197,39 @@ function StruggleLockPickGetDifficulty(C, Item) {
 	}
 }
 
+/**
+ * Generate the lock pin data
+ *
+ * @param {object} Lock - the lockpicking data. See StruggleLockPickGetDifficulty.
+ * @param {Character} Character
+ * @param {string} Group
+ * @returns {number[]}
+ */
+function StruggleLockPickGenerate(Lock, Character, Group) {
+	if (!Lock || !Character || !Group)
+		return null;
+
+	// Generate a PRNG for shuffling pins around
+	let seed = String(Character.IsNpc() ? Character.Name : Character.MemberNumber) + Group + Lock.Difficulty + Lock.NumPins;
+	const hash = xmur3(seed);
+	const rand = sfc32(hash(), hash(), hash(), hash());
+
+	let Order = [];
+	for (let P = 0; P < Lock.NumPins; P++) {
+		Order.push(P);
+	}
+
+	// Randomize array in-place using Durstenfeld shuffle algorithm
+	// https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array
+	for (var i = Order.length - 1; i > 0; i--) {
+		var j = Math.floor(rand() * (i + 1));
+		var temp = Order[i];
+		Order[i] = Order[j];
+		Order[j] = temp;
+	}
+	return Order;
+}
+
 /**
  * Starts the dialog progress bar for picking a lock
  * First the challenge level is calculated based on the base lock difficulty, the skill of the rigger and the escapee
@@ -1216,12 +1249,6 @@ function StruggleLockPickProgressStart(C, Item) {
 	if (!Lock) return;
 
 	// Prepares the progress bar and timer
-	StruggleLockPickOrder = [];
-	StruggleLockPickSet = [];
-	StruggleLockPickSetFalse = [];
-	StruggleLockPickOffset = [];
-	StruggleLockPickOffsetTarget = [];
-	StruggleLockPickImpossiblePins = [];
 	StruggleLockPickProgressItem = Item;
 	StruggleLockPickProgressOperation = StruggleLockPickProgressGetOperation(C, Item);
 	StruggleLockPickProgressChallenge = Lock.Difficulty;
@@ -1235,39 +1262,22 @@ function StruggleLockPickProgressStart(C, Item) {
 	StruggleLockPickFailTime = 0;
 	DialogMenuButtonBuild(C);
 
+	// Generate the combination
+	StruggleLockPickOrder = [];
+	StruggleLockPickSet = [];
+	StruggleLockPickSetFalse = [];
+	StruggleLockPickOffset = [];
+	StruggleLockPickOffsetTarget = [];
+	StruggleLockPickImpossiblePins = [];
+
+	StruggleLockPickOrder = StruggleLockPickGenerate(Lock, C, C.FocusGroup.Name);
+
 	for (let P = 0; P < Lock.NumPins; P++) {
-		StruggleLockPickOrder.push(P);
 		StruggleLockPickSet.push(false);
 		StruggleLockPickSetFalse.push(false);
 		StruggleLockPickOffset.push(0);
 		StruggleLockPickOffsetTarget.push(0);
 	}
-	/* Randomize array in-place using Durstenfeld shuffle algorithm */
-	// https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array
-	for (var i = StruggleLockPickOrder.length - 1; i > 0; i--) {
-		var j = Math.floor(Math.random() * (i + 1));
-		var temp = StruggleLockPickOrder[i];
-		StruggleLockPickOrder[i] = StruggleLockPickOrder[j];
-		StruggleLockPickOrder[j] = temp;
-	}
-
-	// Initialize persistent pins
-	if ((Item.Property == null)) Item.Property = {};
-	if (Item.Property != null)
-		if ((Item.Property.LockPickSeed == null) || (typeof Item.Property.LockPickSeed != "string")) {
-			Item.Property.LockPickSeed = CommonConvertArrayToString(StruggleLockPickOrder);
-			StruggleLockPickTotalTries = 0;
-		} else {
-			var conv = CommonConvertStringToArray(Item.Property.LockPickSeed);
-			for (let PP = 0; PP < conv.length; PP++) {
-				if (typeof conv[PP] != "number") {
-					Item.Property.LockPickSeed = CommonConvertArrayToString(StruggleLockPickOrder);
-					conv = StruggleLockPickOrder;
-					break;
-				}
-			}
-			StruggleLockPickOrder = conv;
-		}
 
 	if (Lock.Difficulty > 6 && Lock.Impossible) {
 		// if picking is impossible, then some pins will never set
@@ -1275,5 +1285,4 @@ function StruggleLockPickProgressStart(C, Item) {
 		if (Lock.NumPins >= 6) StruggleLockPickImpossiblePins.push(StruggleLockPickOrder[StruggleLockPickOrder.length-2]);
 		if (Lock.NumPins >= 8) StruggleLockPickImpossiblePins.push(StruggleLockPickOrder[StruggleLockPickOrder.length-3]);
 	}
-
 }
diff --git a/BondageClub/Scripts/Typedef.d.ts b/BondageClub/Scripts/Typedef.d.ts
index 90e21d4f02..514841c7e8 100644
--- a/BondageClub/Scripts/Typedef.d.ts
+++ b/BondageClub/Scripts/Typedef.d.ts
@@ -1072,7 +1072,6 @@ interface ItemPropertiesCustom {
 
 	RemoveTimer?: unknown;
 	Password?: string;
-	LockPickSeed?: string;
 	CombinationNumber?: string;
 	LockMemberNumber?: number | string;
 	MemberNumber?: number;
diff --git a/BondageClub/Scripts/Validation.js b/BondageClub/Scripts/Validation.js
index befcace4a7..9f5e3d6c95 100644
--- a/BondageClub/Scripts/Validation.js
+++ b/BondageClub/Scripts/Validation.js
@@ -8,7 +8,7 @@ const ValidationDefaultPassword = "UNLOCK";
 const ValidationRemoveTimerToleranceMs = 5000;
 const ValidationNonModifiableLockProperties = ["LockedBy", "LockMemberNumber"];
 const ValidationRestrictedLockProperties = [
-	"EnableRandomInput", "RemoveItem", "ShowTimer", "CombinationNumber", "Password", "Hint", "LockSet", "LockPickSeed",
+	"EnableRandomInput", "RemoveItem", "ShowTimer", "CombinationNumber", "Password", "Hint", "LockSet",
 ];
 const ValidationTimerLockProperties = ["MemberNumberList", "RemoveTimer"];
 const ValidationAllLockProperties = ValidationNonModifiableLockProperties
@@ -670,29 +670,6 @@ function ValidationSanitizeLock(C, item) {
 		changed = true;
 	}
 
-	// Sanitize lockpicking seed
-	if (typeof property.LockPickSeed === "string") {
-		const seed = CommonConvertStringToArray(property.LockPickSeed);
-		if (!seed.length) {
-			console.warn("Deleting invalid lockpicking seed: ", property.LockPickSeed);
-			delete property.LockPickSeed;
-			changed = true;
-		} else {
-			// Check that every number from 0 up to the seed length is included in the seed
-			for (let i = 0; i < seed.length; i++) {
-				if (!seed.includes(i)) {
-					console.warn("Deleting invalid lockpicking seed: ", property.LockPickSeed);
-					delete property.LockPickSeed;
-					changed = true;
-					break;
-				}
-			}
-		}
-	} else if (property.LockPickSeed != null) {
-		delete property.LockPickSeed;
-		changed = true;
-	}
-
 	// Sanitize lock password
 	if (typeof property.Password === "string") {
 		if (!ValidationPasswordRegex.test(property.Password)) {