Jump to content

[AIDE] Scripts et Questions


Recommended Posts

Bonjour / Bonsoir,

Je crée ce topic pour vous demander de l'aide sur certains scripts, et questions..

PS : Sachez que j'ai essayé de le faire seul, mais sans succès..

1 - Poursuite Criminel mod :

Alors voilà, j'ai fais un script qui choisis aléatoirement un criminel, ça a fonctionné, mais j'ai voulu l'améliorer :

function BlipCriminel () 
         local Criminel = getRandomPlayer () 
         local BlipCriminel = createBlipAttachedTo ( Criminel, 23 ) 
         local PickUpCriminel = createPickup ( 0, 0, 0, 3, 1254 ) 
         setElementParent ( BlipCriminel, Criminel ) 
         attachElements ( PickUpCriminel, Criminel, 0, 0, 5 ) 
         if Criminel then 
         outputChatBox ("Le Criminel aléatoire est : "..getPlayerName(Criminel)..", poursuivez et tuez cette personne.", getRootElement(), 255, 0, 0, true) 
        end 
end 
addCommandHandler ("CrimiAleatoire", BlipCriminel) 
  
function MortCriminel () 
         local SangCriminel = getElementHealth (Criminel) 
         if ( SangCriminel == 0 ) then 
             destroyElement ( BlipCriminel ) 
             outputChatBox ("Le Criminel "..getPlayerName(Criminel).." a été éliminé.", getRootElement(), 0, 255, 0, true) 
        end 
end 
addEventHandler ("onPlayerWasted", getRootElement(), MortCriminel) 

DebugScript : c5u.png

Problème : Quand le criminel aléatoire meurt, le blip ne disparaît pas, et aucun message s'affiche, ensuite, le PickUp ne s'affiche pas..

2 - setElementData et getElementData :

Je me questionne sur ces deux functions, je n'ai pas compris le wiki, ni l'exemple.. Donc vous pourriez m'expliquer m'expliquer ou donner un petit exemple simple? à quoi ça sert?

3 - Système de level :

function AddExp (theplayer, commandName, theExp) 
     local recevant = getPlayerAccount ( thePlayer ) 
     local theExp = tonumber ( theExp ) or 0 
          exports.exp_system:setAccountEXP ( recevant, theExp ) 
end 
addCommandHandler ("setEXP", AddExp) 
  
function LevelUp () 
    local Experience = exports.exp_system:getAccountEXP ( source ) 
      if ( Exprience == 1000 ) then 
        exports.exp_system:addPlayerEXP ( source, 1 ) 
     end 
end 
  
function VoirLvl () 
     local Niveau = exports.exp_system:getAccountLevel ( source ) 
     outputChatBox ( "Votre niveau est : ".. Niveau, source ) 
end 
addCommandHandler ("testniveau", VoirLvl) 

Voilà c'est une tentative de faire un système de niveau, j'essaye de scripter un système manuelle de niveau, avec lequel on peux donner l'EXP, dès qu'on atteint 1000, ça nous UP avec 1 niveau. Sans succès..

DebugScript : XgwpyLP.png

Mod Utilisé pour export : https://wiki.multitheftauto.com/wiki/Resource:Exp_system

4 - Compteur.. Server-Side :

Oui je sais c'est trop, mais j'ai essayé.. Je voudrais faire un compteur mais en server-side.. en client-side j'ai réussi, voilà le script :

client-side :

function Countdown ( source ) 
    guiSetVisible ( imagecount, false ) 
    imagecount = guiCreateStaticImage (450,150,250,200,"images/3.png",false) 
    setTimer ( Countdown2, 1000, 1 ) 
end 
function Countdown2 ( source ) 
    guiSetVisible ( imagecount, false ) 
    imagecount = guiCreateStaticImage(450,150,250,200,"images/2.png",false) 
    setTimer ( Countdown1, 1000, 1 ) 
end 
function Countdown1 ( source ) 
    guiSetVisible ( imagecount, false ) 
    imagecount = guiCreateStaticImage(450,150,250,200,"images/1.png",false) 
    setTimer ( Countdown0, 1000, 1 ) 
