Jump to content

Why is sound not stopping with stopSound() ?


sirrjohn

Recommended Posts

I get the following error

spacer.png

 

 

-- PLAY ZOMBIE SOUNDS
local zombiesounds = {
	"Sonidos/zgroan (1).ogg", 
	"Sonidos/zgroan (2).ogg",
	"Sonidos/zgroan (3).ogg", 
	"Sonidos/zgroan (4).ogg", 
	"Sonidos/zgroan (5).ogg", 
	"Sonidos/zgroan (6).ogg", 
	"Sonidos/zgroan (7).ogg",
	"Sonidos/zgroan (8).ogg",
	"Sonidos/zgroan (9).ogg",
	"Sonidos/zgroan (10).ogg",
	"Sonidos/zgroan (11).ogg", 
	"Sonidos/zgroan (12).ogg",
	"Sonidos/zgroan (13).ogg", 
	"Sonidos/zgroan (14).ogg", 
	"Sonidos/zgroan (15).ogg", 
	"Sonidos/zgroan (16).ogg", 
	"Sonidos/zgroan (17).ogg",
	"Sonidos/zgroan (18).ogg",
	"Sonidos/zgroan (19).ogg",
	"Sonidos/zgroan (20).ogg", 
	"Sonidos/zgroan (21).ogg", 
	"Sonidos/zgroan (22).ogg",
	"Sonidos/zgroan (23).ogg", 
	"Sonidos/zgroan (24).ogg", 
	"Sonidos/zgroan (25).ogg", 
	"Sonidos/zgroan (26).ogg", 
	"Sonidos/zgroan (27).ogg",
	"Sonidos/zgroan (28).ogg",
	"Sonidos/zgroan (29).ogg",
	"Sonidos/zgroan (30).ogg", 
	"Sonidos/zgroan (31).ogg", 
	"Sonidos/zgroan (32).ogg",
	"Sonidos/zgroan (33).ogg", 
	"Sonidos/zgroan (34).ogg", 
	"Sonidos/zgroan (35).ogg", 
	"Sonidos/zgroan (36).ogg", 
} 
zedSound = false


