Jump to content

[HELP] First time testing server with other players. I found several issues.


Moony

Recommended Posts

I've found six issues so far. Being alone, everything seemed fine; with players, these issues are visible.

For the sake of organization and to avoid overwhelming, I'll be going through each issue (if possible), instead of throwing everything at once —unless asked otherwise—.

First in the list is about client.Lua's 'outputChatBox' showing to everyone in the chatbox:

I've got two scripts in this moment that are causing said inconvenient: a quick ATM system and a teleport system. The ATM is a simple marker that, when hit, gives you $500, and outputs that information. The teleports work the same way, but instead, the set the interior, position and rotation of the player, and output a message.

ATM:

Client:
(this example's location is at LV's gas station, next to Four Dragon's Casino).

atm1 = createMarker (2123.0048828125, 897.57653808594, 10.1796875, "cylinder", 1, 0, 100, 0, 170)

function moneyLawn (hitPlayer, matchingDimension)
	if (source == atm1) and (isPedInVehicle(hitPlayer) == false) then
	triggerServerEvent ("givePlayerMoney", hitPlayer)
	outputChatBox ("#D2691E[#FF7F50INFO#D2691E]#FFFFFF: El servidor te regaló #006400$500.", 0, 0, 0, true)
	end
end

(translation: "The server gave you $500")

Server:

function giveToPlayer ()
	givePlayerMoney (root, 500)
end
addEvent ("giveMoney", true)
addEventHandler ("giveMoney", root, giveToPlayer)

Because of its close relation, I'll also name another issue regarding this script. The money is being given to all players in the server, and it is being multiplied by each player. This means that is, for example, I have 3 players in my server, when any player touches the marker, each player will be given $500 x amountOfPlayers = $1500.

Teleports:
(I have a few other teleports, but they only change interior and position).

Client:

-------------------------
-- FOUR DRAGONS CASINO --
-------------------------
inFourD = createMarker (2019.76953125, 1007.0116577148, 9.7203125, "cylinder", 1, 255, 0, 0, 153)

function inFourDragons (hitPlayer, matchingDimension)
    if (source == inFourD) and (isPedInVehicle(hitPlayer) == true) then
    outputChatBox("#D2691E[#FF7F50INFO#D2691E]#FFFFFF: No se permiten vehículos dentro.", 0, 0, 0, true)
    elseif (source == inFourD) and (isPedInVehicle(hitPlayer) == false) then
    outputChatBox("#D2691E[#FF7F50INFO#D2691E]#FFFFFF: Ingresaste al casino '#DD0000Four Dragons#FFFFFF'.", 0, 0, 0, true)
    setElementInterior (hitPlayer, 10)
    setElementPosition (hitPlayer, 2016.9376220703, 1017.0843505859, 996.875 )
    setElementRotation (hitPlayer, 0, 0, 90)
    end
end
addEventHandler ("onClientMarkerHit", root, inFourDragons)

outFourD = createMarker (2018.9376220703, 1017.0843505859, 995.875, "cylinder", 1, 255, 0, 0, 153)
setElementInterior (outFourD, 10)

function outFourDragons (hitPlayer, matchingDimension)
    if (source == outFourD) and (isPedInVehicle(hitPlayer) == true) then
    outputChatBox("#D2691E[#FF7F50INFO#D2691E]#FFFFFF: No se permiten vehículos dentro.", 0, 0, 0, true)
    elseif (source == outFourD) and (isPedInVehicle(hitPlayer) == false) then
    outputChatBox("#D2691E[#FF7F50INFO#D2691E]#FFFFFF: Te retiraste del casino '#DD0000Four Dragons#FFFFFF'.", 0, 0, 0, true)
    setElementInterior (hitPlayer, 0)
    setElementPosition (hitPlayer, 2021.76953125, 1007.0116577148, 10.7203125 )
    setElementRotation (hitPlayer, 0, 0, 90)
    end
end
addEventHandler ("onClientMarkerHit", root, outFourDragons)

[translation: (if player in veh) "No cars allowed". (if player not in veh) "You've entered/exited "Four Dragons" casino".]

There is no server.

This similar post, which I'm following, says that in client-side, the output is bound to be shown just for the player who triggered the event.

Link to comment
30 minutes ago, Moony said:

First in the list is about client.Lua's 'outputChatBox' showing to everyone in the chatbox:

I've got two scripts in this moment that are causing said inconvenient: a quick ATM system and a teleport system. The ATM is a simple marker that, when hit, gives you $500, and outputs that information. The teleports work the same way, but instead, the set the interior, position and rotation of the player, and output a message.

ATM:

Client:
(this example's location is at LV's gas station, next to Four Dragon's Casino).


atm1 = createMarker (2123.0048828125, 897.57653808594, 10.1796875, "cylinder", 1, 0, 100, 0, 170)

function moneyLawn (hitPlayer, matchingDimension)
	if (source == atm1) and (isPedInVehicle(hitPlayer) == false) then
	triggerServerEvent ("giveMoney", root)
	outputChatBox ("#D2691E[#FF7F50INFO#D2691E]#FFFFFF: El servidor te prestó #009900$500#FFFFFF.", 0, 0, 0, true)
	end
end
addEventHandler ("onClientMarkerHit", atm1, moneyLawn)

(translation: "The server gave you $500")

Server:


function giveToPlayer ()
	givePlayerMoney (root, 500)
end
addEvent ("giveMoney", true)
addEventHandler ("giveMoney", root, giveToPlayer)

Because of its close relation, I'll also name another issue regarding this script. The money is being given to all players in the server, and it is being multiplied by each player. This means that is, for example, I have 3 players in my server, when any player touches the marker, each player will be given $500 x amountOfPlayers = $1500.

Teleports:
(I have a few other teleports, but they only change interior and position).

Client:


-------------------------
-- FOUR DRAGONS CASINO --
-------------------------
inFourD = createMarker (2019.76953125, 1007.0116577148, 9.7203125, "cylinder", 1, 255, 0, 0, 153)

function inFourDragons (hitPlayer, matchingDimension)
    if (source == inFourD) and (isPedInVehicle(hitPlayer) == true) then
    outputChatBox("#D2691E[#FF7F50INFO#D2691E]#FFFFFF: No se permiten vehículos dentro.", 0, 0, 0, true)
    elseif (source == inFourD) and (isPedInVehicle(hitPlayer) == false) then
    outputChatBox("#D2691E[#FF7F50INFO#D2691E]#FFFFFF: Ingresaste al casino '#DD0000Four Dragons#FFFFFF'.", 0, 0, 0, true)
    setElementInterior (hitPlayer, 10)
    setElementPosition (hitPlayer, 2016.9376220703, 1017.0843505859, 996.875 )
    setElementRotation (hitPlayer, 0, 0, 90)
    end
end
addEventHandler ("onClientMarkerHit", root, inFourDragons)

outFourD = createMarker (2018.9376220703, 1017.0843505859, 995.875, "cylinder", 1, 255, 0, 0, 153)
setElementInterior (outFourD, 10)

function outFourDragons (hitPlayer, matchingDimension)
    if (source == outFourD) and (isPedInVehicle(hitPlayer) == true) then
    outputChatBox("#D2691E[#FF7F50INFO#D2691E]#FFFFFF: No se permiten vehículos dentro.", 0, 0, 0, true)
    elseif (source == outFourD) and (isPedInVehicle(hitPlayer) == false) then
    outputChatBox("#D2691E[#FF7F50INFO#D2691E]#FFFFFF: Te retiraste del casino '#DD0000Four Dragons#FFFFFF'.", 0, 0, 0, true)
    setElementInterior (hitPlayer, 0)
    setElementPosition (hitPlayer, 2021.76953125, 1007.0116577148, 10.7203125 )
    setElementRotation (hitPlayer, 0, 0, 90)
    end
end
addEventHandler ("onClientMarkerHit", root, outFourDragons)

[translation: (if player in veh) "No cars allowed". (if player not in veh) "You've entered/exited "Four Dragons" casino".]

There is no server.

This similar post, which I'm following, says that in client-side, the output is bound to be shown just for the player who triggered the event.

Spoiler

I'd really love the 'Edit' option to have its time extended.

I apologize. I had some errors in my script. It's been fixed now. It is the original with the output issues.

Link to comment

Using root will make things work, but very hard on the CPU. You will want to switch from root to getResourceRoot() instead for most cases, directed at those Event Handlers though. Also if it continues to execute for every player, add a check with onClientMarkerHit (outFourDragons) for the local player:

if(hitPlayer == localPlayer)then
  -- Whatever Code
end

 

Link to comment
58 minutes ago, ReZurrecti0n said:

Using root will make things work, but very hard on the CPU. You will want to switch from root to getResourceRoot() instead for most cases, directed at those Event Handlers though. Also if it continues to execute for every player, add a check with onClientMarkerHit (outFourDragons) for the local player:


if(hitPlayer == localPlayer)then
  -- Whatever Code
end

 

With that added to the client.Lua, now only the hitPlayer receives the message. However, all players are receiving the amount of money specified in the script.

Link to comment
24 minutes ago, #\_oskar_/# said:

givePlayerMoney (root, 500) -- root = all players

I changed 'root' to 'hitPlayer', 'source', 'player', 'localPlayer', and neither work. They either stop giving money, or give money to all players.

UPDATE: Works: added 'client' in place of 'root'. Now, each client receive the money and the message. Others players are not affected.

I guess it's [SOLVED]

Next issue: output to all when using Teleports.

Spoiler

-------------------------
-- FOUR DRAGONS CASINO --
-------------------------
inFourD = createMarker (2019.76953125, 1007.0116577148, 9.7203125, "cylinder", 1, 255, 0, 0, 153)

function inFourDragons (hitPlayer, matchingDimension)
    if (source == inFourD) and (isPedInVehicle(hitPlayer) == true) then
    outputChatBox("#D2691E[#FF7F50INFO#D2691E]#FFFFFF: No se permiten vehículos dentro.", 0, 0, 0, true)
    elseif (source == inFourD) and (isPedInVehicle(hitPlayer) == false) then
    outputChatBox("#D2691E[#FF7F50INFO#D2691E]#FFFFFF: Ingresaste al casino '#DD0000Four Dragons#FFFFFF'.", 0, 0, 0, true)
    setElementInterior (hitPlayer, 10)
    setElementPosition (hitPlayer, 2016.9376220703, 1017.0843505859, 996.875 )
    setElementRotation (hitPlayer, 0, 0, 90)
    end
end
addEventHandler ("onClientMarkerHit", root, inFourDragons)

outFourD = createMarker (2018.9376220703, 1017.0843505859, 995.875, "cylinder", 1, 255, 0, 0, 153)
setElementInterior (outFourD, 10)

function outFourDragons (hitPlayer, matchingDimension)
    if (source == outFourD) and (isPedInVehicle(hitPlayer) == true) then
    outputChatBox("#D2691E[#FF7F50INFO#D2691E]#FFFFFF: No se permiten vehículos dentro.", 0, 0, 0, true)
    elseif (source == outFourD) and (isPedInVehicle(hitPlayer) == false) then
    outputChatBox("#D2691E[#FF7F50INFO#D2691E]#FFFFFF: Te retiraste del casino '#DD0000Four Dragons#FFFFFF'.", 0, 0, 0, true)
    setElementInterior (hitPlayer, 0)
    setElementPosition (hitPlayer, 2021.76953125, 1007.0116577148, 10.7203125 )
    setElementRotation (hitPlayer, 0, 0, 90)
    end
end
addEventHandler ("onClientMarkerHit", root, outFourDragons)

 

I guess that I would have to add the same if to the client.Lua on each teleport function...

Loading...

Works!

Edited by Moony
Link to comment

Next issue might be simple.

I added custom sounds of guns. They work correctly. However, 'playSound3D' is not picking them up. I've set the vectors to 'getPedMuzzlePosition', but the custom sound is being heard on equal volume from next to the player to the point where the player is not being drawn anymore (draw distance).

function onClientPlayerWeaponFire ( weapon )
	local wX, wY, wZ = getPedWeaponMuzzlePosition ( getLocalPlayer() )
	local x, y, z = getElementPosition ( getLocalPlayer() )
	if weapon == 22 then--colt45
		playSound3D ( "sounds/Colt45.wav", false )
	elseif weapon == 23 then--silenced
		playSound3D ( "sounds/Silenced.wav", false )
	elseif weapon == 24 then--deagle
		playSound3D ( "sounds/Deagle.wav", false )
	elseif weapon == 25 then--shotgun
		playSound3D ( "sounds/Shotgun.wav", false )
	elseif weapon == 26 then--sawn-off
		playSound3D ( "sounds/Sawed-Off.wav", false )
	elseif weapon == 27 then--combat shotgun
		playSound3D ( "sounds/Combat Shotgun.wav", false )
	elseif weapon == 28 or weapon == 32 then--uzi/tec-9
		playSound3D ( "sounds/UZI_Tec9.wav", false )
	elseif weapon == 29 then--mp5
		playSound3D ( "sounds/MP5.wav", false )
	elseif weapon == 30 then--AKMS
		playSound3D ( "sounds/AKMS.wav", false )
	elseif weapon == 31 then--G36
		playSound3D ( "sounds/G36.wav", false )
	elseif weapon == 33 then--rifle
		playSound3D ( "sounds/Rifle.wav", false )
	elseif weapon == 34 then--sniper
		playSound3D ( "sounds/Sniper.wav", false )
	end 
end

addEventHandler ( "onClientPlayerWeaponFire", getRootElement(), onClientPlayerWeaponFire )

(Script was downloaded. Author is "Dr.PhillyBLunt".)

Link to comment

--Client

if hitPlayer == localPlayer then
triggerServerEvent ("giveMoney", hitPlayer )

---Server

givePlayerMoney (source, 500)

1 hour ago, Moony said:

Next issue might be simple.

I added custom sounds of guns. They work correctly. However, 'playSound3D' is not picking them up. I've set the vectors to 'getPedMuzzlePosition', but the custom sound is being heard on equal volume from next to the player to the point where the player is not being drawn anymore (draw distance).


function onClientPlayerWeaponFire ( weapon )
	local wX, wY, wZ = getPedWeaponMuzzlePosition ( getLocalPlayer() )
	local x, y, z = getElementPosition ( getLocalPlayer() )
	if weapon == 22 then--colt45
		playSound3D ( "sounds/Colt45.wav", false )
	elseif weapon == 23 then--silenced
		playSound3D ( "sounds/Silenced.wav", false )
	elseif weapon == 24 then--deagle
		playSound3D ( "sounds/Deagle.wav", false )
	elseif weapon == 25 then--shotgun
		playSound3D ( "sounds/Shotgun.wav", false )
	elseif weapon == 26 then--sawn-off
		playSound3D ( "sounds/Sawed-Off.wav", false )
	elseif weapon == 27 then--combat shotgun
		playSound3D ( "sounds/Combat Shotgun.wav", false )
	elseif weapon == 28 or weapon == 32 then--uzi/tec-9
		playSound3D ( "sounds/UZI_Tec9.wav", false )
	elseif weapon == 29 then--mp5
		playSound3D ( "sounds/MP5.wav", false )
	elseif weapon == 30 then--AKMS
		playSound3D ( "sounds/AKMS.wav", false )
	elseif weapon == 31 then--G36
		playSound3D ( "sounds/G36.wav", false )
	elseif weapon == 33 then--rifle
		playSound3D ( "sounds/Rifle.wav", false )
	elseif weapon == 34 then--sniper
		playSound3D ( "sounds/Sniper.wav", false )
	end 
end

addEventHandler ( "onClientPlayerWeaponFire", getRootElement(), onClientPlayerWeaponFire )

(Script was downloaded. Author is "Dr.PhillyBLunt".)

element playSound3D ( string soundURL, float x, float y, float z, [ bool looped = false, bool throttled = true ] )

where =  pos (x ,  y ,  z) ?

Link to comment

ATM is fixed. Works correctly now.

1 hour ago, #\_oskar_/# said:

 


element playSound3D ( string soundURL, float x, float y, float z, [ bool looped = false, bool throttled = true ] )

where =  pos (x ,  y ,  z) ?

The sound needs to come from 'getPedWeaponMuzzlePosition', which is relative to the player's position. Strangely, if I add that, the custom sound is replaced by the GTA's default sound; contrarily, if I don't add the function, the custom sound remains, yet the sound can be heard equally on all distances.

Link to comment
9 hours ago, #\_oskar_/# said:

local wX, wY, wZ = getPedWeaponMuzzlePosition ( getLocalPlayer() )local sound = playSound3D ( "sounds/Colt45.wav",wX, wY, wZ , false )

and use isElement 

I'm sorry, but I can't figure how to use the 'isElement' in this case. I've checked other examples, but it is very difficult for me to locate the function and understand how it's being treated/treats other functions.

Here's the slightly modified script:

Spoiler

function onClientPlayerWeaponFire ( weapon )
	local wX, wY, wZ = getPedWeaponMuzzlePosition ( getLocalPlayer() )
	local x, y, z = getElementPosition ( getLocalPlayer() )
	if weapon == 22 then--colt45
		playSound3D ( "sounds/Colt45.wav", false )
		setSoundMaxDistance ( "sounds/Colt45.wav", 100)
	elseif weapon == 23 then--silenced
		playSound3D ( "sounds/Silenced.wav", false )
		setSoundMaxDistance ( "sounds/Silenced.wav", 40)
	elseif weapon == 24 then--deagle
		playSound3D ( "sounds/Deagle.wav", false )
		setSoundMaxDistance ( "sounds/Deagle.wav", 150)
	elseif weapon == 25 then--shotgun
		playSound3D ( "sounds/Shotgun.wav", false )
		setSoundMaxDistance ( "sounds/Shotgun.wav", 150)
	elseif weapon == 26 then--sawn-off
		playSound3D ( "sounds/Sawed-Off.wav", false )
		setSoundMaxDistance ( "sounds/Sawed-Off.wav", 175)
	elseif weapon == 27 then--combat shotgun
		playSound3D ( "sounds/Combat Shotgun.wav", false )
		setSoundMaxDistance ( "sounds/Combat Shotgun.wav", 165)
	elseif weapon == 28 or weapon == 32 then--uzi/tec-9
		playSound3D ( "sounds/UZI_Tec9.wav", false )
		setSoundMaxDistance ( "sounds/UZI_Tec9.wav", 100)
	elseif weapon == 29 then--mp5
		playSound3D ( "sounds/MP5.wav", false )
		setSoundMaxDistance ( "sounds/MP5.wav", 80)
	elseif weapon == 30 then--AKMS
		playSound3D ( "sounds/AKMS.wav", false )
		setSoundMaxDistance ( "sounds/AKMS.wav", 130)
	elseif weapon == 31 then--G36
		playSound3D ( "sounds/G36.wav", wX, wY, wZ, false )
		setSoundMaxDistance ( "sounds/G36.wav", 120)
	elseif weapon == 33 then--rifle
		playSound3D ( "sounds/Rifle.wav", false )
		setSoundMaxDistance ( "sounds/Rifle.wav", 200)
	elseif weapon == 34 then--sniper
		playSound3D ( "sounds/Sniper.wav", false )
		setSoundMaxDistance ( "sounds/Sniper.wav", 200)
	end 
end

addEventHandler ( "onClientPlayerWeaponFire", getRootElement(), onClientPlayerWeaponFire )

 

How I understand, by defining that the three variables (wX, wY, wZ) represent the variables in 'getPedWeaponMuzzlePosition', if I do what I did with the G36, the sound would always come from the muffler of the weapon any player is carrying. However, after another test to make sure, I can confirm that the playSound3D is working, but the custom sound is not being processed. As a result, players can hear the weapon fade out as they get further away, but the sound is the GTA's default one.
If I replace 'playSound3D' with 'playSound', the custom sound will be heard, but the fade out will not exist.

Edited by Moony
Link to comment
function Sound3D(sound3d,...)
local wX, wY, wZ = getPedWeaponMuzzlePosition ( localPlayer )
local sound = playSound3D (sound3d,wX, wY, wZ, false  )
attachElements (sound ,localPlayer , 0, 0, 2 )
setSoundMaxDistance(sound, 50)
setElementDimension(sound,getElementDimension ( localPlayer ))
setElementInterior(sound,getElementInterior( localPlayer ),...)
return sound 
end

local weapons = {
[22] = "sounds/Colt45.wav",

--[id] = "sound name",
}

-- setWorldSoundEnabled(5,false) 
function onClientPlayerWeaponFire ( weapon )
if weapons[weapon] then
local x, y, z = getElementPosition ( localPlayer )
if isElement(sound ) then destroyElement(sound ) end 
sound = Sound3D(weapons[getPedWeapon(localPlayer)], x, y, z )
end 
end
addEventHandler ( "onClientPlayerWeaponFire", getRootElement(), onClientPlayerWeaponFire )

is this what you want ?

Link to comment
9 hours ago, #\_oskar_/# said:

function Sound3D(sound3d,...)local wX, wY, wZ = getPedWeaponMuzzlePosition ( localPlayer )local sound = playSound3D (sound3d,wX, wY, wZ, false  )attachElements (sound ,localPlayer , 0, 0, 2 )setSoundMaxDistance(sound, 50)setElementDimension(sound,getElementDimension ( localPlayer ))setElementInterior(sound,getElementInterior( localPlayer ),...)return sound endlocal weapons = {[22] = "sounds/Colt45.wav",--[id] = "sound name",}-- setWorldSoundEnabled(5,false) function onClientPlayerWeaponFire ( weapon )if weapons[weapon] thenlocal x, y, z = getElementPosition ( localPlayer )if isElement(sound ) then destroyElement(sound ) end sound = Sound3D(weapons[getPedWeapon(localPlayer)], x, y, z )end endaddEventHandler ( "onClientPlayerWeaponFire", getRootElement(), onClientPlayerWeaponFire )

is this what you want ?

To be honest, I don't know. I don't know a lot, but I had imagined that setting a playSound3D for a custom sound where its coordinates are the weapon's muzzle wouldn't look so complex.

It doesn't work. The sound is still the default one.

Edited by Moony
Link to comment
2 hours ago, #\_oskar_/# said:

 setWorldSoundEnabled(5,false) -- mute original sound weapon

 

Alright. Every shooting sound (included machine guns from planes) are muted. The guns I've gave a custom sound can be heard. Still, 'playSound3D' is not working. Weapons still can be heard equally from all distances.

Link to comment

You are creating all sounds from the gun muzzle position of the localPlayer. No wonder you hear all weapons equally as loud. I recommend you to use the source element in the onClientPlayerWeaponFire event to create the sound at. Also make sure to properly destroyElement sounds (not sure if required but just to be sure?).

Link to comment
2 hours ago, The_GTA said:

You are creating all sounds from the gun muzzle position of the localPlayer. No wonder you hear all weapons equally as loud. I recommend you to use the source element in the onClientPlayerWeaponFire event to create the sound at. Also make sure to properly destroyElement sounds (not sure if required but just to be sure?).

Using addEventHandler ("onClientPlayerWeaponFire", source, <functionName>) returns the default sounds.

I've tried using the wiki's example, but I'm left with overlaid sounds. Even adding 'setWorldSoundEnabled' affecting '5' (gunfires) doesn't fix it. On top of it, I'm having a very hard time testing the changes (for which I tried using SlothBot, but I never figured it out. Also tried using 'setPedControlState', but the ped stood there and DB 3 gave me an invalid value for "fire").

This is really frustrating. I thought it would be easy. I know there are several experienced members helping me, but I would have never imagined it to be so hard.

I'm back at level 1: I've got the custom sounds for each weapon, everyone hears them, but I can't set the custom sounds to be 3D (identify them from left or right, and hear them faded out when distanced).

Link to comment
4 hours ago, Moony said:

I've tried using the wiki's example, but I'm left with overlaid sounds. (...)

This is really frustrating. I thought it would be easy. I know there are several experienced members helping me, but I would have never imagined it to be so hard.

(...)

Dear Moony,

here is a script that fixes both overlaid sounds and the volume of distant sounds:

function Sound3D(shooterPed, sound3d)
    local wX, wY, wZ = getPedWeaponMuzzlePosition ( shooterPed )
    local sound = playSound3D (sound3d,wX, wY, wZ, false  )
    attachElements (sound ,shooterPed , 0, 0, 2 )
    setSoundMaxDistance(sound, 50)
    setElementDimension(sound,getElementDimension ( shooterPed ))
    setElementInterior(sound,getElementInterior( shooterPed ))
    return sound 
end

local weapons = {
[22] = "sounds/Colt45.wav",

--[id] = "sound name",
}

local pedSounds = {};

setWorldSoundEnabled(5,false) 
function onClientPlayerWeaponFire ( weapon )
    if weapons[weapon] then
        if isElement(pedSounds[source] ) then destroyElement(pedSounds[source] ) end 
        pedSounds[source] = Sound3D(source, weapons[weapon] )
    end 
end
addEventHandler ( "onClientPlayerWeaponFire", getRootElement(), onClientPlayerWeaponFire )

Sounds are not deleted if players leave the server. Implementing this is an exercise left for OP.

P.S. Please understand that scripting is an effort that you can train. If you are having trouble with parameters like "source" or don't know about the function calls, it can be a good idea to script some random resources (exploding bottle attachment to players, weapon attachment to vehicles, etc). :)

Edited by The_GTA
  • Thanks 1
Link to comment
9 hours ago, The_GTA said:
Spoiler


function Sound3D(shooterPed, sound3d)
    local wX, wY, wZ = getPedWeaponMuzzlePosition ( shooterPed )
    local sound = playSound3D (sound3d,wX, wY, wZ, false  )
    attachElements (sound ,shooterPed , 0, 0, 2 )
    setSoundMaxDistance(sound, 50)
    setElementDimension(sound,getElementDimension ( shooterPed ))
    setElementInterior(sound,getElementInterior( shooterPed ))
    return sound 
end
local weapons = {
[22] = "sounds/Colt45.wav",
--[id] = "sound name",
}
local pedSounds = {};
setWorldSoundEnabled(5,false) 
function onClientPlayerWeaponFire ( weapon )
    if weapons[weapon] then
        if isElement(pedSounds[source] ) then destroyElement(pedSounds[source] ) end 
        pedSounds[source] = Sound3D(source, weapons[weapon] )
    end 
end
addEventHandler ( "onClientPlayerWeaponFire", getRootElement(), onClientPlayerWeaponFire )

 

 

A good excercise I found is to explain myself colloquially what this does. Would you be so kind and correct me if I'm wrong?

1st function: "Sound3D".
My first guess is that, since there is no 'addEventHandler', the function will be applied as long as it is running and as soon as the player downloads it.
First, you set the wX, wY, and wZ coordinates equal to the muzzle of the weapon being held by the shooter. From that moment, MTA will know that those three values represent the respective x, y and z of the muzzle. The muzzle will be relative to the player, whom we'll call "shooterPed'. Then, you do the same by saying that the word "sound" is equal to the sound that we have to reproduce, in 'playSound3D' format, with the coords that you previously set, and a false bool for 'loop'. Continuing the conditions, you also set that the sound will be attached to the player's position (a little variation to the player's height), you set the max distance the sound can be heard from, and the dimension and interior, which will be taken from the player's (shooterPed) dimension and interior.
Is this correct?

What's the return sound for?

Also being applied as long as the resource is started and the player downloads it, you briefly set the sound to be played. You say that the weapons sound available as of this moment is for the Colt 45 (weapon ID = 22), and that the sound that will be played is the one called "Colt45.wav" at the given location (which is being taken from meta.xml) —if I were to add more weapons, I would need to repeat the 2nd function for each weapon—. You then equal 'PedSounds' to... nothing? And lastly, you disable the weapon sounds (5) of the world.
Right?

2nd function: "onClientWeaponFire (weapon)".
The parentheses are the first argument of the event handler 'onClientPlayerWeaponFire'. That means that whenever 'weapon' is fired, the function will be called. (Here's where I get stuck) first, you say that 'if weapons[weapon] then'; if true, then the next 'if' happens, which is the isElement and destroyElement. Why do you destroy this? From this point on, I can't translate what's happening. I can't understand "
pedSounds[source] = Sound3D(source, weapons[weapon] )". Lastly, you close all 'if' and the function, and set the event handler to trigger the 2nd function when the client shoots.
Clearly the 2nd function is where I'm having trouble at.

Questions:
- Is this server-side or client-side?
- In the 1st function, you said that "
local sound = playSound3D (sound3d,wX, wY, wZ, false )". Wouldn't you have to assign a value to 'sound3d'? How does the script know what 'sound3d' is equal to?
- What's the use for "local PedSounds = {}"? Why empty?
- Between so many '<word> = value', I get confused and need to reread to know what the word is equal to. I also get confused on when to use 'source', 'root', 'getRootElement(), 'localPlayer', 'client', etc. I just can't feel the difference.
- I have more questions, but they might be answered if the ones before are answered.

Also, thanks for being so sympathetic. And sorry for the random vent...

Edited by Moony
Link to comment

Alright, I'll answer some of the questions.

Why do you destroyElement before creating a new one? - Whenever a player shoots you delete the sound that was previously played and create a new one to avoid multiple sounds being created at once, basically overlapping each other when they shouldn't.

What is sound3d, why do you play from it when you didn't define it? - Look in the function, the function is named Sound3D then a table with "weapons" is created in which he posted the weapon 22, in this case the colt as well as the co-responding sound path to it. Now once you use the weapons [ weapon ] in the Sound3D the function itself will read the file path from the table that OP has posted.

Basically what he did was make a seperate function that is somewhat of a replacement for the "playSound3D" in a way that it is further extended to the point that it can actually read data from your table making it easier for you to just simply add new data to the table rather than editing the entire function with, let's say, for example, "elseif" statements where you'd check all possible weapons.

He does not need to define the sound3d variable because he already did so as a function arguement -  "function Sound3D ( shooterPed, sound3d )"

pedSounds is empty because it creates a new table, this way you can actually attach the source (in this case the shooting player) to the table so that each sound definition is unique, meaning multiple sounds won't be created under 1 variable which would cause multiple sounds being stuck to 1 variable as "destroyElement" would just destroy the latest defined sound to it and ignore all the sounds that were previously added to it. (see Lua's table definitions here to learn more about tables:
https://www.Lua.org/pil/3.6.html )


Basically all you need to do now to add more sounds is update the table that OP has posted, here's an example:

 

local weapons = {
[22] = "sounds/Colt45.wav",
[30] = "sounds/AK-47.wav",
  
}


This basically adds the AK-47 sound to the table as well, obviously you'd need the file to load from. After that the script will check if the shooting player has weapon ID 30, if so, it'll read from the table and play the sound from ID 30 which is defined in the [ ] tags.

Edited by Blast3r
  • Like 1
Link to comment
31 minutes ago, Blast3r said:

EDIT: Can someone tell me how to turn on the Lua editor here, wanted to show him a code example but no idea how to do it lol.

If you're talking about adding a code like several replies above, you can do so with the "<>" sign next to the text formatting. Another window will open, where you can simply copy and paste the code from Notepad++ to there. If it's too big, I advice you use the spoiler format (symbol is an eye) so the reply is compressed, yet accessible to the reader.

 

31 minutes ago, Blast3r said:

Why do you destroyElement before creating a new one? - Whenever a player shoots you delete the sound that was previously played and create a new one to avoid multiple sounds being created at once, basically overlapping each other when they shouldn't.

Got it. So "if isElement(pedSounds[source] ) then destroyElement(pedSounds[source] ) end" destroys the element before reproducing another element. In other words, he is destroying the original sound and then playing the custom sound.
To reproduce the custom sound, he is using "
pedSounds[source] = Sound3D(source, weapons[weapon]", where source = PedShooter, PedSounds = any unique sound, Sound3D = the function [being played to the source (shooterPed) and reproducing "weapon" (the first argument of  'onClientPlayerWeaponFire')]. What would 'weapon' be equal to, then?

 

31 minutes ago, Blast3r said:

What is sound3d, why do you play from it when you didn't define it? - Look in the function, the function is named Sound3D then a table with "weapons" is created in which he posted the weapon 22, in this case the colt as well as the co-responding sound path to it. Now once you use the weapons [ weapon ] in the Sound3D the function itself will read the file path from the table that OP has posted.

Basically what he did was make a seperate function that is somewhat of a replacement for the "playSound3D" in a way that it is further extended to the point that it can actually read data from your table making it easier for you to just simply add new data to the table rather than editing the entire function with, let's say, for example, "elseif" statements where you'd check all possible weapons.

He does not need to define the sound3d variable because he already did so as a function arguement -  "function Sound3D ( shooterPed, sound3d )"

pedSounds is empty because it creates a new table, this way you can actually attach the source (in this case the shooting player) to the table so that each sound definition is unique, meaning multiple sounds won't be created under 1 variable which would cause multiple sounds being stuck to 1 variable as "destroyElement" would just destroy the latest defined sound to it and ignore all the sounds that were previously added to it.

I'll have to repeat this to myself several times along with some testing to fully understand it, but I think I generally get it.

 

I went with someone a bit more simple before fully getting into the weapons: a simple script that plays a sound in the player's position (type="client").

function beatbox ()
	local bX, bY, bZ = getElementPosition (client)
	local beat = playSound3D ("beatboxF.mp3", bX, bY, bZ, false)
end
addCommandHandler ("beatbox", beatbox)

Meta has the file, the file works, but DB3 is saying that getElementPosition is nil, as well as 'vector3'.
Ok! Ok! It works! The sound is always coming from the player. Now I need to make sure if other players can hear it coming from me.
I used 'localPlayer' in place of 'client', and 'attachElements'. Why did 'localPlayer' worked?

Edited by Moony
Further testing.
Link to comment

He's actually deleting the custom sound to create a custom sound again so you don't get multiple sounds created at once, original sound is already deleted with the "setWorldSoundEnabled" code and no longer needs to be deleted again as it's done so when the resource is loaded to the client.

"Weapon" equals to weapon id which is defined in the weapons table, basically the event onClientWeaponFire ( weapon ) returns the weapon ID that's used by the player, so if for example the player has a colt-45 then the "weapon" variable will return 22, which you have a check for in the "weapons" table, the [22] in the tags.

"Client" is only used on serverside to get what client actually triggered the event, for more understanding of those please read the "predefined variables" which can be found on this link:
https://wiki.multitheftauto.com/wiki/Predefined_variables_list

 

Edited by Blast3r
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...