Summary
LocationBasedActionSpec.OnArriveGraffiti() fails when a custom NPC schedule activates location-based graffiti on IL2CPP. The NPC starts walking toward the graffiti action, then stops, and S1API logs that the resolved GraffitiBehaviour could not be cast to the concrete type.
Game Version
Other (specify in Additional Context)
S1API Version
3.0.5 / current stable local build
MelonLoader Version
0.7.2
Runtime Environment
IL2CPP (Regular)
Steps to Reproduce
- Create a custom NPC with
builder.EnsureGraffiti() in prefab configuration.
- Add a location-based schedule action that calls
.OnArriveGraffiti().
- Load the NPC on the public IL2CPP game branch.
- Let the NPC's schedule activate the graffiti action.
- Observe that the NPC walks briefly/stops and graffiti never starts.
Expected vs Actual Behavior
Expected: The NPC resolves its GraffitiBehaviour, assigns a spray surface, activates the behavior, and starts spraying graffiti.
Actual: The graffiti behavior lookup returns something named/resolved as GraffitiBehaviour, but S1API fails the concrete cast and returns before assigning the surface or activating the behavior.
MelonLoader Log
[16:58:30.889] Melon Assembly loaded: '.\Mods\CustomNPCTest_Il2cpp.dll'
[16:58:30.899] Melon Assembly loaded: '.\Mods\S1API.dll'
[16:58:31.128] S1API (Forked by Bars) v3.0.5
[16:58:36.313] CustomNPCTest mod initialized
[16:59:50.001] [LocationBasedActionSpec] [LocationBasedActionSpec] Graffiti: GraffitiBehaviour could not be cast to the concrete type.
What Have You Tried?
- Verified the issue reproduces after the same location-based schedule path was fixed for smoke breaks.
- Confirmed
CustomNPCTest and S1API load successfully before the warning.
- Inspected the failing S1API path:
LocationBasedActionSpec.ToggleGraffiti() calls npcBehaviour.GetBehaviour("GraffitiBehaviour"), then uses behaviour as GraffitiBehaviour; the cast fails on IL2CPP.
Additional Context
This looks similar in shape to the smoke-break issue fixed for #85: the schedule event fires and reaches the action-specific code, but the custom NPC behavior/component path does not line up with the current IL2CPP runtime wrapper behavior.
Initial suspicion: NPCBehaviour.GetBehaviour(string) returns the base Behaviour wrapper, and the direct C# as GraffitiBehaviour cast is not reliable for the IL2CPP wrapper object returned from that lookup. S1API may need to resolve the live component directly (GetComponentInChildren<GraffitiBehaviour>(true) / behavior stack scan / generated wrapper cast helper) before calling SetSpraySurface_Client.
Pre-submission Checklist
Summary
LocationBasedActionSpec.OnArriveGraffiti()fails when a custom NPC schedule activates location-based graffiti on IL2CPP. The NPC starts walking toward the graffiti action, then stops, and S1API logs that the resolvedGraffitiBehaviourcould not be cast to the concrete type.Game Version
Other (specify in Additional Context)
S1API Version
3.0.5 / current
stablelocal buildMelonLoader Version
0.7.2
Runtime Environment
IL2CPP (Regular)
Steps to Reproduce
builder.EnsureGraffiti()in prefab configuration..OnArriveGraffiti().Expected vs Actual Behavior
Expected: The NPC resolves its
GraffitiBehaviour, assigns a spray surface, activates the behavior, and starts spraying graffiti.Actual: The graffiti behavior lookup returns something named/resolved as
GraffitiBehaviour, but S1API fails the concrete cast and returns before assigning the surface or activating the behavior.MelonLoader Log
What Have You Tried?
CustomNPCTestand S1API load successfully before the warning.LocationBasedActionSpec.ToggleGraffiti()callsnpcBehaviour.GetBehaviour("GraffitiBehaviour"), then usesbehaviour as GraffitiBehaviour; the cast fails on IL2CPP.Additional Context
This looks similar in shape to the smoke-break issue fixed for #85: the schedule event fires and reaches the action-specific code, but the custom NPC behavior/component path does not line up with the current IL2CPP runtime wrapper behavior.
Initial suspicion:
NPCBehaviour.GetBehaviour(string)returns the baseBehaviourwrapper, and the direct C#as GraffitiBehaviourcast is not reliable for the IL2CPP wrapper object returned from that lookup. S1API may need to resolve the live component directly (GetComponentInChildren<GraffitiBehaviour>(true)/ behavior stack scan / generated wrapper cast helper) before callingSetSpraySurface_Client.Pre-submission Checklist