GTAOnline.net
San Andreas Multiplayer (sa:mp) => Scripting SA-MP [Pawn center] => Discussion démarrée par: sadmandono le 30 Juillet 2007, 23:17:46
-
Bonjour à tous.
Voila. Je voudrais créer un compteur de vitesse pour mon serveur. Or, je déteste faire des copier-coller.
J’ai donc décidé d’écrire mon propre script. (Bien que je débute en prog.).
Je veux simplement que vous me disiez, si j’emploie la bonne méthode. Et sinon, que vous m’indiquiez une meilleure méthode. Mais surtout pas un script complet, juste une méthode. J’insiste là-dessus, car comme je l’ai dit plus haut, je déteste faire des copier-coller car c’est trop facile.
Voila, j’espère que vous pourrais me conseiller.
Note aux Admins. Si vous juger, ce topic inutile, n’hésitez pas à le supprimer. (Même si vous n’avez pas besoin de mon autorisation ^^).
Voici l’adresse Pastebin. http://pastebin.gtaonline.fr/pastebin.php?show=28
-
Salut sadmandono
Je suis comme toi un débutant en programmation et comme toi je deteste faire du copier/coller ;)
J'ai regardé ton code, je t'avouerai franchement que j'y comprend pas grand chose. Moi je serais partis autrement, j'aurais peut-être utilisé la bonne vieille formule V = D/T où V = vitesse, D = Distance et T = Temps, avec un timer. Encore faut il trouvé la bonne unité pour D.
Attendons la réponse de notre expert Syg ::)
Ps: Je ne vois pas pourquoi on supprimerai ton topic :)
-
Moi j'aurai utiliser la fontion kph() (ou un truc comme ça) des include non-officiel SA-MP.
Comme vous voulez :)
-
Euh dis moi pourquoi tu utilises pas les fonctions floatpower, floatsqroot ... au lieu de faire Deplacement1*Deplacement1 dans le genre ? Sinon moi perso j'ai déja essayé de faire un compteur tout seul mais sa me retournais un chiffre comme 354354687 alors que mon joueur ne bougait pas d'un poil :s
-
Bonjour.
Guigui. C’est bel et bien V=D/T que j'ai utilisé pour mon script (incomplet d'ailleurs, puisque je n'ai pas encore intégrer les timer.)
Pour trouver D. j’ai utilisé….Pythagore ! (Je vous laisse deviner pourquoi). Cela vous aidera peut-être à comprendre pourquoi il y a des carrés et racine carrée dans le script.
At1x pourquoi utiliser une fonction pour trouvé un carré. Alors qu’il suffit de multiplier une variable par elle-même ?
J’ai testé mon script avec un ide. Dev c++.
J’ai lancé le mode debug de san andreas. J’ai parcouru la map d’est en ouest chrono en main (sans oublier d’utiliser la commande /save au départ et à l’arrivé). En divisant le résultat par le temps obtenu. Le script m’a retourné des valeurs comme 256 km/h et plus pour un hydra. Et environ 80 km/h avec une voiture de base (ce sont des moyennes sur toute la distance et non pas des vitesses à un temps T).
UZI-I. merci pour l'info mais comme je préfère créer cette fonction compteur de A à Z....
Sinon, si vraiment je ne trouve pas, je jetterais peut-être un coup d'oeil à cette fonction kph() :)
C'est bizarre. Ma signature ne fonctionne pas dans ce topic alors quelle marche très bien. dans mon profil.
-
Première erreur : Tu récupères deux fois de suite la position du joueur (CoordX et CoordX2) l'une à la suite de l'autre.
J'imagine que ces deux appels à la fonction GetPlayerPos se font si rapidement que CoordX et CoordX2 doivent sensiblement être égaux et que donc la vitesse que tu calcules doit être complétement fausse.
Deuxième erreur : Tu calcules la vitesse du joueur dans le plan (XY) et tu oublies que GTA est en 3D et qu'il y a un composante Z. (La vitesse d'un joueur en chute libre sera de 0 KM/H avec tes calculs .... !!!)
Autre chose : floatsqroot pour calculer une racine carrée me semble plus rapide que ton algorithme.
Donc petit cours sur le compteur de vitesse :
Effectivement, comme l'a dit Guigui, il faut se baser sur un timer. Donc on démarre un timer de 1000ms dans OnGameModeInit (1000ms sinon on risque de surcharger le serveur si tous les joueurs mettent le compteur de vitesse). On verra plus loin ce qu'on met dedans.
Ensuite, on met en place notre commande "/vitesse" et là, on ne fait que sauvegarder la position (Xa, Ya, Za) du joueur dans un tableau (une entree par joueur) et positionner un flag (un par joueur) pour dire que le joueur a demandé le compteur de vitesse.
Dans notre Timer :
Si le joueur a demandé le compteur de vitesse (test sur le flag qu'on a positionné dans la commande)
On récupère la position de joueur (Xb, Yb, Zb) (ce qui fait qu'on va récupérer la position de joueur toutes les secondes).
Ensuite, on calcule la distance (en 3D) qu'il a parcouru depuis sa dernière position.
La distance entres un point A(Xa Ya, Za) et B(Xb, Yb, Zb) dans l'espace est :
Dist = floatsqroot ((Xb-Xa)*(Xb-Xa) + (Yb-Ya)*(Yb-Ya) + (Zb-ZXa)*(Zb-Za))
Dans SA-MP, les coordonnées sont en mètres (enfin je crois) donc la vitesse du joueur est :
Vitesse en m/s -> Vitms = Dist/1.0 (puisque notre timer est à 1 seconde) (cette ligne en inutile dans le script)
Donc Vitesse en KM/H -> VitKmh = Dist / 3600.0 (C'est cette vitesse qu'on affiche)
Enfin, on sauvegarde la nouvelle position du joueur (Xa, Ya, Za) = (Xb, Yb, Zb)
Dernière petite chose : Si le joueur refait /vitesse, on reset le flag comme ça le compteur ne s'affiche plus
Par contre, vu qu'on utilise un timer, la précision n'est pas géniale et à vitesse constante du ton véhicule, le vitesse affichée peut varier de +/- 10 km/h. Pour un peu plus de précision, on peut utiliser la fonction GetTickCount (disponible exclusivement sous Windows) et sauvegarder le TickCount en même temps que la position du joueur et faire les calcul avec la différence entre le TickCount suvegardé et le TickCount du moment où l'on calcule.
++
Syg
-
l expert a parlé .....
:dejadehors
-
Merci Raf(FS), c'est trop d'honneur :-[.
En plus, l'expert a fait une grosse boulette qu'il vient de voir en se relisant (oui, bon d'accord, j'aime me relire mais c'est pour trouver mes erreurs avant que d'autres ne les trouvent)
La vitesse en KM/H est (mais tout le monde s'en était rendu compte) VitKmh = Dist * 3600.0 (hum hum, je l'avais fait exprès pour voir si vous suiviez)
++
Syg
-
Bonjour.
Pour la vitesse en chute libre, j’avais estimé que ce n’étais pas indispensable. Mais en y réfléchissant, j’avais tort.
Je ne connais pas encore parfaitement les flags (j’ai encore à apprendre).
En tout cas la méthode donnée est à 80% égale à ce que j’avais imaginé avant de commencer mon script. Mais je ne savais pas tellement comment m’y prendre. Je ne savais pas où placer mes SetTimer ;D.
Merci pour ce petit cours, c’est exactement ce que je demandais (Une méthode, pas une solution).
Voila, je vais me mettre au boulot. Je reviendrais sur ce topic en cas de problèmes.
Quelqu'un connaît l’id max pour la météo ? 50 100 200 ……. ?
PS : Je me disais bien. : « Mais pourquoi il veut me faire diviser la vitesse pas 3600 ?!!!! ». C’était fait exprès ? (hum hum hum :blink.)
-
Très léger cours sur les flags (drapeaux).
En fait un flag n'est qu'une "vulgaire" variable à qui l'on fait prendre les valeurs 0 ou 1 (parfois d'autres valeurs dans certains cas plutôt rares) pour indiquer un état particulier (d'un joueur, d'un véhicule, ...).
Par exemple si on déclare le tableau suivant :
new CompeurOn[MAX_PLAYERS]; // Un flag par joueur pour le compteur de vitesse
Lorsque le joueur tape la commande "/vitesse" pour la première fois, on fait passer la valeur de son flag à 1 :
CompteurOn[playerid] = 1; // Afficher le compteur pour le joueur
On se sert ensuite de ce flag pour savoir si le joueur a activé le compteur de vitesse :
if (CompteurOn[playerid] == 1)
{
// On fait ce qu'on a à faire
}
Puis, quand le joueur saisi la commande "/vitesseoff", on reset son flag :
CompteurOn[playerid] = 0; // Plus de compteur pour le joueur
C'est pas très compliqué.
Bon, maintenant, je suis en vacances, retour le 20 août.
EDIT Syg :
Et j'en ai apparement bien besoin parce que, deuxième boulette : C'est pas par 3600.0 qu'il faut multiplier mais par 3.6 (OK, je vais pas dire que je l'avais fait exprès ....En fait dans mon script, je me sers de GetTickCount () qui donne des millisecondes, d'où le 3600.0)
Effectivement, je suis expert, mais expert en boulettes !!
++ les scripteurs
Syg
-
Pour quoi tu appelle ça des "flag" ?
C'est des array unidimensionnel.
-
Pour quoi tu appelle ça des "flag" ?
C'est des array unidimensionnel.
Peut-être parce que c'est plus court "flag" ;)
-
Coucou. en fait, les "flags" c'est la même chose que les booléens ? :blink
-
Oui Sadmandono, mais dans l'absolu un flag est un indicateur d'état binaire qui prend les valeurs VRAI=1 ou FAUX=0 alors qu'un booléen est un type de donnée (qui n'existe pas en PAWN d'ailleurs).
Ainsi, dans l'absolu toujours, un flag est de type booléen.
Mais dans le langage courant des développeurs (comme moi), on étend parfois la définition du flag aux indicateurs d'états multiples (par exemple, VRAI, FAUX ou INDEFINI ou encore BLEU, VERT, ROUGE, JAUNE ou ORANGE_FLUO_QUI_FLASHE_BIEN) parce que, comme le dit Guigui c'est plus court à dire et à écrire.
Dans le cas qui nous interresse, le flag est bien binaire (AVEC=1 ou SANS=0 affichage du compteur de vitesse).
Et donc pour répondre à UZI-I, sans trop le contredire,
new CompeurOn[MAX_PLAYERS]; // Un flag par joueur pour le compteur de vitesse
est un array (tableau) unidimensionnel de flags (un par joueur comme le dit le commentaire)
++ (la je suis vraiment en vacances maintenant, profitez en pour dire du mal de moi)
Syg
-
C'est un Array de taille [MAX_PLAYERS]
Apres tu en fait ce que tu veut.
-
C'est quoi cette histoire qu'un booléen n'est pas utilisable en pawn ? Bien sur que si c'est utilisable, d'ailleurs pour en faire un faites : "new bool:var;" et voila cette variable prend par défaut la valeur false(faux), vous pouvez aussi lui faire prendre la valeur true(vrai). :)
-
Bonjour.
Citation du mini-cours de Syg: " Ensuite, on met en place notre commande "/vitesse" et là, on ne fait que sauvegarder la position (Xa, Ya, Za) du joueur dans un tableau (une entrée par joueur) et positionner un flag (un par joueur) pour dire que le joueur a demandé le compteur de vitesse."
Est ce que ça donne ceci ? http://pastebin.gtaonline.fr/pastebin.php?show=31
Voila c'était juste pour confirmation.
Merci.
@+++
Edit:
Je pense avoir terminé le script mais j'obtient l'erreur :" must be a constant expression, assumed zero. Quelqu’un peut-il m'expliquer dans quels cas peut-ont obtenir cette erreur (pour pouvoir corriger par moi-même) ?
Encore un edit. (hé oui !).
Voila sur le forum sa-mp.com, Le nom de fichier pawn-lang.pdf apparait souvent. Il me semble qu'il explique le pourquoi du comment des erreurs de compilation. Or il m'est impossible de mettre la main sur ce fameux fichier (sensé être dans le dossier pawno) les topic ou j'ai vu ce nom sont assez vieux (2006). Quelqu'un connait ce fichier ?
-
Télecharge le fichier ZIP contenant le serveur 0.1b .
http://www.gtasa.fr/download.php?act=view&id=1090
-
ok merci Alless(01) :)
-
Petit problème. Il me semble que mon code soit correct. (Bon il y surement des erreurs que je n'arrive pas à voir, en cause mon très petit niveau :bangin).
Mais j'ai l'impression que le Fonction SetTimer ne travaille pas.
Cela fait que je me retrouve avec deux coordonnées identiques pour les calculs. Ce qui fait donc que vitesse = 0.
http://pastebin.gtaonline.fr/pastebin.php?show=33
Si quelqu’un est capable de m'expliquer le pourquoi du comment, je suis preneur. merci :)
-
attendons l avis le l expert syg :king
-
L'expert SYG est en vacances :)
Bon je continu à chercher de mon coté. (J'attend tout de même un avis de Monsieur SYG.).
De toute façon je reposterais au cas ou.
-
Je répond d'abord à Atx1 (qui a raison) :
J'ai pas dit que les booléens n'étaient pas utilisables, j'ai dit que le type booléen n'existait pas en PAWN :
"pawn lacks the typing mechanism of C. pawn is an “integer-only” variety of C; there are no structures or unions, and floating point support must be implemented with user-defined operators and the help of native functions."
Pour ceux qui n'ont pas compris : "pawn n'a pas le même méchanisme de typage que le C. pawn est une variétée de C avec seulement le type entier ; il n'y a pas de structure ou d'union et le support des nombres en virgule flottante doit être implémenté par des opérateurs définis par l'utilisateur et à l'aide des fonctions natives." (Bon, d'accord, c'est pas forcément plus clair en français)
Citation de la doc officielle de PAWN (celle que cherche sadmandono).
Et, autant pour moi, il existe bien un tag bool: qui permet de limiter les valeurs d'une variable à 0 (false) ou 1 (true) et donc de définir (et d'utiliser) des booléens.
Et maintenant, je répond à sadmandono :
1 - La fonction c'est OnGameModeInit et pas OnGamaModeinit
2 - Le dernier paramètre de SetTimer est 0 ou 1 (false ou true), et dans ton cas c'est 1
3 - Ta fonction afficheVitesse NE doit PAS avoir de paramètre puisqu'elle va être appelée par le timer (qui ne lui passera pas de paramètre) et elle DOIT être "public".
4 - Tes tableaux positionJoueur[] et afficheCompteur[] doivent être déclarés en dehors de toutes fonctions. Les variables déclarées dans une fonction n'existent que pendant que le fonction est exécutée, elles sont détruites après.
5 - Ta fonction afficheVitesse doit contenir une boucle sur TOUS les joueurs (playerid indéfini) et testé si les joueurs sont connectés ou pas
6 - Toutes les variables de tes calculs doivent avoir le tag Float:
7 - Pourquoi est-ce que tu divises la distance par 125.400048 ? Je pense pas que ce soit nécessaire.
8 - Evites les printf toutes les secondes, c'est pas très pratique à lire
9 - Ta variable valide n'est pas utile, tu peux directement sauvegarder la position
10 - Pour la sauvegarde de la position, fais positionJoueur[playerid] = positionJoueur2[playerid];, il sauvegardera tout seul les 3 coordonnées
J'ai fait une correction de ton code, c'est plus simple : http://pastebin.gtaonline.fr/pastebin.php?show=41 mais tu n'est pas obligé de regarder tout de suite, tu peux essayer de corriger toi-même.
++
Syg
-
Bonjour a tous!
Je voudrai poser une question a propos du Timer:
L'intervalle égale a quoi? minute, seconde, milliseconde?
-
Les intervales de timers se donnent en millisecondes.
++
Syg
-
Merci beaucoup
-
Ok merci Syg. Je vais tenter de corriger cette multitude d'erreurs avant de jeter un œil à ta correction.
En tout cas merci pour ton aide précieuse ^^.
Je vais de ce pas, me pencher sur les corrections à apporter à mon script.
@+++
Merci.
;)
-
on dois utiliser "forward" pour les prototype ???
-
Les seule fonctions à déclarées forward dans un script PAWN sont celles qui sont définies comme public.
Il n'y a que deux types de fonctions à definir comme public : les callbacks (comme OnGameModeInit) et les fonctions utilisées par les timers.
Pour les callbacks, la déclaration forward est déjà faite dans le fichier include a_samp.inc.
Donc il reste à la faire pour les fonctions utilisées par les timers.
++
Syg
-
Bonjour.
Voila syg, j'ai presque fini les corrections. (Je suis un peu long car je ne me met pas a fond dans ce script. d'ailleur je "boss" sur d'autres).
J'ai une petite question.
j'ai plusieurs fois vu des bots sur des serveurs.
Comment est-ce possible, c'est des fonction officiel de samp ?
ça semble intéressant. Pour faire des missions en coop par exemple.
-
Les bots ne sont pas possibles à implémenter par script car ce n'est pas prévu (peut-être dans le 0.3).
Les bots que tu as vu viennent d'un modification non officielle du serveur 0.1b.
Donc pas de bot en 0.2.
++
Syg
-
Ok merci pour l'info ^^
Ce serait super si cette option pourrait être intégrée dans samp 0.3 (S'il existe un jour !!! Pourquoi pas ?).
Encore une petit question.
Désolé mais je n'ai pas trouvé de topic y répondant.
Il s'agit de la fonction GetPlayerkeys. Est-ce cette fonction qui est utilisée dans les serveurs de stunt pour par exemple, faire apparaître une rampe.
Si quelqu'un pouvais m'expliquer les paramètres de cette fonction ?
Simplement savoir à quoi elle sert.
@++
Sad
-
Je n'ai jamais utilisé la fonction GetPlayerKeys et je ne vois pas à quoi peuvent correspondre les paramètres de cette fonction.
Par contre, j'ai codé la création de rampes avec la callback OnPlayerKeyStateChange.
Cette callback permet de connaitre pour un joueur donné (playerid) les touches qu'il vient juste d'enfoncer.
On retrouve ces touches dans le paramètre newkeys qui est une combinaison de toutes les touches que le joueur enfonce au moment de l'appel.
Pour extraire de ce paramètre les informations que l'on veut, il faut utiliser le ET logique (&) comme dans l'exemple ci-dessous :
public OnPlayerKeyStateChange(playerid, newkeys, oldkeys)
{
/* Le joueur utilise la touche "Attaque secondaire" */
if (newkeys & KEY_SECONDARY_ATTACK)
{
/* On fait ce qu'on a à faire */
}
}
Pour avoir la liste des touches, regardes dans le fichier include a_samp.inc
++
Syg
-
Salut !
Ok merci pour ces explications très intéressantes.
Je file de suite voir ce qu'il en est de ce fichier a_samp.inc
@++
sad
-
Merci j'ai presque reusi a faire ma cmd :P
AK NV.