function playZombieSounds()
local ped = getElementsByType("ped")
	for theKey,peds in ipairs(ped) do
		if ped and isElement(peds) and isElementStreamedIn(peds) then
			local Zx,Zy,Zz = getElementPosition(peds)
			zedSound = playSound3D(zombiesounds[math.random(1,#zombiesounds)], Zx, Zy, Zz, false)
			setSoundMaxDistance(zedSound,5)
		end
		
		if getElementData(peds,"deadman") or getElementData(peds,"Muerto") then
			stopSound(zedSound)
		end		
	end
end
setTimer(playZombieSounds,6000,0)

 

Link to comment
function playZombieSounds()
local ped = getElementsByType("ped")
	for theKey,peds in ipairs(ped) do
		if ped and isElement(peds) and isElementStreamedIn(peds) then
      if getElementData(peds,"deadman") or getElementData(peds,"Muerto") return end
			local Zx,Zy,Zz = getElementPosition(peds)
			zedSound = playSound3D(zombiesounds[math.random(1,#zombiesounds)], Zx, Zy, Zz, false)
			setSoundMaxDistance(zedSound,5)
		end
		end		
	end
setTimer(playZombieSounds,6000,0)

 

Link to comment
5 hours ago, Bishop_G said:
function playZombieSounds()
local ped = getElementsByType("ped")
	for theKey,peds in ipairs(ped) do
		if ped and isElement(peds) and isElementStreamedIn(peds) then
      if getElementData(peds,"deadman") or getElementData(peds,"Muerto") return end
			local Zx,Zy,Zz = getElementPosition(peds)
			zedSound = playSound3D(zombiesounds[math.random(1,#zombiesounds)], Zx, Zy, Zz, false)
			setSoundMaxDistance(zedSound,5)
		end
		end		
	end
setTimer(playZombieSounds,6000,0)

 

Hey Bishop! Sadly it didnt work... I had the same code on a different zombie gamemode and there it worked fine... but on this one it doesnt.. zombies keep making sounds when dead

Edited by sirrjohn
Link to comment
for theKey,peds in ipairs(ped) do
  if ped and isElement(peds) and isElementStreamedIn(peds) then
    local Zx,Zy,Zz = getElementPosition(peds)
    zedSound = playSound3D(zombiesounds[math.random(1,#zombiesounds)], Zx, Zy, Zz, false)

zedSound variable is overwritten for every ped. This means you're creating new sounds but discarding the pointer/reference/element handle for the old one. The old one will thus remain playing and you have no way* to delete it. What you need instead is a table of sounds you've spawned, and when you call stopSound, you should call it once per sound element in that table. This should stop all the sounds you've created.

Example:

-- when creating
spawnedSounds = {}
for theKey,peds in ipairs(ped) do
  if ped and isElement(peds) and isElementStreamedIn(peds) then
    local Zx,Zy,Zz = getElementPosition(peds)
    zedSound = playSound3D(zombiesounds[math.random(1,#zombiesounds)], Zx, Zy, Zz, false)
    -- do whatever with zedSound
    spawnedSounds[ped] = zedSound -- store the zedSound into a table for later when calling stopSound


    -- when stopping
    for theKey,theSound in pairs(spawnedSounds) do -- go through each sound in the table (note the use of pairs is 
      -- essential if the keys of the table are not numerical and sequential: in this case they are elements so pairs, is needed)
      
      -- (also NB: some performance comparisons point out pairs is faster than ipairs even with sequential numeric tables
      --  so you can just blindly always use pairs instead of ipairs without performance impact)
      stopSound(theSound) -- stop the sound that is stored as the value of a key=value pair in each row of the table
    end

* You can still recover the pointer/reference/element handle though functions like getElementsByType for sound type but its going to be much harder to identify which one you want.

Edited by Addlibs
  • Thanks 1
Link to comment
13 hours ago, Addlibs said:
for theKey,peds in ipairs(ped) do
  if ped and isElement(peds) and isElementStreamedIn(peds) then
    local Zx,Zy,Zz = getElementPosition(peds)
    zedSound = playSound3D(zombiesounds[math.random(1,#zombiesounds)], Zx, Zy, Zz, false)

zedSound variable is overwritten for every ped. This means you're creating new sounds but discarding the pointer/reference/element handle for the old one. The old one will thus remain playing and you have no way* to delete it. What you need instead is a table of sounds you've spawned, and when you call stopSound, you should call it once per sound element in that table. This should stop all the sounds you've created.

Example:

-- when creating
spawnedSounds = {}
for theKey,peds in ipairs(ped) do
  if ped and isElement(peds) and isElementStreamedIn(peds) then
    local Zx,Zy,Zz = getElementPosition(peds)
    zedSound = playSound3D(zombiesounds[math.random(1,#zombiesounds)], Zx, Zy, Zz, false)
    -- do whatever with zedSound
    spawnedSounds[ped] = zedSound -- store the zedSound into a table for later when calling stopSound


    -- when stopping
    for theKey,theSound in pairs(spawnedSounds) do -- go through each sound in the table (note the use of pairs is 
      -- essential if the keys of the table are not numerical and sequential: in this case they are elements so pairs, is needed)
      
      -- (also NB: some performance comparisons point out pairs is faster than ipairs even with sequential numeric tables
      --  so you can just blindly always use pairs instead of ipairs without performance impact)
      stopSound(theSound) -- stop the sound that is stored as the value of a key=value pair in each row of the table
    end

* You can still recover the pointer/reference/element handle though functions like getElementsByType for sound type but its going to be much harder to identify which one you want.

It seems its working, but how to stop sound only when ped is dead?

 

i tried this, didnt work

 

spawnedSounds = {}
function playZombieSounds()
	local ped = getElementsByType("ped")
	for theKey,peds in ipairs(ped) do
	  if ped and isElement(peds) and isElementStreamedIn(peds) then
		local Zx,Zy,Zz = getElementPosition(peds)
		zedSound = playSound3D(zombiesounds[math.random(1,#zombiesounds)], Zx, Zy, Zz, false)
		spawnedSounds[ped] = zedSound


		for theKey,theSound in pairs(spawnedSounds) do 
		if getElementData(ped,"deadman") or getElementData(ped,"Muerto") then
		  stopSound(theSound)
		end
		end
	end
end
end
setTimer(playZombieSounds,6000,0)

 

Link to comment

There seems to be confusion between variables due to a poor choice of names. ped is a table of all peds while peds is the current ped in the iteration. Because of that, the sound handle inserted into the table in one iteration still gets overridden in the other - because ped is the same value between iterations (always refers to the table of all peds). So it's better to swap them. But with the current names, you're supposed to use spawnedSounds[peds] to refer to the current ped's sound, and pass peds to getElementData.

Link to comment
13 hours ago, DiSaMe said:

There seems to be confusion between variables due to a poor choice of names. ped is a table of all peds while peds is the current ped in the iteration. Because of that, the sound handle inserted into the table in one iteration still gets overridden in the other - because ped is the same value between iterations (always refers to the table of all peds). So it's better to swap them. But with the current names, you're supposed to use spawnedSounds[peds] to refer to the current ped's sound, and pass peds to getElementData.

It works now, but with many DUPS... 

DCImRbR.png

 


spawnedSounds = {}
function playZombieSounds()
	local ped = getElementsByType("ped")
	for theKey,peds in ipairs(ped) do
	  if ped and isElement(peds) and isElementStreamedIn(peds) then
		local Zx,Zy,Zz = getElementPosition(peds)
		zedSound = playSound3D(zombiesounds[math.random(1,#zombiesounds)], Zx, Zy, Zz, false)
		spawnedSounds[peds] = zedSound


		for theKey,theSound in pairs(spawnedSounds) do 
		if getElementData(peds,"deadzombie") then
		  stopSound(theSound)
		end
		end
	end
end
end
setTimer(playZombieSounds,6000,0)

 

Link to comment

This block:

for theKey,theSound in pairs(spawnedSounds) do
  --
end

was meant to be used separately from the code that starts the sounds. By putting it into the same block, you're stopping the sounds for all peds if the current ped has deadzombie set to true, as it loops through spawnedSounds table.

I'd say your initial code is close enough, you just need to use spawnedSounds[peds] to refer to the current ped's sound.

But then the warning will still be there, it happens because calling stopSound destroys the sound element, but the (no-longer-valid) handle is still in spawnedSounds table, so when it gets passed to stopSound the next time, you get a warning. You can remove a value from the table by assigning nil to it, so destroying the current ped's sound would look like this:

stopSound(spawnedSounds[peds]) -- stop the sound, destroy the sound element
spawnedSounds[peds] = nil -- remove the no-longer-existing element from the table

But even then, I can think of scenarios where things go wrong. Like for example the loop is executed every 6 seconds, so you call playSound3D and store the result to spawnedSounds[peds] repeatedly, meaning the sound element from the previous execution is still overwritten by new sound element. So the next stopSound call will only stop the ped's most recent sound. I guess the right way to handle this depends on your needs, but in any case, assuming you clean up the sounds from the table after stopping them, you can check if the sound from earlier executions exists by directly checking the value in the table:

if spawnedSounds[peds] then
  -- called if the sound exists
else
  -- called if the sound doesn't exist
end

 

  • Thanks 1
Link to comment
spawnedSounds = {}
function playZombieSounds()
   local ped = getElementsByType("ped")
   for theKey,peds in ipairs(ped) do
      if ped and isElement(peds) and isElementStreamedIn(peds) then
	     local Zx,Zy,Zz = getElementPosition(peds)
         if not spawnedSounds[peds] or not isElement(spawnedSounds[peds] then
            spawnedSounds[peds] = playSound3D(zombiesounds[math.random(1,#zombiesounds)], Zx, Zy, Zz, false)
         end 
	  end
   end
end
setTimer(playZombieSounds,6000,0)
    
addEventHandler("onClientPedWasted", root, 
   function()
      if spawnedSounds[source] and isElement(spawnedSounds[source] then 
         destroyElement(spawnedSounds[source])
         spawnedSounds[source] = nil            
      end 
   end
)

 

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...