docs(reference): import Dune: Awakening server-manager references
All checks were successful
CI / backend-types (push) Successful in 10s
CI / frontend-build (push) Successful in 15s
CI / agent-tests (push) Successful in 39s
CI / integration (push) Successful in 22s

Phase 2 references for the host-agent Dune adapter, moved out of volatile /tmp
into docs/reference-repos/ (per Commander). Three upstream projects, .git +
node_modules + compiled binaries stripped (16MB source). Nested AI-instruction
files (.claude/, CLAUDE.md) removed so they don't pollute Corrosion sessions.

- icehunter/    dune-admin (Go+React) — 4 control planes; SETUP_DOCKER.md is the
                closest analog to our agent's Dune docker control plane (compose
                lifecycle, docker logs, RabbitMQ-via-exec, dune Postgres schema)
- adainrivers/  Rust/Tauri desktop — SSH+k8s BattleGroup control, maintenance
                daemon, in-game admin console (Rust idiom reference)
- the4rchangel/ Node web UI replacing battlegroup.bat — matches the Commander's
                Hyper-V self-host path + game-config schema

See docs/reference-repos/README.md for the full index + how we use each.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Vantz Stockwell
2026-06-11 21:08:05 -04:00
parent 0715492ddf
commit 651a35d4be
1334 changed files with 238971 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
-- _character_transfer_ensure_player_is_owner_of_vbt_vehicle(in_vehicle_id bigint[]) -> void
-- oid: 58100 kind: FUNCTION category: vehicle
CREATE OR REPLACE FUNCTION dune._character_transfer_ensure_player_is_owner_of_vbt_vehicle(in_vehicle_id bigint[])
RETURNS void
LANGUAGE sql
AS $function$
update permission_actor_rank set "rank" = 1 where permission_actor_id = any(in_vehicle_id);
$function$

View File

