How to wait() without yielding a while loop?

I have tried coroutines, delay, and spawn functions but I am most likely not using them properly. I am attempting to have the NPC search for threats constantly while the wander is delayed and doesn’t run again until the wait is over. The issue is that after the wander() function runs the first time, it loops with the findthreat() function.

while wait() do
	
	if hum.Health > 0 then	
		if aggrostate == false then
			
			local threat = findthreat()
			if threat then aggro(threat) end
			print("searching for threats..")

			delay(math.random(5,10), function()
				wander()
				print("wandering")
			end)
		end
	else
		break
	end
end

Are you saying that findthreat() has a wait in it?

Not sure if this is what you hope to achieve, but here’s a non-tested rewrite of your code snippet that may solve your problem or at least give you an idea of what to do. Note that this may not be the most optimal method.

local wanderingQueued = false
--[[
Previously, the delay function was being ran every wait(),
which basically removes the delay after the first one.
]]--

while task.wait() do
	if humanoid.Health <= 0 then
	    break
	end
	
	if inAggro then
	    return
	end
		
	local threat = findThreat()
	if threat then
	    aggro(threat) --Sets inAggro = true and to false when un-aggro'd
	    return
    end
    
    if wanderingQueued then
        return
    end
    
    coroutine.wrap(function()
        wanderingQueued = true
        task.wait(math.random(5, 10))
        wander() --set wanderingQueued = false when finished wandering
    end)()
end

you can use tick() for that,

local st = tick()
local randomtick = 5
while wait() do
	
	if hum.Health > 0 then	
		if aggrostate == false then	
			local threat = findthreat()
			if threat then aggro(threat) end
			print("searching for threats..")

			if tick() - st > randomtick then
                            st = tick()
                            randomtick = math.random(5,10)

		            wander()
			    print("wandering")
			end)
		end
	else
		break
	end
end

will run the function once it has been 5-10 seconds and restart the timer basically