end 
function Countdown0 ( source ) 
    guiSetVisible ( imagecount, false ) 
    imagecount = guiCreateStaticImage(450,150,320,200,"images/GO.png",false) 
    setTimer ( CountdownEnd, 3000, 1 ) 
end 
function CountdownEnd ( source ) 
    guiSetVisible ( imagecount, false ) 
end 

server-side :

function greetingCommand ( playerSource, commandName ) 
    triggerClientEvent ( "DEBUTcompteur", getRootElement() ) 
end 
addCommandHandler ( "compteur", greetingCommand ) 

DebugScript : 8d6SdKx.png

Merci d'avance :)

Link to comment
  • Moderators

1 et 2:

Ta fonction MortCriminel est exécutée à chaque fois que quelqu'un meurt sur le serveur. Il faut donc savoir si le joueur qui vient de mourir est bien le criminel choisit par notre fonction BlipCriminel.

On va utiliser les fonctions set/get ElementData comme ça je répondrai en même temps à ta deuxième question.

Un élément data est une variable/donnée que l'on peut "attacher" à un élément et identifié par une clé (véhicules, markers, joueurs etc).

Par exemple, si je veux ajouter une variable qui permet de savoir combien de fois le joueur X est mort depuis qu'il s'est connecté. Lorsqu'un joueur se connecte, je vais lui mettre un element data qui va s'appeler "morts" et le mettre à 0.

function playerConnected() 
    setElementData(source, "morts", 0) --d'après le wiki, source est le joueur qui vient de se co. 
end 
addEventHandler("onPlayerJoin", root, playerConnected) 

Donc là à chaque fois qu'un joueur se connectera, l'element data "morts" vaudra 0.

Maintenant on veut que lorsqu'il meurt, on lui rajoute +1 à son nombre de morts.

fonction playerDeath() 
    local nbMorts = getElementData(source, "morts") --on récupère la valeur de la clé "[b]morts[/b]" 
    setElementData(source, "morts", nbMorts+1) 
end 
addEventHandler("onPlayerWasted", root, playerDeath) 

C'est donc très pratique pour rajouter des variables persos sur des éléments. On pourrait aussi par exemple faire un système de lock sur les voitures. Imaginons qu'un joueur tape /lock dans un véhicule, on mettrait la clé "locked" sur le véhicule à true et si quelqu'un veut rentrer dans le véhicule (y a un event pour ça), tu vérifies si la clé vaut true et si c'est le cas, tu annules l'event (tu peux annuler des events) du coup le joueur ne pourra pas le carjacker. Pour annuler un event: cancelEvent().

Voici donc ma correction:

j'ai aussi mit un element data pour le blip et le marker pour être en mesure de les récupérer car un variable local est détruit au premier end qui suit (la variable, pas l'objet).

function BlipCriminel ( thePlayer ) 
    local Criminel = getRandomPlayer () 
    if Criminel then 
        local BlipCriminel = createBlipAttachedTo ( Criminel, 23 ) 
        local PickUpCriminel = createPickup ( 0, 0, 0, 3, 1254 ) 
        attachElements ( PickUpCriminel, Criminel, 0, 0, 5 ) 
        setElementData(Criminel, "isCriminel", true) 
        setElementData(Criminel, "attachedBlip", BlipCriminel) 
        setElementData(Criminel, "attachedPickup", PickUpCriminel) 
        outputChatBox ("Le Criminel aléatoire est : "..getPlayerName(Criminel)..", poursuivez et tuez cette personne.", getRootElement(), 255, 0, 0, true) 
    else 
        --Afficher à l'auteur de la commande que le criminel n'a pas pu être choisit 
        --C'est impossible de retrouver dans ce cas là, car si cette fonction à été appelée, c'est forcement 
        -- par un joueur qui a tapé la commande, donc il y a forcement quelqu'un sur le serveur. 
        outputChatBox ("Le Criminel aléatoire n'a pas pu être choisit (personne sur le serveur) !", thePlayer, 200, 0, 0) 
    end 
