diff --git a/src/components/NaNScreen.vue b/src/components/NaNScreen.vue
index 76a7b75..511d1b6 100644
--- a/src/components/NaNScreen.vue
+++ b/src/components/NaNScreen.vue
@@ -14,9 +14,12 @@
             </div>
             <br />
             <div>
-                <a :href="discordLink" class="nan-modal-discord-link">
+                <a
+                    :href="discordLink || 'https://discord.gg/WzejVAx'"
+                    class="nan-modal-discord-link"
+                >
                     <span class="material-icons nan-modal-discord">discord</span>
-                    {{ discordName }}
+                    {{ discordName || "The Paper Pilot Community" }}
                 </a>
             </div>
             <br />
@@ -50,49 +53,51 @@ import state from "game/state";
 import type { DecimalSource } from "util/bignum";
 import Decimal, { format } from "util/bignum";
 import type { ComponentPublicInstance } from "vue";
-import { computed, ref, toRef } from "vue";
+import { computed, ref, toRef, watch } from "vue";
 import Toggle from "./fields/Toggle.vue";
 import SavesManager from "./SavesManager.vue";
 
 const { discordName, discordLink } = projInfo;
-const autosave = toRef(player, "autosave");
+const autosave = ref(true);
+const isPaused = ref(true);
 const hasNaN = toRef(state, "hasNaN");
 const savesManager = ref<ComponentPublicInstance<typeof SavesManager> | null>(null);
 
