Jump to content

[HELP] Power-Up Invisibilité


Trinx

Recommended Posts

Bonjour / Bonsoir,

Moi et un ami travaillons sur un panel race classique, et nous sommes bloqué sur un power up, l'invisibilité, nous n'arrivons pas à rendre le véhicule invisible après des dizaines de tentatives.. uniquement le joueur le deviens.

CODE :

----------------Client:

   addEventHandler ("onClientGUIClick", getRootElement(), 
  
function(button, state, absoluteX, absoluteY) 
  
if ( source ==  buyInvisible2 ) then  
  
triggerServerEvent("buyInvisible2",getLocalPlayer())  
  
  
end  
  
end  
) 

-------------- Server:

addEvent("buyInvisible2",true) 
  
addEventHandler("buyInvisible2",root, 
  
function() 
    setElementData(source, "invVEH", true) 
    local sourceVeh = getPedOccupiedVehicle(source) 
    setElementAlpha(sourceVeh, 0) 
    setTimer ( setElementAlpha, 70000, 1, source, 500, true) 
    setElementData(source, "invVEH", false) end, 70000, 1, true) 

Nous avons créé 2 event, un pour le joueur ( fonctionnel ), un autre pour le véhicule ( erreur ).

Le debugscript :

kauv.png

Si vous avez besoin de la partie du joueur invisible, dites le.

Merci d'avance!

Link to comment
  • Moderators

Depuis quand un addEventHandler accepte ces arguments après la fonction ?

 70000, 1, true 

Vous êtes dans la même situation que RoRo76 en ce moment. Vous essayez d'utiliser une forme avancée de coding qui permet d'utiliser des fonctions anonymes mais vers la fin, vous êtes complètement perdu et mettez n'importe quoi.

Voici la définition du addEventHandler sous sa forme minimale (sans les arguments optionnels):

bool addEventHandler ( string eventName, element attachedTo, function handlerFunction )

Il lui faut donc:

en argument 1 => le nom de l'event (ici buyInvisible2)

en argument 2 => qui peut être la source de cet event pour exécuter la fonction en argument 3 (ici root , qui équivaut à "tout")

et en argument 3 => la fonction à exécuter lorsque cet event sera appelé/lancé. On peut lui donner soit le nom de la fonction, soit la fonction directement (en lui donnant la fonction directement, on doit lui donner une fonction anonyme).

Voici 2 codes équivalents mais seul le second utilise une fonction anonyme:

function maFunction() 
    --Instructions ici 
end 
addEventHandler( "buyInvisible2", root, maFonction) 

addEventHandler( "buyInvisible2", root, function () 
    --Instructions ici 
end) 

Cette deuxième notation est plus complexe et déroutante que la première plus lisible. Je vous conseil donc de n'utiliser que cette première version. Après 4 ans, j'utilises toujours cette notation car plus lisible est donc plus facile à reprendre/maintenir par la suite. Je n'utilise la 2ème que si la fonction est vraiment petite (en nombres d'instructions).

Dans votre code, tout part en cacahuète après la ligne 9. Visez toujours la lisibilité, n'hésitez pas à séparer en plusieurs fonctions. Voici la correction que je propose (vous pouvez gardez le client tel qu'il est):

addEvent("buyInvisible2",true) 
function startInvisible() 
    setElementData(source, "invVEH", true) 
    local sourceVeh = getPedOccupiedVehicle(source) 
    setElementAlpha(sourceVeh, 0) 
    --on appel stopInvisible après 70 secondes en lui donnant le joueur en argument 1 
    setTimer(stopInvisible, 70000, 1, source) 
end 
addEventHandler("buyInvisible2", root, startInvisible) 
  
function stopInvisible( thePlayer ) 
    setElementAlpha(thePlayer, 255) 
    setElementData(thePlayer, "invVEH", false) 
    local veh = getPedOccupiedVehicle(thePlayer) 
    setElementAlpha(veh, 255) 
end 