end 
addCommandHandler ("CrimiAleatoire", BlipCriminel) 
  
function MortCriminel () 
    if ( getElementData(source, "isCriminel") == true ) then 
        destroyElement ( getElementData(source, "attachedBlip") ) 
        destroyElement ( getElementData(source, "attachedPickup") ) 
        outputChatBox ("Le Criminel "..getPlayerName(source).." a été éliminé.", getRootElement(), 0, 255, 0, true) 
    end 
end 
addEventHandler ("onPlayerWasted", getRootElement(), MortCriminel) 

--------------------------------------------------------------------------------------------------

3: Hummm t'essayes d'utiliser un mod qui ne convient pas à ce que tu veux faire car il faut définir les différents levels dans le fichier levels.xml.

Je pense que la solution la plus simple serait de remplir ce xml:

<levels> 
    <level name = "level 1" experienceRequired = "1000" /> 
    <level name = "level 2" experienceRequired = "2000" /> 
    <level name = "level 3" experienceRequired = "3000" /> 
    <level name = "level 4" experienceRequired = "4000" /> 
    <level name = "level 5" experienceRequired = "5000" /> 
    etc ... 
</levels> 

Après on pourrait faire un truc générique comme ça les levels sont infinis, mais il va falloir casser le système de ce mod pour gérer ça nous même.

--------------------------------------------------------------------------------------------------

4: Déjà tu nous as donné qu'une partie de ton code côté client et évidemment c'est pas là que se trouve le problème. Dans ton client tu dois avoir un

addEvent("DEBUTcompteur") 

Hors, le wiki mentionne bien qu'il y a un deuxième paramètre qui est optionel et qui est par défaut false.

Optional Arguments

*allowRemoteTrigger: A boolean specifying whether this event can be called remotely using triggerClientEvent / triggerServerEvent or not.

Il permet de dire si cet event peut être "triggered"/appelé depuis l'autre côté via un triggerClientEvent ou triggerServerEvent. Par "autre côté", j'entends bien sur que si ton addEvent est du côté client, l'autre côté est le côté serveur et vice-versa.

Donc si t'as bien compris, il te faut créer ton event comme ceci:

addEvent("DEBUTcompteur", true) 

Et sinon t'as mis:

function Countdown ( source ) 

D'abord source est une variable "invisible" que les events envoit à la fonction (mais pas en paramètre de celle-ci). Mais en plus tu ne l'utilise pas, donc tu peux le virer de partout.

Ouf ! Enfin finit icon_biggrin.gif

J'espère que mes explications on été clair et que tu as bien compris tes erreurs et l'utilisation des element datas.

BONUS: Tu peux largement réduire ton code et la répétition pour le compteur comme ceci:

local x, y, sx, sy = 450, 150, 250, 200 
function Countdown( number ) 
    if not number then number = 3 end 
    if number > 0 then 
        local img = "images/"..number..".png" 
        if not imagecount then 
            imagecount = guiCreateStaticImage (x, y, sx, sz, img, false) 
        else 
            guiStaticImageLoadImage( imagecount, img ) 
        end 
        setTimer(Countdown, 1000, 1, number-1) 
    elseif number == 0 then 
        guiStaticImageLoadImage( imagecount, "images/GO.png" ) 
        guiSetSize( imagecount, sx+70, sy) --pour mettre sx à 320 
        setTimer(Countdown, 3000, 1, number-1) 
    else 
        destroyElement( imagecount ) 
    end 
end 

Link to comment

Merci c'est vraiment très clair!

Mais encore quelques questions..

1 - Le script du criminel, le PickUp ne se crée pas, c'est une erreur de coordonnées? Et aussi, même si un joueur qui N'EST PAS criminel meurt, le message de mort du criminel s'affiche :?

2 - J'ai donné le script du compteur complet.. Et ça ne fonctionne pas, j'ai ajouté le : "addEvent" sur le côté client, ça ne change rien, mise à part que il n'y a aucune erreur dans le debugscript

