Quick answer: array_copy is shallow. Nested arrays/structs share references with the original. Write a recursive deep_copy for nested data.

An RPG saves the player’s inventory by copying the array into a save slot. Edits to the live inventory mysteriously appear in the saved snapshot. Shallow copy with shared nested structs.

The Trap

var live = [
    { name: "sword", qty: 1 },
    { name: "potion", qty: 3 }
];

var saved = array_create(array_length(live));
array_copy(saved, 0, live, 0, array_length(live));

live[1].qty = 99;
show_debug_message(saved[1].qty);   // 99 - share!

The struct references are copied, not the structs themselves. Both arrays point to the same structs.

Deep Copy Helper

function deep_copy(value) {
    if (is_array(value)) {
        var n = array_length(value);
        var result = array_create(n);
        for (var i = 0; i < n; i++) result[i] = deep_copy(value[i]);
        return result;
    }
    if (is_struct(value)) {
        var result = {};
        var keys = variable_struct_get_names(value);
        for (var i = 0; i < array_length(keys); i++) {
            variable_struct_set(result, keys[i], deep_copy(variable_struct_get(value, keys[i])));
        }
        return result;
    }
    return value;   // numbers, strings: passed by value
}

Recurses through arrays and structs. Primitives copy by value naturally.

Alternative: JSON Snapshot

var saved = json_parse(json_stringify(live));

Quick and dirty: serialize to JSON and back. Slower than recursive deep copy, but handles all nested data and is one line. Loses methods/refs but for save state usually fine.

Verifying

Make a deep copy. Mutate the original. Check the copy: unchanged. Edge cases: nested arrays inside structs inside arrays — all isolated.

“Shallow copies work for flat data. For nested structures, you need a full traversal.”

For RPG-grade save systems, JSON snapshot is also your serialization format — double duty.