-const path = computed(() => state.NaNPath?.join("."));
-const property = computed(() => state.NaNPath?.slice(-1)[0]);
-const previous = computed<DecimalSource | null>(() => {
-    if (state.NaNReceiver && property.value != null) {
-        return state.NaNReceiver[property.value] as DecimalSource;
-    }
-    return null;
-});
-const isPaused = computed({
-    get() {
-        return player.devSpeed === 0;
-    },
-    set(value: boolean) {
-        player.devSpeed = value ? null : 0;
+watch(hasNaN, hasNaN => {
+    if (hasNaN) {
+        autosave.value = player.autosave;
+        isPaused.value = player.devSpeed === 0;
+    } else {
+        player.autosave = autosave.value;
+        player.devSpeed = isPaused.value ? 0 : null;
     }
 });
 
+const path = computed(() => state.NaNPath?.join("."));
+const previous = computed<DecimalSource | null>(() => {
+    if (state.NaNPersistent != null) {
+        return state.NaNPersistent.value;
+    }
+    return null;
+});
+
 function setZero() {
-    if (state.NaNReceiver && property.value != null) {
-        state.NaNReceiver[property.value] = new Decimal(0);
+    if (state.NaNPersistent != null) {
+        state.NaNPersistent.value = new Decimal(0);
         state.hasNaN = false;
     }
 }
 
 function setOne() {
-    if (state.NaNReceiver && property.value != null) {
-        state.NaNReceiver[property.value] = new Decimal(1);
+    if (state.NaNPersistent) {
+        state.NaNPersistent.value = new Decimal(1);
         state.hasNaN = false;
     }
 }
 
 function ignore() {
-    if (state.NaNReceiver && property.value != null) {
-        state.NaNReceiver[property.value] = new Decimal(NaN);
+    if (state.NaNPersistent) {
+        state.NaNPersistent.value = new Decimal(NaN);
         state.hasNaN = false;
     }
 }
diff --git a/src/components/SavesManager.vue b/src/components/SavesManager.vue
index 37b4d5b..91edd40 100644
--- a/src/components/SavesManager.vue
+++ b/src/components/SavesManager.vue
@@ -59,11 +59,10 @@
 <script setup lang="ts">
 import Modal from "components/Modal.vue";
 import projInfo from "data/projInfo.json";
-import type { PlayerData } from "game/player";
+import type { Player } from "game/player";
 import player, { stringifySave } from "game/player";
 import settings from "game/settings";
 import LZString from "lz-string";
-import { ProxyState } from "util/proxies";
 import { getUniqueID, loadSave, newSave, save } from "util/save";
 import type { ComponentPublicInstance } from "vue";
 import { computed, nextTick, ref, shallowReactive, watch } from "vue";
@@ -72,7 +71,7 @@ import Select from "./fields/Select.vue";
 import Text from "./fields/Text.vue";
 import Save from "./Save.vue";
 
-export type LoadablePlayerData = Omit<Partial<PlayerData>, "id"> & { id: string; error?: unknown };
+export type LoadablePlayerData = Omit<Partial<Player>, "id"> & { id: string; error?: unknown };
 
 const isOpen = ref(false);
 const modal = ref<ComponentPublicInstance<typeof Modal> | null>(null);
@@ -195,7 +194,7 @@ const saves = computed(() =>
 function exportSave(id: string) {
     let saveToExport;
     if (player.id === id) {
-        saveToExport = stringifySave(player[ProxyState]);
+        saveToExport = stringifySave(player);
     } else {
         saveToExport = JSON.stringify(saves.value[id]);
     }
@@ -228,7 +227,7 @@ function duplicateSave(id: string) {
     }
 
     const playerData = { ...saves.value[id], id: getUniqueID() };
-    save(playerData as PlayerData);
+    save(playerData as Player);
 
     settings.saves.push(playerData.id);
 }
@@ -272,7 +271,7 @@ function newFromPreset(preset: string) {
     }
     const playerData = JSON.parse(preset);
     playerData.id = getUniqueID();
-    save(playerData as PlayerData);
+    save(playerData as Player);
 
     settings.saves.push(playerData.id);
 
@@ -287,7 +286,7 @@ function editSave(id: string, newName: string) {
             player.name = newName;
             save();
         } else {
-            save(currSave as PlayerData);
+            save(currSave as Player);
             cachedSaves[id] = undefined;
         }
     }
diff --git a/src/data/projEntry.tsx b/src/data/projEntry.tsx
index f930d3a..e4640b6 100644
--- a/src/data/projEntry.tsx
+++ b/src/data/projEntry.tsx
@@ -6,7 +6,7 @@ import { branchedResetPropagation, createTree } from "features/trees/tree";
 import { globalBus } from "game/events";
 import type { BaseLayer, GenericLayer } from "game/layers";
 import { createLayer } from "game/layers";
-import type { PlayerData } from "game/player";
+import type { Player } from "game/player";
 import player from "game/player";
 import type { DecimalSource } from "util/bignum";
 import Decimal, { format, formatTime } from "util/bignum";
@@ -79,7 +79,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
  */
 export const getInitialLayers = (
     /* eslint-disable-next-line @typescript-eslint/no-unused-vars */
-    player: Partial<PlayerData>
+    player: Partial<Player>
 ): Array<GenericLayer> => [main, prestige];
 
 /**
@@ -97,7 +97,7 @@ export const hasWon = computed(() => {
 /* eslint-disable @typescript-eslint/no-unused-vars */
 export function fixOldSave(
     oldVersion: string | undefined,
-    player: Partial<PlayerData>
+    player: Partial<Player>
     // eslint-disable-next-line @typescript-eslint/no-empty-function
 ): void {}
 /* eslint-enable @typescript-eslint/no-unused-vars */
diff --git a/src/game/persistence.ts b/src/game/persistence.ts
index 01e4c96..9ad0634 100644
--- a/src/game/persistence.ts
+++ b/src/game/persistence.ts
@@ -7,6 +7,8 @@ import Decimal from "util/bignum";
 import { ProxyState } from "util/proxies";
 import type { Ref, WritableComputedRef } from "vue";
 import { computed, isReactive, isRef, ref } from "vue";
+import player from "./player";
+import state from "./state";
 
 /**
  * A symbol used in {@link Persistent} objects.
@@ -56,6 +58,7 @@ export type State =
  * A {@link Ref} that has been augmented with properties to allow it to be saved and loaded within the player save data object.
  */
 export type Persistent<T extends State = State> = Ref<T> & {
+    value: T;
     /** A flag that this is a persistent property. Typically a circular reference. */
     [PersistentState]: Ref<T>;
     /** The value the ref should be set to in a fresh save, or when updating an old save to the current version. */
@@ -89,31 +92,65 @@ function getStackTrace() {
     );
 }
 
+function checkNaNAndWrite<T extends State>(persistent: Persistent<T>, value: T) {
+    // Decimal is smart enough to return false on things that aren't supposed to be numbers
+    if (Decimal.isNaN(value as DecimalSource)) {
+        if (!state.hasNaN) {
+            player.autosave = false;
+            state.hasNaN = true;
+            state.NaNPath = persistent[SaveDataPath];
+            state.NaNPersistent = persistent as Persistent<DecimalSource>;
+        }
+        console.error(
+            `Attempted to save NaN value to`,
+            persistent[SaveDataPath]?.join("."),
+            persistent
+        );
+        throw "Attempted to set NaN value. See above for details";
+    }
+    persistent[PersistentState].value = value;
+}
+
 /**
  * Create a persistent ref, which can be saved and loaded.
  * All (non-deleted) persistent refs must be included somewhere within the layer object returned by that layer's options func.
  * @param defaultValue The value the persistent ref should start at on fresh saves or when reset.
  */
 export function persistent<T extends State>(defaultValue: T | Ref<T>): Persistent<T> {
-    const persistent = (
-        isRef(defaultValue) ? defaultValue : (ref<T>(defaultValue) as unknown)
-    ) as Persistent<T>;
+    const persistentState: Ref<T> = isRef(defaultValue)
+        ? defaultValue
+        : (ref<T>(defaultValue) as Ref<T>);
 
-    persistent[PersistentState] = persistent;
-    persistent[DefaultValue] = isRef(defaultValue) ? defaultValue.value : defaultValue;
-    persistent[StackTrace] = getStackTrace();
-    persistent[Deleted] = false;
-    const nonPersistent: Partial<NonPersistent<T>> = computed({
+    if (isRef(defaultValue)) {
+        defaultValue = defaultValue.value;
+    }
+
+    const nonPersistent = computed({
         get() {
-            return persistent.value;
+            return persistentState.value;
         },
         set(value) {
-            persistent.value = value;
+            checkNaNAndWrite(persistent, value);
         }
-    });
-    nonPersistent[DefaultValue] = persistent[DefaultValue];
-    persistent[NonPersistent] = nonPersistent as NonPersistent<T>;
-    persistent[SaveDataPath] = undefined;
+    }) as NonPersistent<T>;
+    nonPersistent[DefaultValue] = defaultValue;
+
+    // We're trying to mock a vue ref, which means the type expects a private [RefSymbol] property that we can't access, but the actual implementation of isRef just checks for `__v_isRef`
+    const persistent = {
+        get value() {
+            return persistentState.value as T;
+        },
+        set value(value: T) {
+            checkNaNAndWrite(persistent, value);
+        },
+        __v_isRef: true,
+        [PersistentState]: persistentState,
+        [DefaultValue]: defaultValue,
+        [StackTrace]: getStackTrace(),
+        [Deleted]: false,
+        [NonPersistent]: nonPersistent,
+        [SaveDataPath]: undefined
+    } as unknown as Persistent<T>;
 
     if (addingLayers.length === 0) {
         console.warn(
@@ -125,7 +162,7 @@ export function persistent<T extends State>(defaultValue: T | Ref<T>): Persisten
         persistentRefs[addingLayers[addingLayers.length - 1]].add(persistent);
     }
 
-    return persistent as Persistent<T>;
+    return persistent;
 }
 
 /**
diff --git a/src/game/player.ts b/src/game/player.ts
index 6271629..5d1142e 100644
--- a/src/game/player.ts
+++ b/src/game/player.ts
@@ -1,13 +1,8 @@
-import { isPlainObject } from "is-plain-object";
-import Decimal from "util/bignum";
-import type { ProxiedWithState } from "util/proxies";
-import { ProxyPath, ProxyState } from "util/proxies";
-import { reactive, unref } from "vue";
 import type { Ref } from "vue";
-import transientState from "./state";
+import { reactive, unref } from "vue";
 
 /** The player save data object. */
-export interface PlayerData {
+export interface Player {
     /** The ID of this save. */
     id: string;
     /** A multiplier for time passing. Set to 0 when the game is paused. */
@@ -36,9 +31,6 @@ export interface PlayerData {
     layers: Record<string, LayerData<unknown>>;
 }
 
-/** The proxied player that is used to track NaN values. */
-export type Player = ProxiedWithState<PlayerData>;
-
 /** A layer's save data. Automatically unwraps refs. */
 export type LayerData<T> = {
     [P in keyof T]?: T[P] extends (infer U)[]
@@ -52,7 +44,7 @@ export type LayerData<T> = {
         : T[P];
 };
 
-const state = reactive<PlayerData>({
+const player = reactive<Player>({
     id: "",
     devSpeed: null,
     name: "",
@@ -68,90 +60,16 @@ const state = reactive<PlayerData>({
     layers: {}
 });
 
+export default window.player = player;
+
 /** Convert a player save data object into a JSON string. Unwraps refs. */
-export function stringifySave(player: PlayerData): string {
+export function stringifySave(player: Player): string {
     return JSON.stringify(player, (key, value) => unref(value));
 }
 
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-const playerHandler: ProxyHandler<Record<PropertyKey, any>> = {
-    // eslint-disable-next-line @typescript-eslint/no-explicit-any
-    get(target: Record<PropertyKey, any>, key: PropertyKey): any {
-        if (key === ProxyState || key === ProxyPath) {
-            return target[key];
-        }
-
-        const value = target[ProxyState][key];
-        if (key !== "value" && (isPlainObject(value) || Array.isArray(value))) {
-            if (value !== target[key]?.[ProxyState]) {
-                const path = [...target[ProxyPath], key];
-                target[key] = new Proxy({ [ProxyState]: value, [ProxyPath]: path }, playerHandler);
-            }
-            return target[key];
-        }
-
-        return value;
-    },
-    set(
-        // eslint-disable-next-line @typescript-eslint/no-explicit-any
-        target: Record<PropertyKey, any>,
-        property: PropertyKey,
-        // eslint-disable-next-line @typescript-eslint/no-explicit-any
-        value: any,
-        receiver: ProxyConstructor
-    ): boolean {
-        if (
-            !transientState.hasNaN &&
-            ((typeof value === "number" && isNaN(value)) ||
-                (value instanceof Decimal &&
-                    (isNaN(value.sign) || isNaN(value.layer) || isNaN(value.mag))))
-        ) {
-            const currentValue = target[ProxyState][property];
-            if (
-                !(
-                    (typeof currentValue === "number" && isNaN(currentValue)) ||
-                    (currentValue instanceof Decimal &&
-                        (isNaN(currentValue.sign) ||
-                            isNaN(currentValue.layer) ||
-                            isNaN(currentValue.mag)))
-                )
-            ) {
-                state.autosave = false;
-                transientState.hasNaN = true;
-                transientState.NaNPath = [...target[ProxyPath], property];
-                transientState.NaNReceiver = receiver as unknown as Record<string, unknown>;
-                console.error(
-                    `Attempted to set NaN value`,
-                    [...target[ProxyPath], property],
-                    target[ProxyState]
-                );
-                throw "Attempted to set NaN value. See above for details";
-            }
-        }
-        target[ProxyState][property] = value;
-        return true;
-    },
-    // eslint-disable-next-line @typescript-eslint/no-explicit-any
-    ownKeys(target: Record<PropertyKey, any>) {
-        return Reflect.ownKeys(target[ProxyState]);
-    },
-    // eslint-disable-next-line @typescript-eslint/no-explicit-any
-    has(target: Record<PropertyKey, any>, key: string) {
-        return Reflect.has(target[ProxyState], key);
-    },
-    getOwnPropertyDescriptor(target, key) {
-        return Object.getOwnPropertyDescriptor(target[ProxyState], key);
-    }
-};
-
 declare global {
     /** Augment the window object so the player can be accessed from the console. */
     interface Window {
         player: Player;
     }
 }
-/** The player save data object. */
-export default window.player = new Proxy(
-    { [ProxyState]: state, [ProxyPath]: ["player"] },
-    playerHandler
-) as Player;
diff --git a/src/game/state.ts b/src/game/state.ts
index bda0b6a..db71c7b 100644
--- a/src/game/state.ts
+++ b/src/game/state.ts
@@ -1,4 +1,6 @@
+import type { DecimalSource } from "util/bignum";
 import { shallowReactive } from "vue";
+import type { Persistent } from "./persistence";
 
 /** An object of global data that is not persistent. */
 export interface Transient {
@@ -8,8 +10,8 @@ export interface Transient {
     hasNaN: boolean;
     /** The location within the player save data object of the NaN value. */
     NaNPath?: string[];
-    /** The parent object of the NaN value. */
-    NaNReceiver?: Record<string, unknown>;
+    /** The ref that was being set to NaN. */
+    NaNPersistent?: Persistent<DecimalSource>;
 }
 
 declare global {
diff --git a/src/util/computed.ts b/src/util/computed.ts
index c940b1a..8a9ad62 100644
--- a/src/util/computed.ts
+++ b/src/util/computed.ts
@@ -1,6 +1,7 @@
+import type { JSXFunction } from "features/feature";
+import { isFunction } from "util/common";
 import type { Ref } from "vue";
 import { computed } from "vue";
-import { isFunction } from "util/common";
 
 export const DoNotCache = Symbol("DoNotCache");
 
@@ -32,21 +33,22 @@ export function processComputable<T, S extends keyof ComputableKeysOf<T>>(
     key: S
 ): asserts obj is T & { [K in S]: ProcessedComputable<UnwrapComputableType<T[S]>> } {
     const computable = obj[key];
-    // eslint-disable-next-line @typescript-eslint/no-explicit-any
-    if (isFunction(computable) && computable.length === 0 && !(computable as any)[DoNotCache]) {
+    if (
+        isFunction(computable) &&
+        computable.length === 0 &&
+        !(computable as unknown as JSXFunction)[DoNotCache]
+    ) {
         // eslint-disable-next-line @typescript-eslint/ban-ts-comment
         // @ts-ignore
         obj[key] = computed(computable.bind(obj));
     } else if (isFunction(computable)) {
         obj[key] = computable.bind(obj) as unknown as T[S];
-        // eslint-disable-next-line @typescript-eslint/no-explicit-any
-        (obj[key] as any)[DoNotCache] = true;
+        (obj[key] as unknown as JSXFunction)[DoNotCache] = true;
     }
 }
 
 export function convertComputable<T>(obj: Computable<T>): ProcessedComputable<T> {
-    // eslint-disable-next-line @typescript-eslint/no-explicit-any
-    if (isFunction(obj) && !(obj as any)[DoNotCache]) {
+    if (isFunction(obj) && !(obj as unknown as JSXFunction)[DoNotCache]) {
         // eslint-disable-next-line @typescript-eslint/ban-ts-comment
         // @ts-ignore
         obj = computed(obj);
diff --git a/src/util/proxies.ts b/src/util/proxies.ts
index 9dad138..174378b 100644
--- a/src/util/proxies.ts
+++ b/src/util/proxies.ts
@@ -1,11 +1,11 @@
+import type { Persistent } from "game/persistence";
 import { NonPersistent } from "game/persistence";
 import Decimal from "util/bignum";
 
 export const ProxyState = Symbol("ProxyState");
 export const ProxyPath = Symbol("ProxyPath");
 
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-export type ProxiedWithState<T> = NonNullable<T> extends Record<PropertyKey, any>
+export type ProxiedWithState<T> = NonNullable<T> extends Record<PropertyKey, unknown>
     ? NonNullable<T> extends Decimal
         ? T
         : {
@@ -16,6 +16,18 @@ export type ProxiedWithState<T> = NonNullable<T> extends Record<PropertyKey, any
           }
     : T;
 
+export type Proxied<T> = NonNullable<T> extends Record<PropertyKey, unknown>
+    ? NonNullable<T> extends Persistent<infer S>
+        ? NonPersistent<S>
+        : NonNullable<T> extends Decimal
+        ? T
+        : {
+              [K in keyof T]: Proxied<T[K]>;
+          } & {
+              [ProxyState]: T;
+          }
+    : T;
+
 // Takes a function that returns an object and pretends to be that object
 // Note that the object is lazily calculated
 export function createLazyProxy<T extends object, S extends T>(
diff --git a/src/util/save.ts b/src/util/save.ts
index e43d34b..2955fd1 100644
--- a/src/util/save.ts
+++ b/src/util/save.ts
@@ -1,13 +1,12 @@
 import projInfo from "data/projInfo.json";
 import { globalBus } from "game/events";
-import type { Player, PlayerData } from "game/player";
+import type { Player } from "game/player";
 import player, { stringifySave } from "game/player";
 import settings, { loadSettings } from "game/settings";
 import LZString from "lz-string";
-import { ProxyState } from "util/proxies";
 import { ref } from "vue";
 
-export function setupInitialStore(player: Partial<PlayerData> = {}): Player {
+export function setupInitialStore(player: Partial<Player> = {}): Player {
     return Object.assign(
         {
             id: `${projInfo.id}-0`,
@@ -27,11 +26,9 @@ export function setupInitialStore(player: Partial<PlayerData> = {}): Player {
     ) as Player;
 }
 
-export function save(playerData?: PlayerData): string {
-    const stringifiedSave = LZString.compressToUTF16(
-        stringifySave(playerData ?? player[ProxyState])
-    );
-    localStorage.setItem((playerData ?? player[ProxyState]).id, stringifiedSave);
+export function save(playerData?: Player): string {
+    const stringifiedSave = LZString.compressToUTF16(stringifySave(playerData ?? player));
+    localStorage.setItem((playerData ?? player).id, stringifiedSave);
     return stringifiedSave;
 }
 
@@ -70,7 +67,7 @@ export async function load(): Promise<void> {
     }
 }
 
-export function newSave(): PlayerData {
+export function newSave(): Player {
     const id = getUniqueID();
     const player = setupInitialStore({ id });
     save(player);
@@ -91,7 +88,7 @@ export function getUniqueID(): string {
 
 export const loadingSave = ref(false);
 
-export async function loadSave(playerObj: Partial<PlayerData>): Promise<void> {
+export async function loadSave(playerObj: Partial<Player>): Promise<void> {
     console.info("Loading save", playerObj);
     loadingSave.value = true;
     const { layers, removeLayer, addLayer } = await import("game/layers");