N'hésitez pas si vous avez d'autres question où si je n'ai pas été assez précis sur certains points évoqués dans ce topic.

Link to comment
  • Moderators

Hummm ce n'est pas normal du tout, car le wiki spécifie bien:

This can be a player or a vehicle.

Est-ce que c'est bien un véhicule du jeu ou un véhicule moddé ? (je ne suis pas sûr qu'il y ait un lien)

Si c'est un véhicule moddé, essayez avec un véhicule normal du jeu.

Si vous avez activé des shadders qui influent sur la brillance des textures (eau, sol, véhicules etc), essayez de les désactiver.

J'ai aussi oublié dans ma correction de mettre l'alpha du joueur à 0, mais il semblerai qu'il prenne automatiquement l'alpha de son parent. Essayez donc ceci et dites moi ce qui s'affiche dans la chatbox (F8 pour pouvoir copier/coller):

addEvent("buyInvisible2",true) 
function startInvisible() 
    setElementData(source, "invVEH", true) 
    local sourceVeh = getPedOccupiedVehicle(source) 
    setElementAlpha(source, 0) --oublié mais surement sans importance 
    setElementAlpha(sourceVeh, 0) 
    testingParentAlpha(sourceVeh) 
    --on appel stopInvisible après 70 secondes en lui donnant le joueur en argument 1 
    setTimer(stopInvisible, 70000, 1, source) 
end 
addEventHandler("buyInvisible2", root, startInvisible) 
  
function stopInvisible( thePlayer ) 
    setElementAlpha(thePlayer, 255) 
    setElementData(thePlayer, "invVEH", false) 
    local veh = getPedOccupiedVehicle(thePlayer) 
    setElementAlpha(veh, 255) 
end 
  
function testingParentAlpha( elem ) 
    outputChatBox( "== testingParentAlpha ==" ) 
    do 
        outputChatBox( "elem: "..tostring(getElementType( elem )) ) 
        outputChatBox( "alpha: "..tostring(getElementAlpha( elem )) ) 
        elem = getElementParent() 
        outputChatBox( "==" ) 
    while (elem ~= nil) 
    outputChatBox( "== Fin ==" ) 
end 

Link to comment
  • Moderators

Ouai alors j'aimerai que vous fassiez plus attentions à ce que vous faites :evil:

Je vous avez dit de garder le client tel qu'il était alors que vous avez changé cette ligne (client-side):

triggerServerEvent("buyInvisible2",getLocalPlayer()) 

en ceci:

triggerServerEvent("buyInvisible",getLocalPlayer()) 

et tout ça sans me prévenir ni réfléchir aux conséquences.

Je suis d'accord pour renommer l'event mais dans ce cas il faut aussi le renommer server-side ... Enfin moi ça me parait logique perso.

Donc renommer les 2 occurrences du côté serveur pour que mon code soit bien exécuté.

Vous pouvez aussi utiliser la variable cachée localPlayer du côté client uniquement. C'est la même chose que de faire getLocalPlayer().

triggerServerEvent("buyInvisible", localPlayer) 

Voici une liste des variables prédéfinis disponibles dans les fichiers du côté client (client only), du côté serveur (server only) ou des deux côtés (shared):

https://wiki.multitheftauto.com/wiki/Pre ... ables_list

Link to comment
  • Moderators

Alors dans ce cas, pourquoi c'est seulement maintenant que tu nous en informe ?? On ne connait pas ton code je te le rappel !

Et pourquoi en avoir fait 2 différents ?! 1 seul trigger suffit largement. J'ai donné un code pour l'event "buyInvisible2" qui est censé parfaitement marcher.

Link to comment
  • Moderators

Hummmm, juste pour être sûr, on est bien d'accord que le joueur appuis sur un bouton et ça le rend invisible lui ET sa voiture en même temps et pour seulement 70 secondes ? oui ?

