Utility Scripts · Body Penetration

States and Events

Distinguish ongoing state from a one-off event and react to actual entry.

jolt_penetration_events() returns {schema, dropped_total, events}, or undefined. Reading drains the queue. One central consumer reads it after jolt_update and dispatches results to audio, damage and other systems; another consumer would receive an empty array.

Public states#

JoltPenetrationStateValueMeaning
Idle0No active connection or current blocking condition.
Candidate1The Tip is waiting for suitable conditions near a surface.
Penetrating2Actual entry has happened and the relationship is in its active penetration state.
Embedded3Derived after resting sufficiently inside material; not an additional fixed weld.
Extracting4Outward motion or releasing phase.
AtLimit5Reached the effective max_depth region.
Blocked6Aggregate rejected Tip state; inspect reject_reason.
Ended7Ended relationship in a final event snapshot.
Captured8A relationship created before actual entry; has_entered=false.

Events#

JoltPenetrationEventValueWhen it occurs
Start1The first actual entry for this relationship; snapshot has has_entered=true.
Embedded2Transition into the derived embedded state.
ExtractionStart3Transition into extraction. Can occur again after reinsertion within the same relationship.
Extracted4Full extraction of a relationship that had actual entry.
AtLimit5Transition to the depth limit.
End6Termination for any reason; follows Extracted during normal extraction.

End reasons#

JoltPenetrationEndReasonValueMeaning
Extracted1Full extraction.
PenetratorDestroyed2Penetrator body destroyed.
TargetDestroyed3Target body destroyed.
TipRemoved4Tip explicitly removed.
WorldStopped5World stopped; teardown also clears the event queue.
CaptureCancelled6Capture ended before actual entry; do not expect Start or Extracted.

Format and processing#

Each event has sequence, type, end_reason and snapshot. sequence increases; end_reason is 0 on events without an end reason. The snapshot is an independent native relationship-data copy including handles, depth and geometry; unlike rel.get_snapshot(), it does not contain a GML target wrapper. Identify the target using snapshot.target_handle and your own registry.

Initialize last_dropped=0 in Create before this Step code. Editing event data does not control the simulation.

GML
var batch = jolt_penetration_events();
if (is_struct(batch)) {
    if (batch.dropped_total > last_dropped) {
        show_debug_message("Penetration event loss detected");
    }
    last_dropped = batch.dropped_total;
    for (var i = 0; i < array_length(batch.events); ++i) {
        var event = batch.events[i];
        var snapshot = event.snapshot;
        switch (event.type) {
            case JoltPenetrationEvent.Start:
                show_debug_message("Entered " + string(snapshot.target_handle));
                break;
            case JoltPenetrationEvent.Extracted:
                show_debug_message("Extracted " + string(snapshot.handle));
                break;
            case JoltPenetrationEvent.End:
                show_debug_message("Ended: " + string(event.end_reason));
                break;
        }
    }
}

Verified operation contracts#

These contracts distinguish units, return values, errors and lifetime according to the current implementation. Check results: false, 0 and undefined can mean different things for different methods.

Symbol / ownerSignatureOperation contract
jolt_penetration_eventsjolt_penetration_events()Current schema:1 events/metrics snapshot of the managed world, undefined on invalid world/transport; not a physics mutation command.