Since you are emulating halo script, maybe some details on how it works internally would be useful.

The hs runtime has its own "hs threads" (which are not actual system threads). Eg, a startup script would spawn its own hs_thread, a continuous script would run in its own hs_thread, the console has its own hs_thread, globals are initialized in their own hs_thread, etc.

Like system threads, each hs_thread has its own stack memory. Bit of trivia: Kirby was a jerk and made a heavily nested script for a CMT feature which exceeded the stack memory of an hs_thread, causing it to overflow into another hs_thread (and thus crashing). Were the community to have access to actual debug/tag builds of the runtime, there would be errors explaining this overflow. Instead, I had to debug this nonsense, which wasn't immediately obvious (and I wasn't involved with CMT's scripts). The stack memory contains stack frames (essentially an IP and a few other useful values) plus arguments to hs functions.

Anyway, for sleep they set a field to be 'current-game-time + sleep-time', and when the hs_runtime updates it checks that if the current game time to be sure if it can evaluate the hs_thread yet.

Also, 343i no longer uses the a LISP-esque syntax for halo script. Eg,
Code:
script static void f_rumble_gondola(player p_player)
    local boolean b_rumble_valid     = TRUE;
    local boolean b_rumble_active     = FALSE;
    local boolean b_rumble_break      = FALSE;
    local short rumble_count              = 0;
    local short rumble_count_max      = 10;
    
    repeat            
        if volume_test_object(tv_gondola_path, p_player) and b_rumble_valid  then
            rumble_count = rumble_count + 1;
            inspect(    rumble_count );
            if rumble_count >= rumble_count_max then
                b_rumble_valid = FALSE;
            end
                
            if not b_rumble_active then
                dprint("RUMBLE ON");
                player_effect_set_max_rumble_for_player(p_player, 0.1, 0.1);
                b_rumble_active = TRUE;
            end
                
        elseif not volume_test_object(tv_gondola_path, p_player) or not b_rumble_valid then
            
            dprint("RUMBLE OFF");
            player_effect_set_max_rumble_for_player(p_player, 0, 0);
            b_rumble_active = FALSE;
            
            if rumble_count >= rumble_count_max then
                sleep_s(1.5);
                rumble_count = 0;
                b_rumble_valid = TRUE;
            end
            
        end
            sleep_s(1);
            
    until(not sp01_gondola_moving, 1);
    player_effect_set_max_rumble_for_player(p_player, 0, 0);
end

IDK if this was work that Bungie had initially started, or if it was something 343i sparked. Either way, they changed a lot of the underlying implementation of the script system (for the better AFAICT)