Sinon est-ce qu'il y a 2 boutons différents, l'un pour le joueur et l'autre pour le véhicule ? Si oui quel est l'intérêt de rendre l'un ou l'autre invisible séparément alors que c'est un serveur Race ?!

Merci de m'éclaircir sur ce point.

Link to comment
  • Moderators

Oui donc dans ce cas, mon code est correct et suffisant, à part qu'il faut renommer l'event en "buyInvisible2" en "buyInvisible" que ce soit du côté client ou du côté serveur.

Il n'y aura qu'un seul triggerServerEvent "attaché" à un seul bouton.

Je te remet le code côté serveur au cas où (j'ai déjà remplacé le nom de l'event):

addEvent("buyInvisible",true) 
function startInvisible() 
    setElementData(source, "invVEH", true) 
    local sourceVeh = getPedOccupiedVehicle(source) 
    setElementAlpha(source, 0) 
    setElementAlpha(sourceVeh, 0) 
    --on appel stopInvisible après 70 secondes en lui donnant le joueur en argument 1 
    setTimer(stopInvisible, 70000, 1, source) 
end 
addEventHandler("buyInvisible", root, startInvisible) 
  
function stopInvisible( thePlayer ) 
    setElementAlpha(thePlayer, 255) 
    setElementData(thePlayer, "invVEH", false) 
    local veh = getPedOccupiedVehicle(thePlayer) 
    setElementAlpha(veh, 255) 
end 

Pour cacher le nametag, le gamemode race ne te fournit aucune fonction pour le faire, il va falloir que tu édites toi même le gamemode.

Pour t'orienté, il va falloir que tu rajoute une 3ème condition à la ligne 41 du fichier nametags.lua qui devrait ressemblé à cela:

if not isPedInVehicle(player) or isPlayerDead(player) then break end 

L'instruction break permet d'arrêter la boucle while juste au-dessus et permet donc de passer directement au joueur suivant.

Donc cette ligne de code signifie:

