"cannot resume dead coroutine"

i’m having problems with a simple sound entity i’m trying to make.


function ENT:RunBehaviour() -- give me some new sequences, vary it up until i get communication working
local done = nil 
local sequence = nil
while(true) do
if(done ~= true) then
	local num = {"npc/overwatch/radiovoice/one.wav", "npc/overwatch/radiovoice/zero.wav", "npc/overwatch/radiovoice/two.wav", "npc/overwatch/radiovoice/three.wav", "npc/overwatch/radiovoice/four.wav","npc/overwatch/radiovoice/five.wav",}
	local RanNum = num[math.random(#num)]
	local desig = {"npc/overwatch/radiovoice/defender.wav","npc/overwatch/radiovoice/patrol.wav","npc/overwatch/radiovoice/union.wav","npc/overwatch/radiovoice/victor.wav","npc/overwatch/radiovoice/xray.wav","npc/overwatch/radiovoice/yellow.wav","npc/overwatch/radiovoice/roller.wav","npc/overwatch/radiovoice/jury.wav"}
	local RanDesig = desig[math.random(#desig)]
	PrintTable(desig)
	
	--local ShouldSound = math.random(3,3)
	--print(ShouldSound)
		--if(ShouldSound == 3) then
			 sequence = math.random(2,2)
		--end
		print(sequence)
	
if(sequence == 1) then
		print("picked 1")
			local len = SoundDuration("npc/metropolice/die1.wav")
			local len2 = SoundDuration("npc/overwatch/radiovoice/on3.wav") +len
			local len3 = SoundDuration("npc/overwatch/radiovoice/lostbiosignalforunit.wav") +len2
			local len4 = SoundDuration(RanDesig) + len3
			local len5 = SoundDuration(RanNum) + len4

		timer.Simple(len, function() self:EmitSound("npc/overwatch/radiovoice/on3.wav") end)
		timer.Simple(len2, function() self:EmitSound("npc/overwatch/radiovoice/lostbiosignalforunit.wav") end)
		timer.Simple(len3, function() self:EmitSound("npc/overwatch/radiovoice/patrol.wav") end)
		timer.Simple(len4, function() self:EmitSound(RanNum)   end)
		timer.Simple(len5, function() self:EmitSound("npc/overwatch/radiovoice/off2.wav") done=true self:Remove() end)

elseif(sequence == 2)then
print("picked 2")
local lenq = SoundDuration("npc/metropolice/die1.wav")
	local len2q = SoundDuration("npc/overwatch/radiovoice/on3.wav") +lenq
	local len3q = SoundDuration(RanDesig) +len2q
	local len4q = SoundDuration(RanNum) + len3q
	local len5q = SoundDuration("npc/overwatch/radiovoice/unitdownat.wav") + len4q
	local len6q = SoundDuration("npc/overwatch/radiovoice/sector.wav") +len5q
	local len7q = SoundDuration(RanNum)
	
	timer.Simple(lenq, function() self:EmitSound("npc/overwatch/radiovoice/on3.wav") end)
	timer.Simple(len2q, function() self:EmitSound(RanDesig) end)
	timer.Simple(len3q, function() self:EmitSound(RanNum) end)
	timer.Simple(len4q, function() self:EmitSound("npc/overwatch/radiovoice/unitdownat.wav") end)
	timer.Simple(len5q, function() self:EmitSound("npc/overwatch/radiovoice/sector.wav") end)
	timer.Simple(len6q, function() self:EmitSound(RanNum) end)
	timer.Simple(len7q, function() done = true self:Remove() end)
/*elseif(sequence == 3) then
print("got nothing")
self:Remove()
*/
end

	
end
return
end
end

if sequence 2 is chosen, and the code reaches this point:


elseif(sequence == 2)then
print("picked 2")
local lenq = SoundDuration("npc/metropolice/die1.wav")
	local len2q = SoundDuration("npc/overwatch/radiovoice/on3.wav") +lenq
	local len3q = SoundDuration(RanDesig) +len2q
	local len4q = SoundDuration(RanNum) + len3q
	local len5q = SoundDuration("npc/overwatch/radiovoice/unitdownat.wav") + len4q
	local len6q = SoundDuration("npc/overwatch/radiovoice/sector.wav") +len5q
	local len7q = SoundDuration(RanNum)
	
	timer.Simple(lenq, function() self:EmitSound("npc/overwatch/radiovoice/on3.wav") end)
	timer.Simple(len2q, function() self:EmitSound(RanDesig) end)
	timer.Simple(len3q, function() self:EmitSound(RanNum) end)
	timer.Simple(len4q, function() self:EmitSound("npc/overwatch/radiovoice/unitdownat.wav") end)
	timer.Simple(len5q, function() self:EmitSound("npc/overwatch/radiovoice/sector.wav") end)
	timer.Simple(len6q, function() self:EmitSound(RanNum) end)
	timer.Simple(len7q, function() done = true self:Remove() end)
/*elseif(sequence == 3) then
print("got nothing")
self:Remove()
*/
end

it gives the error: “NextBot [116][sound_bot]error: cannot resume dead coroutine”

and the entity removes itself, causing all the timers to fail.

sorry for the wall of code, i guessed that there might be something wrong with the definitions? Any thing off here?

Nothing?
My code too disorganized?
Am i missing some blatantly obvious thing?

I’d recommend making a table outside of your RunBehavior ( loop… ) which grabs sound-duration ONCE instead of re-calculating it every frame that RunBehavior runs…

don’t use timer.Simple with coroutines, use coroutine.wait



--CODE
coroutine.wait(2) --pauses the coroutine, it will NOT continue OR do anything AT ALL for 2 seconds
--MORE CODE


Hey, what a coincidence, I just wrote one of these. Don’t use timers for stuff like this, that’s a really bad way to do it.

Using a table of sounds and a single timer is a lot simpler to write, easier to update and it separates building the phrase from actually playing it:
[lua]
– holy shit this is so ugly
local sndlist = {}
local function addLine(s)
if type(s) == “table” then
for i, v in ipairs(s) do
– awful way of adding commas in compound phrases
if i ~= 1 then
sndlist[#sndlist + 1] = “npc/overwatch/radiovoice/_comma.wav”
end
sndlist[#sndlist + 1] = “npc/overwatch/radiovoice/” … v … “.wav”
end
return
end
sndlist[#sndlist + 1] = “npc/overwatch/radiovoice/” … s … “.wav”
end

if math.random() > 0.5 then
addLine(“attention”)
addLine("_comma")
end

addLine(“die” … math.random(1, 3))
addLine(“on3”)
addLine(math.random() > 0.5 and “lostbiosignalforunit” or “unitdeserviced”)
addLine("_comma")
addLine(table.Random{
“remainingunitscontain”,
{ “switchcomtotac3”, “remainingunitscontain” },
{ “switchcomtotac3”, “investigateandreport” },
{ “suspectisnow187”, “investigateandreport” },
{ “suspectisnow187”, “remainingunitscontain” },
“allteamsrespondcode3”,
“teamsreportstatus”,
“switchtotac5andreporttocp”
})
addLine(“off2”)

– single timer goes over our phrase file-by-file, pausing for the appropriate amount of time
local pos = ply:GetPos()
local function play()
local snd = table.remove(sndlist, 1)
if not snd then return end

sound.Play(snd, pos, 100, 100, 1)

timer.Simple(SoundDuration(snd), play)

end
play()[/lua]