Environment
- Schedule I 0.4.7f6, Steam beta branch, Steam build 25439817 (the 2026-09-21 beta update), IL2CPP
- MelonLoader 0.7.3
- S1API (Forked by Bars) 3.2.1-beta.2 (
+9d9d07706762ab943f548091b6b313b00bdb5514), S1MAPI 2.0.0
- No other mods loaded: a minimal repro mod (below) with S1API and S1MAPI only reproduces it
What happens
Two phone-only custom NPCs, subclasses of S1API.Entities.NPC built with the deprecated 4-argument constructor (base(id, firstName, lastName, null), which the [Obsolete] message describes as the supported path for non-physical NPCs), fail to instantiate on every attempt when a save is loaded:
[WARNING] [NPCPatches] [S1API] Failed to instantiate custom NPC type '<Type>' before contract loading:
System.Reflection.TargetInvocationException ---> System.InvalidOperationException:
The custom NPC prefab has no framework data object.
at S1API.Internal.Entities.NPCDataAccess.InitializeCurrentDataForConstruction(NPC npc)
at S1API.Entities.NPC..ctor()
at S1API.Entities.NPC..ctor(String id, String firstName, String lastName, Sprite icon)
at <Type>..ctor()
at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean wrapExceptions)
at S1API.Internal.Patches.NPCPatches.PrepareCustomNpcsForContractLoad()
The same failure repeats for each save ID and at "with default data", four attempts per type, so the contacts never exist.
Where it comes from
NPC() calls NPCDataAccess.InitializeCurrentDataForConstruction(prefabNpc), which throws when GetDataObject(npc) is null. NPCDataAccess.AssignNewData (which creates and attaches the NPCDataObject) is only called on the base-employee fallback path (when the source NPC component is replaced) and the dealer/supplier paths. As far as we can read from source (not verified at runtime), a plain NPC template where sourceNpc == replacementNpc never gets a data object attached, which would make both the parameterless path and the legacy constructor fail.
We don't know whether this also fails on 0.4.7f5 (the build 3.2.1-beta.2 was validated on) or only on f6. The f5→f6 code diff shows no NPC-framework changes, so the template's data object would be asset-side if anything.
Minimal repro result
With only S1API, S1MAPI and the repro mod below installed, loading a save logs the same exception for both contacts: the legacy 4-arg constructor and the recommended parameterless constructor with ConfigurePrefab + WithIdentity. After load, NPC.Get(id) returns null for both (REPRO RESULT ...: MISSING). The modern path throws from NPC..ctor() directly, so this is not specific to the deprecated constructor.
Expected
Non-physical NPCs created through the legacy constructor (or the parameterless one with no ConfigurePrefab override) get a framework data object, the same as on 3.2.0.
Repro
public sealed class ReproLegacyContact : S1API.Entities.NPC
{
#pragma warning disable CS0618
public ReproLegacyContact() : base("repro_legacy_contact", "Legacy", "Repro", null) { }
#pragma warning restore CS0618
}
public sealed class ReproModernContact : S1API.Entities.NPC
{
public ReproModernContact() : base() { }
protected override void ConfigurePrefab(S1API.Entities.NPCPrefabBuilder builder) =>
builder.WithIdentity("repro_modern_contact", "Modern", "Repro");
}
Load any save on 0.4.7f6 with 3.2.1-beta.2 installed. Both types fail in PrepareCustomNpcsForContractLoad with the exception above, and neither exists after load. The full MelonLoader log from the repro run is available on request.
Happy to test a fix build.
Environment
+9d9d07706762ab943f548091b6b313b00bdb5514), S1MAPI 2.0.0What happens
Two phone-only custom NPCs, subclasses of
S1API.Entities.NPCbuilt with the deprecated 4-argument constructor (base(id, firstName, lastName, null), which the[Obsolete]message describes as the supported path for non-physical NPCs), fail to instantiate on every attempt when a save is loaded:The same failure repeats for each save ID and at "with default data", four attempts per type, so the contacts never exist.
Where it comes from
NPC()callsNPCDataAccess.InitializeCurrentDataForConstruction(prefabNpc), which throws whenGetDataObject(npc)is null.NPCDataAccess.AssignNewData(which creates and attaches theNPCDataObject) is only called on the base-employee fallback path (when the source NPC component is replaced) and the dealer/supplier paths. As far as we can read from source (not verified at runtime), a plain NPC template wheresourceNpc == replacementNpcnever gets a data object attached, which would make both the parameterless path and the legacy constructor fail.We don't know whether this also fails on 0.4.7f5 (the build 3.2.1-beta.2 was validated on) or only on f6. The f5→f6 code diff shows no NPC-framework changes, so the template's data object would be asset-side if anything.
Minimal repro result
With only S1API, S1MAPI and the repro mod below installed, loading a save logs the same exception for both contacts: the legacy 4-arg constructor and the recommended parameterless constructor with
ConfigurePrefab+WithIdentity. After load,NPC.Get(id)returns null for both (REPRO RESULT ...: MISSING). The modern path throws fromNPC..ctor()directly, so this is not specific to the deprecated constructor.Expected
Non-physical NPCs created through the legacy constructor (or the parameterless one with no
ConfigurePrefaboverride) get a framework data object, the same as on 3.2.0.Repro
Load any save on 0.4.7f6 with 3.2.1-beta.2 installed. Both types fail in
PrepareCustomNpcsForContractLoadwith the exception above, and neither exists after load. The full MelonLoader log from the repro run is available on request.Happy to test a fix build.