Si le joueur n'est pas dans un véhicule OU s'il est mort alors, on passe au joueur suivant (donc on n'affiche pas son nametag avec sa barre de vie qui sont les instructions qui suivent).

Donc toi il te faut rajouter un 2ème "OU" pour que ça fasse en français:

Si le joueur n'est pas dans un véhicule OU s'il est mort OU s'il est invisible alors, on passe au joueur suivant.

Mais tu ne feras ça que lorsque notre code fonctionnera correctement.

Tiens moi au courant.

Cordialement,

Citizen

Link to comment

Presque parfait, mais un joueur peux quand même acheter Invisible, même si il n'a pas l'argent nécessaire, il deviens invisible, et le message : "Tu n'as pas assez d'argent" apparaît. Et aucun message debugscript..

J'profite pour ajouter une question : Je veux créer un barril qui spawn derrière le joueur, quand j'essaye d'ajouter aux coordonnées X, Y, Z. comment dire exemple :

Je tourne à gauche, il spawn à droite, je tourne à droite, il spawn à gauche, je reste droit, il spawn derrière, je vais dans le côté inverse, il spawn devant moi.

( Je précise que j'ai essayé, mais j'ai supprimé le code )

Donc quelle est le moyen d'le spawn derrière la voiture, peu importe la position du véhicule?

Link to comment
  • Moderators
le message : "Tu n'as pas assez d'argent" apparaît.

Il sort d'où ce message ?! Trouve lequel il s'agit dans ton code en essayant de modifier le texte et colle moi la fonction dans laquelle il est. Car effectivement, dans mon code que je t'ai passé, il n'y a aucune gestion de l'argent etc. Donc si tu veux lui retirer l'argent à l'achat et l'empêcher d'acheter quand il n'as plus assez d'argent, c'est dans la fonction startInvisible() qu'il faut le faire et pas ailleurs !

Il doit y avoir qu'un seul

addEventHandler( "buyInvisible", ... 

dans tout ton code serveur.

Pour ta deuxième question, il faut utiliser de la trigonométrie afin de passer du repère terrestre (de la map de gta) au repère du véhicule. (Je te laisse vérifier sur google ce qu'est un repère en 3D)

Mais en gros tu dois positionner le baril à -5Y (environ) sur le repère local du véhicule et non pas sur le repère de la map qui lui ne bouge jamais.

Je t'ai fait une petite fonction avec du code que j'ai retrouvé dans mes affaires:

function setElementPositionOnLocalAxes( element, reference, angle, distance ) 
    local x, y, z = getElementPosition( reference ) 
    local _, _, rz = getElementRotation( reference ) 
    local a = math.rad(rz) 
    x = x + distance*math.deg(math.sin(-a)) 
    y = y + distance*math.deg(math.cos(-a)) 
    setElementPosition( element, x, y, z ) 
end 

Son utilisation est simple:

Arguments:

element - l’élément que tu veux placer à un certains endroit (ici ton baril)

reference - l’élément qui va servir de référence (ici ton véhicule)

angle - la rotation en degré qui va définir vers ou déplacer l’élément en argument 1 (0=vers l'avant, 90=vers la droite, 180=vers l'arrière et 270=vers la gauche). Donc pour toi 180

distance - bah tout simplement la distance qui doit séparer le milieu de la reference (ici, du véhicule) et l'element que tu places.Si tu mets 0, le baril va se placer en plein milieu du véhicule ce qui n'est pas une bonne idée :lol:

Donc essaye 5 et puis si c'est trop court, augmente un peu. En tout cas prends bien en compte les longs véhicules, histoire qu'ils ne se retrouvent pas avec un baril en plein dans le coffre :D.

En attendant ta réponse.

Cordialement,

Citizen

Link to comment

Bon alors, je vais passer pour un c**, mais j'pas bien compris, on fais un truc de ce genre? :

addEvent ("buyBarrel", true) 
function setElementPositionOnLocalAxes( element, reference, angle, distance ) 
  local Barril = createObject ( 1225, 0, 0, 0 ) 
  local sourceVeh = getPedOccupiedVehicle(source) 
    local x, y, z = getElementPosition( sourceVeh ) 
    local _, _, rz = getElementRotation( sourceVeh ) 
    local a = math.rad(rz) 
    x = x + 5*math.deg(math.sin(-a)) 
    y = y + 5*math.deg(math.cos(-a)) 
    setElementPosition( Barril, x, y, z ) 
end 
addEventHandler("buyBarrel", root, setElementPositionOnLocalAxes) 

PS : Pour l'invisibilité, c'est bon, c'était juste une erreur de frappe, j'ai mal placé la gestion d'argent :oops:

Link to comment
  • Moderators

Ah nan ! C'est une fonction que tu dois utiliser comme si c'était une fonction MTA comme le createObject par exemple :mrgreen:

Donc remet ma fonction comme je te l'ai donné, et ne modifie rien à l'intérieur ! Je te la redonne ici:

function setElementPositionOnLocalAxes( element, reference, angle, distance ) 
    local x, y, z = getElementPosition( reference ) 
    local _, _, rz = getElementRotation( reference ) 
    local a = math.rad(rz) 
    x = x + distance*math.deg(math.sin(-a)) 
    y = y + distance*math.deg(math.cos(-a)) 
    setElementPosition( element, x, y, z ) 
end 

Tu colles cette fonction dans n'importe quel fichier Lua du côté serveur (car c'est de ce côté que tu vas en avoir besoin)

Voici un exemple d'utilisation de ma fonction qui je pense dois convenir parfaitement pour ton code:

addEvent ("buyBarrel", true) 
function buyBarrel() 
    local barrel = createObject ( 1225, 0, 0, 0 ) 
    local vehicle = getPedOccupiedVehicle( source ) 
    setElementPositionOnLocalAxes( barrel, vehicle, 180, 5 ) 
end 
addEventHandler("buyBarrel", root, buyBarrel) 

Voilà, c'est pas compliqué et c'est une fonction que tu pourras réutiliser si jamais tu as besoin :)

Cordialement,

Citizen

Link to comment

( Je vais être élu le mec le plus dérangeant du forum en terme d'aide là.. )

Bon alors, aucun message d'erreur sur le debugscript, j'ai vérifié, les Events sont bien placé, pas d'erreur normalement..

Quand je clique sur le bouton du Barril, ça le spawn pas, rien, nada :|

Link to comment
  • Moderators

Essaye ça et dit moi si le message "barrel spawned !" s'affiche dans la chatbox (le barril devrait peut être spawn au-dessus de ta voiture aussi)

addEvent ("buyBarrel", true) 
function buyBarrel() 
    local vehicle = getPedOccupiedVehicle( source ) 
    local x, y, z = getElementPosition( vehicle ) 
    local barrel = createObject ( 1225, x, y, z+2 ) 
    outputChatBox( "barrel spawned !" ) 
    setElementPositionOnLocalAxes( barrel, vehicle, 180, 5 ) 
end 
addEventHandler("buyBarrel", root, buyBarrel) 

Link to comment
  • Moderators

Alors soit c'est une erreur de coordonnées donc une erreur dans mes calculs, soit le model que t'utilise n'est pas le bon et est peut être invisible.

Tu vois le baril nul part ? t'as bien regardé ?

Je vais tester de mon côté et voir ce qu'il se passe. (Mais réponds quand même a mes question ^^)

EDIT: Alors si je commente cette ligne:

setElementPositionOnLocalAxes( barrel, vehicle, 180, 5 ) 

Le baril apparaît bien au-dessus du véhicule c'est donc mon calcul de trigo qui est erroné, je vais corriger ça :/

EDIT 2: C'était bien un problème dans ma fonction :lol:

Premièrement, je n'utilisais pas l'argument angle qu'on lui donnait, donc le baril spawnait toujours devant le véhicule peut importe l'angle qu'on lui donnait.

Et deuxièmement, la distance qu'on lui donnait n'était pas interprété en mètres, donc j'ai divisé par 100 et ça a l'air de correspondre aux mètres dans le jeu.

Donc pour résumer, ma fonction déplaçait le baril toujours droit devant le véhicule et en plus à 500 mètres environ (donc super loin).

  
addEvent ("buyBarrel", true) 
function buyBarrel() 
    local vehicle = getPedOccupiedVehicle( source ) 
    local x, y, z = getElementPosition( vehicle ) 
    local barrel = createObject ( 1225, x, y, z ) 
    setElementPositionOnLocalAxes( barrel, vehicle, 180, 8 ) 
end 
addEventHandler("buyBarrel", root, buyBarrel) 
  
function setElementPositionOnLocalAxes( element, reference, angle, distance ) 
    local x, y, z = getElementPosition( reference ) 
    local _, _, rz = getElementRotation( reference ) 
    local a, distance = math.rad(rz+angle), distance/100 
    x = x + distance*math.deg(math.sin(-a)) 
    y = y + distance*math.deg(math.cos(-a)) 
    setElementPosition( element, x, y, z ) 
end 

PS: J'ai aussi un peu augmenté la distance, je l'ai mise à 8 unités car dans le jeu c'est plutôt court, dans mes tests, j'étais en moto et c'était trop près. Donc en voiture, j'aurais fait explosé le baril direct ! :D

Link to comment

Merci! Ça fonctionne parfaitement :)

Maintenant, une dernière question pour clore mon problème, pour les camions, comment je peux faire pour que la distance change en fonction des types de véhicules? if (VehID = 1 or 2 or 3 or 4, etc..) then..., ou un truc du genre?

EDIT : En testant, j'ai découvert un autre problème.. le barril respawn, même après qu'il a explosé..

et 2 : Comment modifier la hauteur? il est pas TOUT-A-FAIT au sol..

Link to comment
  • Moderators
comment je peux faire pour que la distance change en fonction des types de véhicules? if (VehID = 1 or 2 or 3 or 4, etc..) then..., ou un truc du genre?

Effectivement, tu vas faire un truc de ce genre mais pour faire plus pro, je te conseil de faire une fonction à part que tu va nommer isTruck qui va se charger de retourner true si c'est un camion ou false sinon et qui prendra en paramètre le véhicule dont tu souhaites vérifier, je te l'écris le contenu de cette fonction mais en français (tu devras donc traduire en Lua)

Je récupère le model du véhicule et je le stock dans une variable (par exemple "model")

Si le model est égal à 499 ou le model est égal à 498 ou le model est égal à 609 ou ... alors

    On retourne true

Sinon

    On retourne false

Fin du Si

Une fois que t'as fais cette fonction, tu vas pouvoir utiliser cette fonction dans ta fonction buyBarrel comme ceci:

addEvent ("buyBarrel", true) 
function buyBarrel() 
    local vehicle = getPedOccupiedVehicle( source ) 
    local x, y, z = getElementPosition( vehicle ) 
    local barrel = createObject ( 1225, x, y, z ) 
    local distance = 8 -- distance par défaut 
    if isTruck( vehicle ) then -- si isTruck renvoit true 
        distance = 15 -- on change la distance pour un nombre plus élevé. 
    end 
    setElementPositionOnLocalAxes( barrel, vehicle, 180, distance ) 
end 
addEventHandler("buyBarrel", root, buyBarrel) 

En testant, j'ai découvert un autre problème.. le barril respawn, même après qu'il a explosé..

Hummmm ouai faudra que je regarde comment on peut virer le respawn.

Comment modifier la hauteur? il est pas TOUT-A-FAIT au sol..

Oui j'avais remarqué, mais comme c'était insignifiant, j'ai pensé que ça n'avais pas d'importance, surtout que si la voiture est en pente (vers l'avant ou vers l'arrière) le centre de rotation du baril sera à la même hauteur que le centre de rotation de la voiture.

A toi de voir, mais si tu veux vraiment pouvoir le mettre au sol, je te file cette nouvelle version de ma fonction setElementPositionOnLocalAxes qui cette fois-ci prends en plus un offsetZ (pour l'ajuster en hauteur, l'axe des Z):

function setElementPositionOnLocalAxes( element, reference, angle, distance, offsetZ ) 
    local x, y, z = getElementPosition( reference ) 
    local _, _, rz = getElementRotation( reference ) 
    local a, distance = math.rad(rz+angle), distance/100 
    x = x + distance*math.deg(math.sin(-a)) 
    y = y + distance*math.deg(math.cos(-a)) 
    setElementPosition( element, x, y, z+(offsetZ or 0) ) 
end 

Donc tu remplaces l'ancienne par celle-ci et dans ta fonction buyBarrel, tu l'utilise comme ceci (c'est un exemple):

setElementPositionOnLocalAxes( barrel, vehicle, 180, 8, -1) 

(J'ai mis 8 en distance mais si t'as fait le truc avec la fonction isTruck, tu remet bien la variable distance.)

Ici j'ajuste la hauteur finale en lui enlevant une unité sur l'axe des Z. Tu peux aussi utiliser des chiffres à virgule comme 0.5 (si -1 l'enfonce trop dans le sol).

Et bien sur, si le baril avait été dès le départ un peu dans le sol, on lui aurai donné un nombre positif.

Voilà bon codage !

Cordialement,

Citizen

Link to comment
  • 2 months later...

Après 3 mois exactement, je réponds..

J'tiens à m'excuser de ce retard, mais je n'ai pas été disponible, à cause des études, des problèmes IRL, et tout..

Donc je reprends le flambeau, je vais re-tester ce vieux script et voir si il fonctionne. Dès que ce sera fait, je ferais un EDIT sur ce message. ;)

EDIT: C'est bon, ça fonctionne, il reste juste le problème du respawn du barril, et après, ça sera bon :)

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