@@ -0,0 +1,49 @@
-- _character_transfer_store_in_world_owned_vehicles_into_recovery(in_player_id bigint) -> void
-- oid: 58109 kind: FUNCTION category: vehicle
CREATE OR REPLACE FUNCTION dune._character_transfer_store_in_world_owned_vehicles_into_recovery(in_player_id bigint)
RETURNS void
LANGUAGE plpgsql
AS $function$
DECLARE
to_store RECORD;
BEGIN
-- remove any vehicles in 'Travel' state, so that they get re-added as recovered vehicles
DELETE FROM actor_state ast
WHERE ast.state = 'Travel'
AND ast.actor_id IN (
SELECT v.id
FROM actors a
INNER JOIN vehicles v ON a.id = v.id
INNER JOIN permission_actor p ON a.id = p.actor_id
INNER JOIN permission_actor_rank r ON p.actor_id = r.permission_actor_id
WHERE r.player_id = in_player_id
AND r.rank = 1::smallint
);
FOR to_store IN
SELECT v.id AS vehicle_id
FROM actors a
INNER JOIN vehicles v ON a.id = v.id
INNER JOIN permission_actor p ON a.id = p.actor_id
INNER JOIN permission_actor_rank r ON p.actor_id = r.permission_actor_id
WHERE r.player_id = in_player_id
AND r.rank = 1::smallint
AND NOT EXISTS
(
SELECT 1 FROM actor_state
WHERE actor_state.actor_id = v.id
AND actor_state.state IS DISTINCT FROM 'Default'
)
LOOP
-- note: storing hardcoded chassis durability because its not available from pure database :(
-- this will only be shown incorrectly in UI though, the spawned vehicle will get the correct value
PERFORM store_recovered_vehicle(to_store.vehicle_id, 1.0, 'None', true);
-- we delete the permissions for this vehicle so that they don't get exported and cause duplicated key failures
-- when the player tries to recover their vehicle on the target battlegroup
-- note: the server will destroy the vehicle as soon as it gets the pg_notify emitted from the store_recovered_vehicle call above, so this would happen regardless
DELETE FROM permission_actor pa WHERE pa.actor_id = to_store.vehicle_id;
END LOOP;
END
$function$

View File

@@ -0,0 +1,17 @@
-- get_player_owned_vehicles_data(in_player_id bigint, in_account_id bigint) -> TABLE(out_actor_id bigint, out_name text, out_class text, out_map text, out_partition_id bigint, out_dimension integer, out_transform dune.transform, out_actor_state text)
-- oid: 58342 kind: FUNCTION category: vehicle
CREATE OR REPLACE FUNCTION dune.get_player_owned_vehicles_data(in_player_id bigint, in_account_id bigint)
RETURNS TABLE(out_actor_id bigint, out_name text, out_class text, out_map text, out_partition_id bigint, out_dimension integer, out_transform dune.transform, out_actor_state text)
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN QUERY WITH owned_actors AS(
SELECT (entry).actor_id, (entry).actor_name FROM get_permission_for_player_actors(in_player_id, 1::smallint) -- 1:owner
WHERE (entry).actor_type = 2 -- 2:vehicles
UNION SELECT vehicle_id, vehicle_name FROM recovered_vehicles -- note: recovered vehicles are removed from permission actors
WHERE account_id = in_account_id
) SELECT owned_actors.actor_id, actor_name, class, map, partition_id, dimension_index, transform, (actor_state).state::text
FROM owned_actors LEFT JOIN actors ON actors.id = owned_actors.actor_id LEFT JOIN actor_state ON actor_state.actor_id = owned_actors.actor_id;
END
$function$

View File

@@ -0,0 +1,18 @@
-- get_unbacked_up_vehicle_ids_for_account(in_account_id bigint) -> TABLE(vehicle_id bigint)
-- oid: 58361 kind: FUNCTION category: vehicle
CREATE OR REPLACE FUNCTION dune.get_unbacked_up_vehicle_ids_for_account(in_account_id bigint)
RETURNS TABLE(vehicle_id bigint)
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN QUERY
SELECT v.id
FROM vehicles v
JOIN permission_actor_rank par ON v.id = par.permission_actor_id
JOIN player_state ps ON par.player_id = ps.player_controller_id
left join backup_vehicles bv ON v.id = bv.vehicle_id
WHERE ps.account_id = in_account_id
AND bv.vehicle_id IS NULL;
END
$function$

View File

@@ -0,0 +1,18 @@
-- get_vehicle_id(in_actor_id bigint, in_class text) -> bigint
-- oid: 58364 kind: FUNCTION category: vehicle
CREATE OR REPLACE FUNCTION dune.get_vehicle_id(in_actor_id bigint, in_class text)
RETURNS bigint
LANGUAGE plpgsql
AS $function$
DECLARE
vehicle_id BIGINT;
BEGIN
SELECT INTO vehicle_id id FROM vehicles WHERE "id" = in_actor_id;
IF vehicle_id IS NULL THEN
SELECT assign_actor_id(in_class) id INTO vehicle_id;
INSERT INTO vehicles("id") VALUES(vehicle_id);
END IF;
RETURN vehicle_id;
END
$function$

View File

@@ -0,0 +1,17 @@
-- get_vehicle_module_inventory_id(in_vehicle_module_id bigint, in_vehicle_module_inventory_type integer) -> bigint
-- oid: 58365 kind: FUNCTION category: vehicle
CREATE OR REPLACE FUNCTION dune.get_vehicle_module_inventory_id(in_vehicle_module_id bigint, in_vehicle_module_inventory_type integer)
RETURNS bigint
LANGUAGE plpgsql
AS $function$
DECLARE
inv_id BIGINT;
BEGIN
SELECT INTO inv_id inventory_id FROM vehicle_module_inventories vi JOIN inventories i ON (vi.inventory_id = i.id) WHERE i.vehicle_module_id = in_vehicle_module_id AND vi.vehicle_module_inventory_type = in_vehicle_module_inventory_type;
IF inv_id IS NULL THEN
INSERT INTO inventories("id", "vehicle_module_id") VALUES(DEFAULT, in_vehicle_module_id) RETURNING id INTO inv_id;
INSERT INTO vehicle_module_inventories("inventory_id", "vehicle_module_inventory_type") VALUES(inv_id, in_vehicle_module_inventory_type);
END IF;
RETURN inv_id;
END $function$

View File

@@ -0,0 +1,16 @@
-- load_backup_vehicle(in_account_id bigint) -> TABLE(out_id bigint, out_class text, out_customization_id text)
-- oid: 58439 kind: FUNCTION category: vehicle
CREATE OR REPLACE FUNCTION dune.load_backup_vehicle(in_account_id bigint)
RETURNS TABLE(out_id bigint, out_class text, out_customization_id text)
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN QUERY
SELECT a.id, a.class, bv.customization_id
FROM actors a
JOIN backup_vehicles bv on a.id = bv.vehicle_id
WHERE bv.account_id = in_account_id
LIMIT 1;
END
$function$

View File

@@ -0,0 +1,18 @@
-- load_recovered_vehicles(in_account_id bigint, in_restore_time_limit integer) -> TABLE(out_vehicle_id bigint, out_class text, out_name text, out_time_stored timestamp without time zone, out_chassis_durability real, out_customization_id text, out_migrated boolean)
-- oid: 58461 kind: FUNCTION category: vehicle
CREATE OR REPLACE FUNCTION dune.load_recovered_vehicles(in_account_id bigint, in_restore_time_limit integer)
RETURNS TABLE(out_vehicle_id bigint, out_class text, out_name text, out_time_stored timestamp without time zone, out_chassis_durability real, out_customization_id text, out_migrated boolean)
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN QUERY
SELECT vehicle_id, class, vehicle_name, time_stored AT TIME ZONE 'UTC', chassis_durability, customization_id, migrated
FROM actors
JOIN recovered_vehicles on id = vehicle_id
WHERE account_id = in_account_id
AND (migrated = TRUE OR time_stored > NOW() - in_restore_time_limit * INTERVAL '1 second')
AND EXISTS (SELECT 1 FROM actor_state WHERE actor_state.actor_id = id AND actor_state.state = 'VehicleRecovery')
ORDER BY time_stored DESC;
END
$function$

View File

@@ -0,0 +1,11 @@
-- load_vehicle_modules(in_vehicle_id bigint) -> TABLE(module_id bigint, template_id text, stats jsonb)
-- oid: 58467 kind: FUNCTION category: vehicle
CREATE OR REPLACE FUNCTION dune.load_vehicle_modules(in_vehicle_id bigint)
RETURNS TABLE(module_id bigint, template_id text, stats jsonb)
LANGUAGE plpgsql
AS $function$
begin
return query SELECT vm.id, vm.template_id, vm.stats FROM vehicle_modules vm WHERE vehicle_id = in_vehicle_id ORDER BY id;
end
$function$

View File

@@ -0,0 +1,50 @@
-- restore_backup_vehicle(in_account_id bigint, in_server_info dune.serverinfo, in_transform dune.transform) -> bigint
-- oid: 58534 kind: FUNCTION category: vehicle
CREATE OR REPLACE FUNCTION dune.restore_backup_vehicle(in_account_id bigint, in_server_info dune.serverinfo, in_transform dune.transform)
RETURNS bigint
LANGUAGE plpgsql
AS $function$
DECLARE
found_vehicle_id BIGINT;
BEGIN
-- Retrieve a backup vehicle for the provided account.
SELECT vehicle_id INTO found_vehicle_id
FROM backup_vehicles
WHERE account_id = in_account_id
LIMIT 1; -- In case more than one is stored.
IF NOT FOUND THEN
RAISE EXCEPTION 'No backup vehicle found for account_id: %', in_account_id;
END IF;
-- Only restore vehicle if the actor state is vehicle backup
PERFORM 1 FROM actor_state WHERE actor_id = found_vehicle_id AND state = 'VehicleBackup';
IF NOT FOUND THEN
RAISE EXCEPTION 'Trying to restore vehicle % that does not belong to vehicle backup feature.', found_vehicle_id;
END IF;
-- Update the actors record to restore the vehicle.
UPDATE actors
SET map = in_server_info.map,
partition_id = in_server_info.partition_id,
dimension_index = in_server_info.dimension_index,
transform = in_transform
WHERE id = found_vehicle_id;
IF NOT FOUND THEN
RAISE WARNING 'No actor record found with id % during restore.', found_vehicle_id;
END IF;
-- Remove the restored vehicle from backup_vehicles.
DELETE FROM backup_vehicles WHERE vehicle_id = found_vehicle_id;
RAISE INFO 'Deleted backup record for vehicle %.', found_vehicle_id;
-- There is no need to keep the actor state in the table anymore since the vehicle backup was successful data wise
DELETE FROM actor_state WHERE actor_id = found_vehicle_id;
RAISE INFO 'Deleted actor state for vehicle %.', found_vehicle_id;
PERFORM verify_item_dup_backup_tool(in_account_id, found_vehicle_id, 'item_dup_on_restore_vbt');
RETURN found_vehicle_id;
END;
$function$

View File

@@ -0,0 +1,66 @@
-- restore_recovered_vehicle(in_account_id bigint, in_vehicle_id bigint, in_server_info dune.serverinfo, in_transform dune.transform, in_restore_time_limit integer) -> void
-- oid: 58535 kind: FUNCTION category: vehicle
CREATE OR REPLACE FUNCTION dune.restore_recovered_vehicle(in_account_id bigint, in_vehicle_id bigint, in_server_info dune.serverinfo, in_transform dune.transform, in_restore_time_limit integer)
RETURNS void
LANGUAGE plpgsql
AS $function$
DECLARE
found_vehicle_id BIGINT;
found_vehicle_name TEXT;
found_player_id BIGINT;
BEGIN
-- Retrieve a recovered vehicle for the provided account.
SELECT vehicle_id, vehicle_name INTO found_vehicle_id, found_vehicle_name
FROM recovered_vehicles
WHERE account_id = in_account_id AND vehicle_id = in_vehicle_id
-- 60s leeway in favor of player in case they try to restore last second
AND (migrated = TRUE OR time_stored > NOW() - (in_restore_time_limit + 60) * INTERVAL '1 second')
LIMIT 1; -- In case more than one is stored.
IF NOT FOUND THEN
RAISE EXCEPTION 'No recovered vehicle found for account_id: % and vehicle_id: %', in_account_id, in_vehicle_id;
END IF;
-- Only restore vehicle if the actor state is VehicleRecovery
PERFORM 1 FROM actor_state WHERE actor_id = found_vehicle_id AND state = 'VehicleRecovery';
IF NOT FOUND THEN
RAISE EXCEPTION 'Trying to restore vehicle % that does not belong to vehicle recovery feature.', found_vehicle_id;
END IF;
-- Update the actors record to restore the vehicle.
UPDATE actors
SET map = in_server_info.map,
partition_id = in_server_info.partition_id,
dimension_index = in_server_info.dimension_index,
transform = in_transform
WHERE id = found_vehicle_id;
IF NOT FOUND THEN
RAISE WARNING 'No actor record found with id % during restore.', found_vehicle_id;
END IF;
-- permissions use the player controllers id, so we need to get that from the account id
SELECT player_controller_id INTO found_player_id FROM player_state WHERE account_id = in_account_id LIMIT 1;
IF NOT FOUND THEN
RAISE EXCEPTION 'No player_controller_id found for account: %', in_account_id;
END IF;
-- restore default permissions
INSERT INTO permission_actor("actor_id", "actor_name", "actor_type", "access_level", "is_child")
VALUES(found_vehicle_id, found_vehicle_name, 2, 3, false);
INSERT INTO permission_actor_rank("permission_actor_id", "player_id", "rank")
VALUES(found_vehicle_id, found_player_id, 1);
-- Remove the restored vehicle from recovered_vehicles.
DELETE FROM recovered_vehicles WHERE vehicle_id = found_vehicle_id;
RAISE INFO 'Deleted recovery record for vehicle %.', found_vehicle_id;
-- There is no need to keep the actor state in the table anymore since the vehicle recovery was successful data wise
DELETE FROM actor_state WHERE actor_id = found_vehicle_id;
RAISE INFO 'Deleted actor state for vehicle %.', found_vehicle_id;
--PERFORM verify_item_dup_backup_tool(in_account_id, found_vehicle_id, 'item_dup_on_restore_vbt');
END;
$function$

View File

@@ -0,0 +1,37 @@
-- save_vehicle_modules(in_add_list dune.vehiclemodule[], in_delete_list bigint[], in_stat_update dune.itemstatupdate[]) -> SETOF bigint
-- oid: 58574 kind: FUNCTION category: vehicle
CREATE OR REPLACE FUNCTION dune.save_vehicle_modules(in_add_list dune.vehiclemodule[], in_delete_list bigint[], in_stat_update dune.itemstatupdate[])
RETURNS SETOF bigint
LANGUAGE plpgsql
AS $function$
DECLARE
module VEHICLEMODULE;
stat ItemStatUpdate;
new_module_id BIGINT;
currentstat RECORD;
BEGIN
--RAISE NOTICE 'Add vehicle modules';
-- add vehicle modules
FOREACH module IN ARRAY in_add_list LOOP
INSERT INTO vehicle_modules(
"vehicle_id", "template_id", "stats"
) VALUES(
(module).vehicle_id, (module).template_id, (module).stats
) RETURNING id INTO new_module_id;
RETURN NEXT new_module_id;
END LOOP;
--RAISE NOTICE 'Delete vehicle modules';
-- delete modules
DELETE FROM vehicle_modules WHERE id = ANY(in_delete_list);
--RAISE NOTICE 'Add vehicle module stats';
-- add vehicle module stats
FOREACH stat IN ARRAY in_stat_update LOOP
UPDATE vehicle_modules SET "stats" = vehicle_modules.stats || (stat).value WHERE "id" = (stat).item_id;
END LOOP;
RETURN;
END
$function$

View File

@@ -0,0 +1,42 @@
-- store_backup_vehicle(in_vehicle_id bigint, in_account_id bigint, in_customization_id text) -> void
-- oid: 58598 kind: FUNCTION category: vehicle
CREATE OR REPLACE FUNCTION dune.store_backup_vehicle(in_vehicle_id bigint, in_account_id bigint, in_customization_id text)
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
-- Lock the backup_vehicles table exclusively to prevent race conditions.
LOCK TABLE backup_vehicles IN EXCLUSIVE MODE;
-- Check if the vehicle already belongs to an actor state
PERFORM 1 FROM actor_state WHERE actor_id = in_vehicle_id;
IF FOUND THEN
RAISE EXCEPTION 'Trying to backup vehicle % that already has an actor state.', in_vehicle_id;
END IF;
-- Check if the vehicle is already in backup_vehicles.
PERFORM 1 FROM backup_vehicles WHERE vehicle_id = in_vehicle_id;
IF FOUND THEN
RAISE EXCEPTION 'Vehicle % is already stored as a backup.', in_vehicle_id;
END IF;
-- Check if the vehicle exists in the actors table.
PERFORM 1 FROM actors WHERE id = in_vehicle_id;
IF NOT FOUND THEN
RAISE EXCEPTION 'Vehicle % does not exist in actors.', in_vehicle_id;
END IF;
-- Insert the vehicle into backup_vehicles.
INSERT INTO backup_vehicles (account_id, vehicle_id, customization_id)
VALUES (in_account_id, in_vehicle_id, in_customization_id);
RAISE INFO 'Inserted vehicle % into backup_vehicles for account %.', in_vehicle_id, in_account_id;
-- Mark the actor as belonging to the vehicle backup tool
INSERT INTO actor_state("actor_id", "state") VALUES(in_vehicle_id, 'VehicleBackup');
RAISE INFO 'Inserted vehicle % into actor_state with VehicleBackup state', in_vehicle_id;
PERFORM verify_item_dup_backup_tool(in_account_id, in_vehicle_id, 'item_dup_on_store_vbt');
END;
$function$

View File

@@ -0,0 +1,63 @@
-- store_recovered_vehicle(in_vehicle_id bigint, in_chassis_durability real, in_customization_id text, in_is_migration boolean) -> void
-- oid: 58599 kind: FUNCTION category: vehicle
CREATE OR REPLACE FUNCTION dune.store_recovered_vehicle(in_vehicle_id bigint, in_chassis_durability real, in_customization_id text, in_is_migration boolean DEFAULT false)
RETURNS void
LANGUAGE plpgsql
AS $function$
DECLARE
owner_id BIGINT;
player_id BIGINT;
vehicle_class TEXT;
vehicle_name TEXT;
BEGIN
-- Lock the recovered_vehicles table exclusively to prevent race conditions.
LOCK TABLE recovered_vehicles IN EXCLUSIVE MODE;
-- Check if the vehicle already belongs to an actor state
PERFORM 1 FROM actor_state WHERE actor_id = in_vehicle_id;
IF FOUND THEN
RAISE EXCEPTION 'Trying to store recovered vehicle % that already has an actor state.', in_vehicle_id;
END IF;
-- Check if the vehicle is already in recovered_vehicles.
PERFORM 1 FROM recovered_vehicles WHERE vehicle_id = in_vehicle_id;
IF FOUND THEN
RAISE EXCEPTION 'Vehicle % is already recovered.', in_vehicle_id;
END IF;
-- Check if the vehicle exists in the actors table.
SELECT class INTO vehicle_class
FROM actors
WHERE id = in_vehicle_id
LIMIT 1;
IF NOT FOUND THEN
RAISE EXCEPTION 'Vehicle % does not exist in actors.', in_vehicle_id;
END IF;
-- get the vehicles owner account id
SELECT a.owner_account_id, r.player_id, p.actor_name INTO owner_id, player_id, vehicle_name
FROM actors a
INNER JOIN permission_actor_rank r ON r.player_id = a.id
INNER JOIN permission_actor p ON p.actor_id = r.permission_actor_id
WHERE r.permission_actor_id = in_vehicle_id
AND r.rank = 1::smallint
LIMIT 1;
IF NOT FOUND THEN
RAISE EXCEPTION 'No account_id found for vehicle: %', in_vehicle_id;
END IF;
-- Insert the vehicle into recovered_vehicles.
INSERT INTO recovered_vehicles(account_id, vehicle_id, chassis_durability, vehicle_name, customization_id, migrated)
VALUES (owner_id, in_vehicle_id, in_chassis_durability, vehicle_name, in_customization_id, in_is_migration);
RAISE INFO 'Inserted vehicle % into recovered_vehicles for account %.', in_vehicle_id, owner_id;
-- Mark the actor as belonging to the vehicle recovery tool
INSERT INTO actor_state("actor_id", "state") VALUES(in_vehicle_id, 'VehicleRecovery');
RAISE INFO 'Inserted vehicle % into actor_state with VehicleRecovery state', in_vehicle_id;
PERFORM pg_notify('vehicle_recovery_notify_channel', FORMAT('stored#{"PlayerId":%s, "VehicleId":%s, "VehicleClass":"%s", "VehicleName":"%s", "VehicleCustomizationId":"%s", "TimeStored":"%s", "ChassisDurability":%s, "bIsMigrated":%s}', player_id, in_vehicle_id, vehicle_class, vehicle_name, in_customization_id, NOW() AT TIME ZONE 'UTC', in_chassis_durability, CASE WHEN in_is_migration THEN 'true' ELSE 'false' END) );
END;
$function$

View File

@@ -0,0 +1,39 @@
-- store_recovered_vehicles_wiped_before_spawn(in_vehicle_ids bigint[], in_delete_items boolean) -> void
-- oid: 58600 kind: FUNCTION category: vehicle
CREATE OR REPLACE FUNCTION dune.store_recovered_vehicles_wiped_before_spawn(in_vehicle_ids bigint[], in_delete_items boolean DEFAULT true)
RETURNS void
LANGUAGE plpgsql
AS $function$
DECLARE
to_store RECORD;
BEGIN
FOR to_store IN
SELECT v.id AS vehicle_id, a.properties -> (regexp_replace("class", '^.*\.', '')) ->> 'm_CustomizationId' AS customization_id
FROM actors a
INNER JOIN vehicles v ON a.id = v.id
INNER JOIN permission_actor p ON a.id = p.actor_id
INNER JOIN permission_actor_rank r ON p.actor_id = r.permission_actor_id
WHERE v.id = ANY(in_vehicle_ids)
AND r.rank = 1::smallint
AND NOT EXISTS
(
SELECT 1 FROM actor_state
WHERE actor_state.actor_id = v.id
AND actor_state.state IS DISTINCT FROM 'Default'
)
LOOP
-- remove all items in all inventories of that vehicle
if in_delete_items then
PERFORM delete_items_from_actor(to_store.vehicle_id);
end if;
-- note: storing hardcoded chassis durability because its not available from pure database :(
-- this will only be shown incorrectly in UI though, the spawned vehicle will get the correct value
PERFORM store_recovered_vehicle(to_store.vehicle_id, 0.25, to_store.customization_id);
-- remove permissions so the stored vehicles don't count towards the vehicle limit (the owner is preserved in the store function above)
PERFORM permission_actor_destroy(to_store.vehicle_id);
END LOOP;
END
$function$