3 - Pour le système de niveau, j'ai jamais fais un script avec fichier .xml .. Donc une aide serait le bienvenue :P Et aussi, c'est assez dur, de faire un système personnalisé?

Link to comment
  • Moderators

1:

Nan je viens de vérifier et c'est bien marqué sur le wiki quels types d'éléments sont accepté pour la fonction attachElements et les pickups n'en font pas parti.

Markers</p>\n<p>Blips</p>\n<p>Objects</p>\n<p>Players</p>\n<p>Vehicles</p>\n<p>Sounds</p>\n<p>Colshapes

Ducoups remplace juste le createPickup par un createObject vu que tu n'utilises pas les propriétés des pickups.

C'est juste que la tête de mort ne tournera pas, tu peux rajouter un bout de code pour le faire tourner toutes les 50 millisecondes.

2:

Ah ! alors si t'as donné le code complet c'est sûr que ça ne va pas marcher car t'as rien pour réceptionner l'event. (Pourtant le message d'erreur dit que l'event n'est pas accessible "remotely" alors que s'il n'existait pas, il sortit une erreur comme quoi l'event n'existe pas clientside)

Bon alors admettons que tu n'avais aucun

addEvent("DEBUTcompteur"... 

ni aucun

addEventHandler("DEBUTcompteur", ... 

(vérifie quand même dans tes autres fichiers car ça me paraît bizarre)

dans ce cas, pour receptionner l'event et éxécuter le compte à rebour, il faut faire comme ceci:

local x, y, sx, sy = 450, 150, 250, 200 
function Countdown( number ) 
    if not number then number = 3 end 
    if number > 0 then 
        local img = "images/"..number..".png" 
        if not imagecount then 
            imagecount = guiCreateStaticImage (x, y, sx, sz, img, false) 
        else 
            guiStaticImageLoadImage( imagecount, img ) 
        end 
        setTimer(Countdown, 1000, 1, number-1) 
    elseif number == 0 then 
        guiStaticImageLoadImage( imagecount, "images/GO.png" ) 
        guiSetSize( imagecount, sx+70, sy) --pour mettre sx à 320 
        setTimer(Countdown, 3000, 1, number-1) 
    else 
        destroyElement( imagecount ) 
    end 
end 
addEvent("DEBUTcompteur", true) 
addEventHandler("DEBUTcompteur", root, Countdown) 

Le addEvent te permet de gérer l'event dans ce fichier lua et le addEventHandler te permet d'éxécuter la fonction de ton choix lorsqu'il se fait "triggered".

3:

Nan t'as pas compris ... Dans le script/mod que tu utilises:

https://wiki.multitheftauto.com/wiki/Resource:Exp_system

Tu est censé avoir 5 fichiers:

client.lua

level_up.mp3

levels.xml

meta.xml

server.lua

Si tu n'as pas le levels.xml, retélécharge le, t'as du le supprimer sans faire exprès.

Si tu l'as, ouvre le et modifie le comme dans mon exemple et supprimes/comment tout ton code perso que t'as essayé de faire. Ça devrait très bien marcher, le soucis c'est que t'est obligé de rentrer à la main tous les levels.

Et aussi, c'est assez dur, de faire un système personnalisé?

Je te conseil de te faire un système de level perso plutôt que d'utiliser ce mod car tu dois "casser" son comportement pour "insérer" ton système.

Maintenant que tu sais comment utiliser les elements data, ça devrait être relativement simple. Faudra juste que tu sauvegardes son XP et son level en base de données et les récupérer quand il se reconnecte.

Comportement:

1 - le joueur se connecte à ton serveur et on essaye de trouver son XP et son Level en base de données.

2 - Si on les trouve, on fait un setElementData( joueur, "XP", xpEnDB ) et un setElementData( joueur, "Level", levelEnDB )

3 - Si on ne les trouve pas, on fait un setElementData( joueur, "XP", 0) et un setElementData( joueur, "Level", 0)

4 - Il joue et reçoit de l'XP en faisant je ne sais quoi. (fait des fonctions genre setXP et setLevel pour modifier l'XP et le level et des fonctions get aussi). On met à jour les valeurs en DB.

5 - Il se déconnecte (les valeurs sont déjà sauvegarder en DB donc rien à faire)

Je te conseil de faire aussi une fonction giveXP( thePlayer, amount) dans laquelle:

- si thePlayer est bien un joueur et si amount est positif.

- tu récupères la valeur actuel de l'XP et tu lui ajoutes amount

- si le nouvel XP est supérieur ou égal à 1000

- tu récupères son level actuel

- tu lui set son level+1

- tu remets son XP à 0

- tu fais autre chose comme jouer un son de level up

- fin si

-fin si

Voilà tiens nous au courant.

Link to comment
  • Moderators

1: Pas la première fois, c'est impossible ! Mais effectivement j'ai pas pensé à remettre isCriminel à false une fois le criminel tué ...

function MortCriminel () 
    if ( getElementData(source, "isCriminel") == true ) then 
        destroyElement ( getElementData(source, "attachedBlip") ) 
        destroyElement ( getElementData(source, "attachedPickup") ) 
        outputChatBox ("Le Criminel "..getPlayerName(source).." a été éliminé.", getRootElement(), 0, 255, 0, true) 
        setElementData(source, "isCriminel", false ) 
    end 
end 
addEventHandler ("onPlayerWasted", getRootElement(), MortCriminel) 

2:

Remplace cette ligne:

local x, y, sx, sy = 450, 150, 250, 200 

par

local x, y = 450, 150 
local sx, sy = 250, 200 

3:

Apparemment, game-host fait bien les bases de données MySQL mais c'est en option. Mais MTA possède déjà une base de données. Ce n'est pas une DB MySQL mais une DB SQLite, les requêtes sont les mêmes mais elle est stocké dans un fichier .db

Pour créer/modifier une base de donnée SQLite, tu peux télécharger sqlitebrowser:

http://sourceforge.net/projects/sqlitebrowser/

Link to comment

1- Merci, cette function est vraiment utile, parcontre, quand un joueur se déconnecte, la function reste activé, ou c'est temporaire jusqu'à la déconnexion?

2- Toujours pas.. les même erreurs

3- Parfait, mais une dernière question.. Un tutoriel permettant de l'utiliser correctement? J'ai essayé d'ouvrir internal.db, je vois les comptes, etc..

Link to comment
  • Moderators

1: Bah nan faut que tu gères quand le criminel quitte le serveur.

2: J'avais mis sz au lieu de sy.

imagecount = guiCreateStaticImage (x, y, sx, sy, img, false) 

3: Désolé, je n'ai pas de tuto sous la main, mais après c'est des requêtes SQL classiques que tu fais grâce à la fonction executeSQLQuery (à utiliser après dbConnect évidemment).

Sur la page du executeSQLQuery il y a des exemples de requêtes dont les 4 principaux (SELECT, UPDATE, INSERT et DELETE). Regarde bien les exemples pour comprendre en gros ce que ça fait. Après tu peux toujours regarder un tuto sur les bases du SQL, ce n'est pas utiliser que pour MTA donc tu peux très bien aller sur des sites qui n'ont rien à voir avec MTA pour ça.

Link to comment
  • Moderators

2 - J'ai besoin des erreurs antérieure à ceux que tu me montres. Il serait plus pratique que tu copies-colles les erreurs clients depuis ton clientscript.log qui se trouve par défaut dans:

C:\Program Files (x86)\MTA San Andreas 1.3\MTA

Il se peut que le fichier soit trop volumineux pour être ouvert dans un éditeur de texte classique, dans ce cas, supprimes carrément le fichier et tu retourne sur ton serveur afin de reprovoquer l'erreur.

Avec le peu d'information que j'ai dans ces erreurs, il semblerai que imagecount vaut autre chose que nil, 0 ou false et que du coups, il ne recrée pas le static image en pensant qu'il existe toujours alors qu'il à été détruit.

Essaye de rajouter un

imagecount = nil 

juste après le destroyElement.

Link to comment
  • 1 month later...

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