Changed in v1.4. Overthrow no longer uses the Enfusion Persistence Framework (EPF) or the Enfusion Database Framework (EDF). Both mods have been removed entirely — there are zero EPF references left in the codebase, and Overthrow has no mod dependencies. Saving and loading now run on Arma Reforger's own persistence system. The EPF
ReadFrom/ApplyTosave-data pattern documented here previously no longer exists.
Overthrow persists state through Arma Reforger's SCR_PersistenceSystem, wired up in Configs/Systems/Persistence/Overthrow.conf (which inherits vanilla's Common.conf).
There are two things to understand: component serializers, which persist manager state, and tracking, which decides whether a runtime-spawned entity is saved at all.
A component whose state must survive a save gets a ScriptedComponentSerializer. These live in Scripts/Game/Persistence/Serializers/Components/.
class OVT_ExampleSerializer : ScriptedComponentSerializer
{
//! The component class this serializer is responsible for.
override static typename GetTargetType()
{
return OVT_ExampleComponent;
}
override protected ESerializeResult Serialize(notnull IEntity owner, notnull GenericComponent component, notnull SaveContext context)
{
const OVT_ExampleComponent example = OVT_ExampleComponent.Cast(component);
if (!example)
return ESerializeResult.ERROR;
context.WriteValue("version", 1);
context.Write(example.GetSomeValue());
return ESerializeResult.OK;
}
override protected bool Deserialize(notnull IEntity owner, notnull GenericComponent component, notnull LoadContext context)
{
// ...read in exactly the order Serialize wrote
}
}
Return ESerializeResult.ERROR on a bad cast, DEFAULT when there is genuinely nothing to write, and OK otherwise.
ComponentSerializers block of the game-mode configuration in Configs/Systems/Persistence/Overthrow.conf, alongside vanilla's own component serializers.Deserialize must be idempotent. It also runs when saved data is re-applied to a live campaign (OVT_PersistenceManagerComponent.ReapplyLatestSaveData), so running it twice must be harmless.An instance is only saved if the persistence system has been told to track it. There are exactly three ways that happens:
Persistence component on the prefabPersistenceSystem.StartTracking() from scriptPersistentStateOverthrow spawns most of its world objects from prefabs it does not own — vanilla props, signs, sandbags, compositions — so route 1 would mean editing dozens of prefabs it doesn't control. Vanilla hits the same wall and solves it the same way (see SCR_EditableEntityComponent.c).
So runtime-spawned entities go through the helper:
OVT_PersistenceTracking.Track(entity);
Notes on this:
PersistenceConfig an instance gets is decided entirely by the rules in Overthrow.conf and the vanilla confs it inherits. Tracking an entity that no rule matches is harmless and simply stores nothing — which is why calling it over a mixed list of prefabs is safe.SystemLocation Server, so the lookup returns null on a client and the call becomes a no-op. Callers do not need to guard.Player bodies and locked vehicles use a reservation model (OVT_PersistenceReservation.c) rather than being saved and released on disconnect.
The distinction matters: a record that is saved and then untracked survives only a short window — measured at around 10 minutes, with no server restart required to lose it. Reserved entities are kept alive and hidden instead, so a player's body and vehicles are still there after days away and any number of restarts.
The old EPF advice — wrap every persistence call in #ifdef PLATFORM_CONSOLE because console platforms have no disk access — no longer applies to persistence, which is now the base game's own system.
PLATFORM_CONSOLE guards are still needed for Overthrow's own file I/O, such as reading and writing Overthrow_Config.json (see OVT_OverthrowConfigComponent).
ref) for arrays, maps, and managed class instancesSerialize and Deserialize adjacent in the file so the positional order stays obviousDeserialize idempotent — it runs on live re-apply, not just on loadOVT_TEST_PersistenceRoundTripSuite covers save → dirty → re-apply, plus a per-instance vehicle despawn/respawn round trip