Jump to content

Recommended Posts

Bonjour,

 

https://community.multitheftauto.com/index.php?p=resources&s=details&id=6277

Le script fonctionne très bien, mais j'aimerais savoir comment faire en sorte que lorsqu'un zombie est équipé du sabre, qu'on puisse entendre les sons?

Car à priori, il n'y a que le joueur qui peu entendre les sons.. :/

 

Une second question, comment faire en sorte qu'une bat de Baseball (par exemple) puisse one shot un zombie?

 

Merci de votre aide. :)

 

 

Link to comment
  • Moderators

Wumbaloo qui répond plus vite que son ombre ... xD Un petit check rapide du code montre bien que c'est un playSound3D qui est utilisé et en plus tu n'as pas dû comprendre la question de LawrenceKnight, il a pas parlé d'un problème de position du son hein ! 9_9

Alors ce script a visiblement été réalisé par un novice qui n'a pas pensé que son script ne marcherai pas avec d'autres joueurs sur son serveur. Voilà la traduction strict du code (la partie son seulement):
* En tant que joueur, si je(1) tire avec une arme et que l'id de cette arme est égal à 8 (Katana), alors je joue pour moi(1) et en 3D un des 3 sons dispo à l'emplacement du bout de l'arme.
(1) Parce que c'est un script côté client = le joueur local

S'il avait eu une autre personne pour tester, il aurait remarqué que lorsqu'un 2ème joueur "tire" avec le katana, aucun son ait joué pour le 1er joueur.

Ma première idée pour le corriger rapidement était d'appeler la fonction jedi avec l'event onClientPedWeaponFire et d'utiliser source au lieu de localPlayer:

Quote

The source of this event is the ped who fired the weapon.

Mais en fait on peut pas parce que:

Quote

This does not trigger for projectiles based, or melee weapons.

