From 9c4d4320f4579ebe56614dadadfbcf754025b500 Mon Sep 17 00:00:00 2001 From: JohnM <234386938+treuenten@users.noreply.github.com> Date: Sat, 10 Oct 2026 00:08:34 +0800 Subject: [PATCH] Treat a deleted entity as undefined for the rest of its frame delete() only queues an entity; it is retired at the scheduler's frame boundary so scripts can still read its fields for the rest of the frame. isdefined() looked only at retired entities, though, so an entity deleted earlier in the same frame still tested defined. The game's scripts expect the opposite. common_scripts/_pipes deletes the sound of a finished pipe burst and immediately runs array_removeUndefined on its list. The dead sound stayed in the list, and the next hit on that pipe faulted in pipe_logic (DistanceSquared on the sound's now-undefined origin), took the "return false" path, and the pipe never burst again for the rest of the match (mp_highrise). isdefined() now also treats an entity with a pending delete as gone. Field reads are unchanged. Co-Authored-By: Claude Opus 5.5 --- crates/sim/src/script/host/registry.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/sim/src/script/host/registry.rs b/crates/sim/src/script/host/registry.rs index 4e883c5..72825bb 100644 --- a/crates/sim/src/script/host/registry.rs +++ b/crates/sim/src/script/host/registry.rs @@ -17,7 +17,10 @@ impl Default for NativeRegistry { } let defined = match &args[0] { Value::Undefined => false, - Value::Object(id) => world.resource::().live(id), + Value::Object(id) => { + let runtime = world.resource::(); + runtime.live(id) && !runtime.pending_deletes.contains(id) + } _ => true, }; Ok(Value::Int(i32::from(defined)))