oh :(
Bon bah du coup plan B, il faut séparer la partie (A)détection d'un tire au katana de la partie (B)jouer un des 3 sons à l'embout de l'arme du joueur responsable avec (A) => côté serveur (B) => côté client

Je te propose donc cet exercice car ça doit être dans tes cordes. Il te faudra la fonction triggerClientEvent pour que depuis le serveur tu puisses déclencher la fonction du son côté client (indice: ne renseigne pas l'option sendTo au début pour que ça le déclenche chez tous le monde.

Pour ta 2ème question:

Il suffit d'utiliser l'event onClientPedDamagetester si l'argument weapon vaut 5 (Batte), et si c'est le cas, tu killPed(source, attacker, weapon, bodypart) et ça devrait faire le taff.
En revanche un Player est considéré comme un Ped spécifique car contrôlé par un joueur donc ça va 1 shot les joueurs aussi (sauf s'ils sont dans la même team et que le friendly fire est désactivé). Donc en plus du check du weapon qui vaut 5, il faut rajouter un check pour vérifier si la source est un zombie, pour ça il faudra regarder dans la fonction qui spawn un zombie s'il y a un element data spécifique qu'on pourrait utiliser afin d'identifier de façon sûr que ça soit un zombie (genre si y a un setElementData(bidule, "isZombie", true) c'est bingo pour nous, il suffira de faire un if getElementData(source, "isZombie") then et la correction est torchée/terminée ^^)

Bon courage en attendant ton retour :)

Cordialement,
Citizen

Edited by Citizen
Link to comment

Etant moi aussi inexpérimenté j'ai quand même essayer mais sans résultat.. :/ 

Je n'ai pas peur d'avoir honte, alors je vais exposé ce que j'ai essayé de faire (même si je sais que j'ai fais pas mal de cochonneries):

côté client:

local JediSound = { "a.mp3", "b.mp3", "c.mp3" }

function sounds ( )
    local muzzleX, muzzleY, muzzleZ = getPedWeaponMuzzlePosition ( localPlayer )
    local px, py, pz = getElementPosition ( localPlayer )
    local weaponID = getPedWeapon ( localPlayer )
    local sound = playSound3D ( JediSound[ math.random( 1,#JediSound ) ], muzzleX, muzzleY, muzzleZ, false )
    setSoundMaxDistance ( sound, 40 )
end
addEvent( "PlaySound", true )
addEventHandler( "PlaySound", getRootElement(), sounds )

côté server:

function jedi ()
    if ( weaponID == 15 and isControlEnabled ( "fire" ) ) then
        triggerClientEvent ( "PlaySound", getRootElement() )
    end
end
bindKey ( "fire", "down", jedi )

 

En ce qui concerne ma deuxième question, je pense avoir bien fait, mais cela ne tue pas les zombies. :/ 

function killp ()
	if weaponID == 5 then
	    if (getElementData (source, "zombie") == true) then
        killPed(source, attacker, weapon, bodypart)
	   end
   end
end
addEvent( "onClientPedDamage", true )
addEventHandler ( "onClientPedDamage", killp )

 

Link to comment
  • Moderators
30 minutes ago, LawrenceKnight said:

Je n'ai pas peur d'avoir honte

Et t'as bien raison ! Ceux qui devraient avoir honte sont ceux qui disent: "j'ai essayé mais j'ai pas réussi, je montre pas ce que j'ai fait peux-tu le faire à ma place ?". Souvent ils n'y ont passé que 10 minutes max, n'ont pas envie d'apprendre et veulent quand même sortir un serveur ! LOL

J'apprécie que tu es testé toi-même de faire les corrections vu le temps que j'ai passé à tout détailler (pourquoi, comment) avec le raisonnement pour bien visualiser.
Et tu vas être content, tu es vraiment pas loin !! C'est quasiment tout bon !

addEvent( "PlaySound", true ) -- Ok
addEventHandler( "PlaySound", getRootElement(), sounds ) -- Ok

Nickel, c'est ce qu'il fallait faire, créer un event qu'on peut trigger du côté serveur (true) et attaché la fonction sounds à cet event. Juste je changerai le nom de l'event pour éviter un conflit avec une autre ressource. Exemple: onLaserSaberSwing (Il faut se lever de bonne heure pour trouver une autre ressource qui utilise ce nom sur ton serveur haha)
 

function jedi ( player ) -- bindKey envoi le joueur qui a appuyé en 1er paramètre, il faut le "receptionner"
    -- Ici tu avais oublié de ramener la fonction qui récupère l'arme actuelle du joueur:
    local weaponID = getPedWeapon ( player ) -- On récupère l'arme du joueur qui a "fire"
    if ( weaponID == 15 and isControlEnabled ( "fire" ) ) then -- Ok pour la cane
        triggerClientEvent ( "PlaySound", player ) -- Ici on met le joueur en source de l'event à la place car root = tout le monde (on le récupérera côté client pour jouer le son à la bonne position)
    end
end
bindKey ( "fire", "down", jedi ) -- Ok

 

local JediSound = { "a.mp3", "b.mp3", "c.mp3" }

function sounds ( )
    local muzzleX, muzzleY, muzzleZ = getPedWeaponMuzzlePosition ( source ) -- remplacer par source car on veut pas le joueur local mais bien celui qui a tiré
    -- local px, py, pz = getElementPosition ( localPlayer ) -- Heuuu px, py, pz ne sont pas utilisé, un oubli de l'auteur. A supprimer !
    -- local weaponID = getPedWeapon ( source ) -- plus besoin de weaponID ici, on n'en a besoin que du côté serveur maintenant. A supprimer !
    local sound = playSound3D ( JediSound[ math.random( 1,#JediSound ) ], muzzleX, muzzleY, muzzleZ, false )
    setSoundMaxDistance ( sound, 40 )
end
addEvent( "PlaySound", true )
addEventHandler( "PlaySound", getRootElement(), sounds )

Et là on devrait retrouver le même fonctionnement d'origine mais qui marche également si d'autres joueurs donnent des coups avec le sabre laser. Mais le problème des sabres lasers des zombies qui ne font pas de bruits est toujours là (ouai j'ai oublié d'en parler dans mon post précédent, mais de toute façon il fallait faire ça avant).

Une fois les corrections fonctionnelles, je ne vois pas d'autre solution que de faire le même triggerClientEvent mais dans la fonction attack de la ressource zombie en mettant le zombie en source de l'event (et c'est tout, ça marchera direct normalement).


Pour la 2ème question:

Ultra proche du bon résultat ! Juste il te manquait la "réception" des argument que t'envoie l'event onClientPedDamage et il ne faut pas faire de addEvent pour les events fournit par MTA.

function killp ( attacker, weapon, bodypart ) -- on doit réceptionner ce que nous envoie l'event pour les utiliser dans la fonction (exception pour 'source')
    if weapon == 5 then -- Du coup comme je l'ai nommé weapon pour le killPed, je change le nom de la variable à tester
        if (getElementData (source, "zombie") == true) then -- C'est juste mais comme c'est un boolean et qu'il n'y a qu'un test, on peut raccourcir à: if getElementData(source, "zombie") then
            killPed(source, attacker, weapon, bodypart)
        end
    end
end
-- addEvent( "onClientPedDamage", true ) -- Event MTA. A supprimer !
addEventHandler ( "onClientPedDamage", getRootElement(), killp ) -- manquait le 2ème argument (= qui peut en être la source)

 

Cordialement,
Citizen

Link to comment

Super! 

Mais j'ai des problèmes pour les deux.

En fait lorsque j'applique le corrigé, dans la console ça m'indique: "WARNING: lightsaber\server.lua:7: Bad argument @ 'bindkey' [Expected player at argument 1, got string 'fire']" :( 

Et puis concernant les dégâts avec la batte, ça ne tue pas les zombies.. :( 

Link to comment
  • Moderators

Arf j'avais zappé que la version server du bindKey doit avoir un argument player obligatoire en 1er (je le pensais optionnel).
Fait le bind lorsque le joueur se connecte:

addEventHandler("onPlayerJoin", root, function () -- root = raccourci de getRootElement(), et je donne la fonction directement en argument en même temps que je la défini, donc elle ne peut pas porter de nom (on parle de fonction anonyme)
    bindKey ( source, "fire", "down", jedi )
end)

 

Pour le 2 il faut débuguer, as-tu une erreur affichée via /debugscript 3 ? Si tu outputChatBox weapon, quel valeur s'affiche dans le chat ? La même chose pour getElementData (source, "zombie") (pour afficher un boolean, il faut le passer à la fonction tostring d'abord, ce qui n'est pas nécessaire pour les nombres) ?

Edited by Citizen
Link to comment

Donc pour le bind j'ai juste à remplacer le "bindKey ( source, "fire", "down", jedi )" du côté server?

Si c'est le cas, dans la console je n'ai plus le Bad Argument mais le son ne se joue toujours pas, pourtant je prend la bonne arme..

 

Pour le /debugscript 3 apparemment rien ne s'affiche.. Et je n'ai pas très bien compris comment faire le reste.. :( 

 

 

 

Link to comment
  • Moderators
6 hours ago, LawrenceKnight said:

Si c'est le cas, dans la console je n'ai plus le Bad Argument mais le son ne se joue toujours pas, pourtant je prend la bonne arme..

Ouai en fait il faut se reconnecter et je pense que ça devrait marcher. J'ai oublié le cas où on restart la ressource et que des joueurs restent sur le serveur. Le bindKey n'est rejoué vu qu'il n'est que sur le onPlayerJoin.

Pour le 2 je pensais à ça:

function killp ( attacker, weapon, bodypart )
    outputChatBox(weapon) -- là
    if weapon == 5 then
        outputChatBox(tostring(getElementData (source, "zombie"))) -- et là
        if (getElementData (source, "zombie") == true) then
            killPed(source, attacker, weapon, bodypart)
        end
    end
end
addEventHandler ( "onClientPedDamage", getRootElement(), killp )

 

Edited by Citizen
Modifications plus visibles
Link to comment

Oui, j'ai déjà pensé à me reconnecter justement et ça ne fonctionne pas. :'( 

D'ailleurs dans la console cette fois-ci ça m'affiche "WARNING: lightsaber\server.lua:3: Bad argument @ 'IsControlEnabled' [Expected player at argument 1, got string 'fire']"

 

Et pour leoutputchatbox ça m'affiche du 7, du 5 ou false.

C'est grave docteur? :o 

 

Link to comment
  • Moderators
28 minutes ago, LawrenceKnight said:

"WARNING: lightsaber\server.lua:3: Bad argument @ 'IsControlEnabled' [Expected player at argument 1, got string 'fire']"

La version server de cette fonction doit prendre un joueur en 1er argument, rajoute le.

30 minutes ago, LawrenceKnight said:

Et pour leoutputchatbox ça m'affiche du 7, du 5 ou false.

C'est grave docteur? :o

Tu vois pas le problème ??

7 = tu as tapé avec la canne (on s'en fou)

5 = tu a tapé avec la batte mais

false = pas un zombie. Si tu as vraiment tapé un zombie, ton test pour savoir si c'est un zombie n'est pas bon. Peux-tu montrer le code que t'as trouvé dans la ressource zombie qui t'a indiqué que ça serait bon ? (Si tu veux que ça oneshot tout le monde (zombies, autres joueurs) retire juste ce test).

 

Link to comment
function Zomb_Idle (ped)
	if isElement(ped) then
		if ( getElementData ( ped, "status" ) == "idle" ) and ( isPedDead ( ped ) == false ) and (getElementData (ped, "zombie") == true) then
			local action = math.random( 1, 6 )
			if action < 4 then -- walk a random direction
				local rdmangle = math.random( 1, 359 )
				setPedRotation( ped, rdmangle )
				setPedAnimation ( ped, "PED", "Player_Sneak", -1, true, true, true)
				setTimer ( Zomb_Idle, 7000, 1, ped )
			elseif action == 4 then -- get on the ground
				setPedAnimation ( ped, "MEDIC", "cpr", -1, false, true, true)
				setTimer ( Zomb_Idle, 4000, 1, ped )
			elseif action == 5 then -- stand still doing nothing
				setPedAnimation ( ped )
				setTimer ( Zomb_Idle, 4000, 1, ped )
			end
		end
	end
end

Voici un exemple de code que j'ai trouvé.

Link to comment
  • Moderators

Effectivement, ton raisonnement est bon du coup mais il y a visiblement un truc qui cloche. Les element data ne sont pas cloisonnés par ressource, c'est à dire l'ajout/modification d'un element data dans la ressource zombie est assurément visible/récupérable dans une autre ressource donc ça aurait dû marcher. La seul possibilité que je vois actuellement c'est que tu regardes le code d'une ressource zombie qui n'est pas celle qui tourne sur ton serveur. Mais je pense que tu n'en as pas 36 milles...

Peux-tu trouver et copier le code du spawn zombie ?

On va vérifier qu'il le met bien cet element data à true et on va rajouter un outputChatBox pour vérifier ingame que c'est bien cette fonction (et donc cette ressource) qui spawn actuellement les zombies sur ton serveur.

Link to comment

Si si, le script tourne bien sur mon serveur.

Je pense que c'est ça

function outbreak(startedResource)
	newZombieLimit = get("" .. getResourceName(startedResource) .. ".Zlimit")
	if newZombieLimit ~= false then
		if newZombieLimit > ZombieLimit then 
			newZombieLimit = ZombieLimit
		end
	else
		newZombieLimit = ZombieLimit
	end
	WoodTimer = setTimer ( WoodSetup, 2000, 1) -- CHECKS FOR BARRIERS
	if startedResource == getThisResource() then
--		call(getResourceFromName("scoreboard"), "scoreboardAddColumn", "Zombie kills") --ADDS TO SCOREBOARD
		local allplayers = getElementsByType ( "player" )
		for pKey,thep in ipairs(allplayers) do
			setElementData ( thep, "dangercount", 0 )
		end	
		local alivePlayers = getAlivePlayers ()
		for playerKey, playerValue in ipairs(alivePlayers) do
			setElementData ( playerValue, "alreadyspawned", true  )
		end
		if ZombieSpeed == 2 then
			MainTimer1 = setTimer ( setangle, 200, 0) -- KEEPS ZOMBIES FACING THE RIGHT DIRECTION (fast)
		else
			MainTimer1 = setTimer ( setangle, 400, 0) -- KEEPS ZOMBIES FACING THE RIGHT DIRECTION
		end
		MainTimer3 = setTimer ( clearFarZombies, 3000, 0) --KEEPS ALL THE ZOMBIES CLOSE TO PLAYERS	
		if ZombieStreaming == 1 then
			MainTimer2 = setTimer ( SpawnZombie, 2500, 0 ) --Spawns zombies in random locations
		elseif ZombieStreaming == 2 then
			MainTimer2 = setTimer ( SpawnpointZombie, 2500, 0 ) --spawns zombies in zombie spawnpoints
		end
	end
end
addEventHandler("onResourceStart", getRootElement(), outbreak)

 

Aucun problème Wumbaloo. :) 

if ( weaponID == 15 and isControlEnabled ( player,"fire" ) ) then

C'est bien ce qu'il fallait faire pour l'argument? (j'ai rajouter le "player" avant le "fire")

Link to comment
  • Moderators

Non je cherchais à voir la fonction qui spawn les zombies et d'après la ligne 28, il y a une fonction qui s'appelle SpawnZombie

3 hours ago, LawrenceKnight said:

C'est bien ce qu'il fallait faire pour l'argument?

oui

 

Edited by Citizen
Link to comment

Donc c'est ça alors:

function SpawnZombie ()
	local pacecount = 0
	while pacecount < 5 do	--4 ZOMBIES AT A TIME TO PREVENT FPS DROP
		if (table.getn( everyZombie )+pacecount < newZombieLimit ) and (ZombieStreaming == 1) then	
			local xcoord = 0
			local ycoord = 0
			local xdirection = math.random(1,2)
			if xdirection == 1 then
				xcoord = math.random(15,40)
			else
				xcoord = math.random(-40,-15)
			end
			local ydirection = math.random(1,2)
			if ydirection == 1 then
				ycoord = math.random(15,40)
			else
				ycoord = math.random(-40,-15)
			end
			local liveplayers = getAlivePlayers ()
			if (table.getn( liveplayers ) > 0 ) then
				local lowestcount = 99999
				local lowestguy = nil
				for PKey,thePlayer in ipairs(liveplayers) do
					if isElement(thePlayer) then
						if (getElementData (thePlayer, "dangercount")) and (getElementData(thePlayer, "zombieProof") ~= true) and (getElementData(thePlayer, "alreadyspawned" ) == true) then
							if (getElementData (thePlayer, "dangercount") < lowestcount) then
								local safezone = 0
								local gx, gy, gz = getElementPosition( thePlayer )
								local allradars = getElementsByType("radararea")
								for theKey,theradar in ipairs(allradars) do
									if getElementData(theradar, "zombieProof") == true then
										if isInsideRadarArea ( theradar, gx, gy ) then
											safezone = 1
										end
									end
								end
								if safezone == 0 then
									lowestguy = thePlayer
									lowestcount = getElementData (thePlayer, "dangercount")
								end
							end
						end
					end
				end
				pacecount = pacecount+1
				if isElement(lowestguy) then
					triggerClientEvent ( "Spawn_Placement", lowestguy, ycoord, xcoord )
				else
					pacecount = pacecount+1
				end
			else
				pacecount = pacecount+1
			end
		else
			pacecount = pacecount+1
		end
	end
end

 

Ah donc c'est bien ce que j'ai fais, mais toujours pas.. j'ai l'impression qu'on peut rien faire pour les sons.. :( 

Link to comment
  • Moderators

Ok alors j'ai reçu une notif par mail du message de Wumbaloo mais pas pour celui de LawrenceKnight de Jeudi ...
Désolé de ne pas t'avoir répondu du coup.

Bon du coup on dirait une vieille version du mode DayZ mais j'ai réussi à trouver des traces de codes sur des forums et en gros il y a une fonction qui s'appelle RanSpawn_Z qui crée le zombie via un 

local zomb = createPed( tonumber( ZombiePedSkins[randomZskin] ), gx, gy, gz )

Puis il fait un

setElementData ( zomb, "zombie", true  )

Peux-tu confirmer que tu es bien ça de ton côté ?

Si c'est bien le cas, notre test devrait être bon et notre outputChatBox(tostring(getElementData (source, "zombie"))) aurait dû nous afficher true plutôt que false dans la chatbox.

Peux-tu refaire le test avec ce code modifié (histoire de lever tout doute sur qui affiche quoi ?):

function killp ( attacker, weapon, bodypart )
    outputChatBox("weapon ? "..weapon) -- là
    if weapon == 5 then
        outputChatBox("zombie ? "..tostring(getElementData (source, "zombie"))) -- et là
        if (getElementData (source, "zombie") == true) then
            outputChatBox("yes ok instakill it !")
            killPed(source, attacker, weapon, bodypart)
        end
    end
end
addEventHandler ( "onClientPedDamage", getRootElement(), killp )


########################################

Pour le son des sabres lasers, je pense que ceci devrait marcher:

-- Server
function jedi ( player )
    local weaponID = getPedWeapon ( player )
    if ( weaponID == 15 and isControlEnabled ( "fire" ) ) then
        triggerClientEvent ( "onLaserSaberSwing ", player )
    end
end

-- Exécuté au démarrage du gamemode pour tous les joueurs déjà co:
for _, player in pairs(getElementsByType("player")) do
	bindKey ( player, "fire", "down", jedi )
end

-- Exécuté pour chaque joueur qui se connecteront plus tard:
addEventHandler("onPlayerJoin", root, function ()
    bindKey ( source, "fire", "down", jedi )
end)
-- Client
local JediSound = { "a.mp3", "b.mp3", "c.mp3" }

function onLaserSaberSwingFunc ( )
    local muzzleX, muzzleY, muzzleZ = getPedWeaponMuzzlePosition ( source )
    local sound = playSound3D ( JediSound[ math.random( 1,#JediSound ) ], muzzleX, muzzleY, muzzleZ, false )
    setSoundMaxDistance ( sound, 40 )
end
addEvent( "onLaserSaberSwing ", true )
addEventHandler( "onLaserSaberSwing ", root, onLaserSaberSwingFunc )

Et pour un zombie, il faudra modifier le code de ton DayZ à l'endroit qui le fait attaquer et faire ceci en testant d'abord qu'il a bien le sabre laser en main:

triggerClientEvent ( "onLaserSaberSwing ", laVariableDuZombie )

 

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...