Fonctions/bouts de code
#1

Yo.

Inspirй par un thread anglais (dis donc ils sont forts ceux lа :o), j'ai dйcidй de crйer ce thread.

Concrиtement, il sert а quoi ?
A partager des bouts de codes ou des fonctions uniques sans crйer un thread avec le prйfixe "include" (car include = bibliothиque et une bibliothиque avec un seul livre c'est pas une bibliothиque m'voyez ?).

Pas de hors sujet s'il vous plait ;)

Le topic original (anglais) est celui ci.

J'en balance quelques unes

randstr et crandom (une string random et un caractиre random)

Utilisation :

[pawn]

new str[31], chr;
randstr(30, str, true);
crandom(chr, false);
printf("Random string : %s | Caractиre random : %c | Valeur ASCII du caractиre : %d", str, chr, chr);

[/pawn]

Fonction :

[pawn]

static const chars[] =
{
65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120
};

static const numbers[] =
{
42, 43, 45, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57
};

static const specials[] =
{
33, 34, 35, 36, 37, 38, 39, 40, 41, 44, 46, 58, 59, 60, 61, 62, 63, 64, 91, 92, 93, 94, 95, 96, 123, 124, 125, 126
};

static const all[] =
{
65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 42, 43, 45, 47,
33, 34, 35, 36, 37, 38, 39, 40, 41, 44, 46, 58, 59, 60, 61, 62, 63, 64, 91, 92, 93, 94, 95, 96, 123, 124, 125, 126
};

static const alphanum[] =
{
65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 42, 43, 45, 47
};

#pragma unused chars, numbers, specials

stock randstr(lenght, string[], bool:specialsc = true)
{
for(new i = 0; i < lenght; i++)
{
do
{
if(specialsc)
{
new j = 33 + random(93); // 126 (max) - 33 (min)
for(new k = 0; k < sizeof(all); k++)
{
if(all[k] == j) string[i] = j, break;
else continue;
}
}
else
{
new j = 48 + random(72);
for(new k = 0; k < sizeof(alphanum); k++)
{
if(alphanum[k] == j) string[i] = j, break;
else continue;
}
}
}
while(string[i] == 0);
}
return 1;
}


stock crandom(&chara, bool:specialc = true)
{
do
{
if(specialsc)
{
new j = 33 + random(93); // 126 (max) - 33 (min)
for(new k = 0; k < sizeof(all); k++)
{
if(all[k] == j) chara = j, break;
else continue;
}
}
else
{
new j = 48 + random(72);
for(new k = 0; k < sizeof(alphanum); k++)
{
if(alphanum[k] == j) chara = j, break;
else continue;
}
}
if(chara != 0) break;
}
while(chara == 0);
return 1;
}

[/pawn]


strreplace - Remplace une partie (oldsub) d'une string (str) par un autre morceau, peu importe que les tailles correspondent ou pas (newsub). (merci а Kilou)

Utilisation :

[pawn]

new str[] = "Salut, suis-je bien sur SMAP ?";
printf(str);
printf("Remplacement...");
strrep(str, "SMAP", "SA-MP");
printf(str);
[/pawn]

Fonction :

[pawn]

#if !defined strreplace
#define strreplace strrep
#endif

stock strrep(str[], oldsub[], newsub[])
{
if(strfind(str, oldsub) == -1) return 0;
new pos[2];
pos[0] = strfind(str, oldsub);
for(new i = 0, l = strlen(str); i < l; i++)
{
if(i <= pos[0] + strlen(oldsub)) continue;
if(str[i] == ' ') break;
}
pos[1] = s_string_var;
strdel(str, pos[0], pos[1]);
strins(str, newsub, pos[0], .maxlength = sizeof(str));
return 1;
}

[/pawn]

ProxDetector йditй avec 5 couleurs qui se substituent selon la distance, qui permet de propager un message sur un radius spйcifique sans utiliser format au prйalable.

Utilisation :

[pawn]

// dans une commande
new pName[MAX_PLAYER_NAME+1];
GetPlayerName(playerid, pName, MAX_PLAYER_NAME+1);
ProxDetector(20.0, playerid, "* %s attrape sa ceinture et l'enfonce dans la boucle.", -1, -1, -1, -1, -1, pName);

[/pawn]

Fonction :

[pawn]

stock ProxDetector__(Float:radi, playerid, const message[], col1, col2, col3, col4, col5, {Float,_}:...)
{
if(!IsPlayerConnected(playerid)) return 1;
static const ARGUMENTS = 8;
new n = (numargs() - ARGUMENTS) * BYTES_PER_CELL, bool:used = false;


if(!n) goto final;


new
arg_start,
arg_end,
fstring[145]
;

#emit CONST.alt col5 // Changer l'argument de cette ligne si vous les rйarrangez (зa doit toujours кtre le dernier argument obligatoire)
#emit LCTRL 5
#emit ADD
#emit STOR.S.pri fstring

#emit LOAD.S.pri n
#emit ADD
#emit STOR.S.pri arg_end

do
{
#emit LOAD.I
#emit PUSH.pri
arg_end -= BYTES_PER_CELL;
#emit LOAD.S.pri arg_end
}
while(arg_end > arg_start);

#emit PUSH.S message
#emit PUSH.C 145
#emit PUSH.ADR fstring

n += BYTES_PER_CELL * 3;

#emit PUSH.S n
#emit SYSREQ.C format

n += BYTES_PER_CELL;

#emit LCTRL 4
#emit LOAD.S.alt n
#emit ADD
#emit SCTRL 4

used = true;

final:
{
new Float:pos[6], Float:f;
GetPlayerPos(playerid, pos[0], pos[1], pos[2]);

foreach(new i : Player)
{
if(GetPlayerVirtualWorld(playerid) != GetPlayerVirtualWorld(i)) continue;
if(i == playerid) continue;
if(radi <= 20.0 && GetPlayerInterior(playerid) != GetPlayerInterior(i)) continue;
GetPlayerPos(i, pos[3], pos[4], pos[5]);

f = VectorSize(pos[0]-pos[3], pos[1]-pos[4], pos[2]-pos[5]);
if(!used)
{
if(f <= radi/16) SCM(i, col1, message);
else if(f <= radi/8) SCM(i, col2, message);
else if(f <= radi/4) SCM(i, col3, message);
else if(f <= radi/2) SCM(i, col4, message);
else if(f <= radi) SCM(i, col5, message);
}
else
{
if(f <= radi/16) SCM(i, col1, fstring);
else if(f <= radi/8) SCM(i, col2, fstring);
else if(f <= radi/4) SCM(i, col3, fstring);
else if(f <= radi/2) SCM(i, col4, fstring);
else if(f <= radi) SCM(i, col5, fstring);
}
}
}
return 1;
}

[/pawn]



mysql_tquery_file - Permet d'exйcuter des requкtes SQL threadйes une par une lorsqu'elles se situent dans un fichier lui-mкme situй dans scriptfiles ! Possibilitй d'appeler une callback lorsque TOUTES les requкtes sont terminйes. (UNE REQUКTE PAR LIGNE SVP)

Utilisation :

[pawn]

mysql_tquery_file(1, "requetes.txt", "OnQueriesFinish", "i", GetTickCount());

// en bas du gm

forward OnQueriesFinish(const &time);
public OnQueriesFinish(const &time)
{
printf("Pour exйcuter toutes les requкtes du fichier requetes.txt, le serveur a mit %d millisecondes", time);
return true;
}

[/pawn]


Fonction :

[pawn]

mysql_tquery_file(const conHandle, const file[], callback[] = "", formt[] = "", {Float,_}:...)
{
new l = strlen(formt);
if((numargs() - 4) != l) return 0;

new bool:passed = false;
if(strlen(callback) <= 1 && l <= 1) goto reading;

static const ARGUMENTS = 4;
new n = (numargs() - ARGUMENTS) * BYTES_PER_CELL;
if(!n) goto reading;

new
parstring[256],
formatted[256],
arg_start,
arg_end;

for(new ii = 0; ii < l; ii++)
{
switch(formt[ii])
{
case 'd': strcat(parstring, "%d, ");
case 'i': strcat(parstring, "%i, ");
case 'f': strcat(parstring, "%f, ");
case 'a', 's': strcat(parstring, "%s, "), formt[ii] = 's';
}
}

#emit CONST.alt formt
#emit LCTRL 5
#emit ADD
#emit STOR.S.pri arg_start

#emit LOAD.S.alt n
#emit ADD
#emit STOR.S.pri arg_end

do
{
#emit LOAD.I
#emit PUSH.pri
arg_end -= BYTES_PER_CELL;
#emit LOAD.S.pri arg_end
}
while (arg_end > arg_start);


#emit PUSH.S parstring
#emit PUSH.C 256
#emit PUSH.ADR formatted

n += BYTES_PER_CELL * 4;
#emit PUSH.S n
#emit SYSREQ.C format

n += BYTES_PER_CELL;
#emit LCTRL 4
#emit LOAD.S.alt n
#emit ADD
#emit SCTRL 4

passed = true;

reading:
{
new File:hfile = fopen(file);
new query[256];
if(!hfile) return 0;
while(read_query(hfile, query)) mysql_tquery(conHandle, query);
fclose(hfile);
reading:
{
new File:hfile = fopen(file);
new query[256];
if(!hfile) return 0;
while(read_query(hfile, query)) mysql_tquery(conHandle, query);
fclose(hfile);
if(passed && funcidx(callback) != -1) CallLocalFunction(callback, formt, formatted);
} return 1;
}

[/pawn]

Voilа, si vous en avez qui pourraient кtre pas mal, postez les !
Reply
#2

Bonne idйe
Pense а optimiser les scripts: les strlen() dans les boucles (comme dans strrep()) vont кtre appelйs а chaque passage, alors que dans le cas de strrep() ce n'est pas nйcessaire, crйe donc des variables qui rйcupйreront la taille avant la boucle pour optimiser cela

Pense aussi а dйcrire ce que va faire les fonctions que tu mets, ce n'est pas forcйment йvident

Et je poste la mienne:
cfind() - Permet de rechercher un seul caractиre dans une chaоne (c'est plus optimisй que d'utiliser strfind)
[pawn]stock cfind(const str[], ch1, end = -1)
{
if(!(-1 < end < strlen(str)))
end = strlen(str) - 1;

if(ch1 < 0)
return -1;

for(new i = 0; i < end; i++)
if(str[i] == ch1) return i;

return -1;
}[/pawn]
Utilisation:
[pawn]new string[] = "Salut зa va ?",
pos;

pos = cfind(string, 'з');
printf("%d", pos);
//Affichera "6" car "з" est le а la position 6 dans la chaоne[/pawn]

GenerateCode() - Gйnиre un code de longueur maximum de 10 chiffres, dont pas un seul chiffre n'apparaоtra deux fois
ccontain() - Vйrifie si une chaоne contient un caractиre, ou pas (Si jamais la valeur retournйe par cfind n'est pas amenйe а кtre utilisйe, c'est trиs lйgиrement plus optimisй et plus appropriй d'utiliser ccontain)
[pawn]stock GenerateCode(length = 6)
{
if(length > 10)
length = 10;

new str[11];
for(new i = 0; i < length; i++){
new letter = random(10) + 48;
while(ccontain(str, letter, length))
letter = random(10) + 48;
str[i] = letter;
}

return str;
}

stock ccontain(const str[], ch1, end =- 1)
{
if(end <= -1 || end >= strlen(str))
end = strlen(str);

for(new i = 0;i < end; i++)
if(str[i] == ch1) return true;

return false;
}[/pawn]
Utilisation:
[pawn]new string[7] = GenerateCode(6);
if(cfind(string, '5'))
printf("string contient le caractиre '5'");[/pawn]
Reply
#3

Okay, merci ma loutre !

J'avais pas compris avant pourquoi les gens assignaient la taille а une variable, mais c'est vrai que c'est pas con du tout !

Et j'ajoute une description pour chaque fonction.
Reply
#4

enfin un topic utile ou on peut c/c :bave:
Reply
#5

Trиs Bien
Reply
#6

J'ai dйjа crйй ce topique dans le temps, mais il n'a pas tenu x)
Reply
#7

Car j'йtais pas lа nйgro ;)

Tu verrais la tonne de conneries que je code par jour
Reply
#8

Voilа c'est une fonction que j'ai mis au point pour les texte trop long (>70 caractиres).
Si le texte et trop long alors le message apparaitera comme cela :

Dйbut du texte ...
... suite du texte.

Code:
stock SendMessage(playerid, phrase[])
{
    new Nom[MAX_PLAYER_NAME];
    new str[256], str2[256], phrase2[256];
    GetPlayerName(playerid, Nom, sizeof(Nom));
    if(strlen(phrase) &gt; 70)
    {
         strmid(str2, phrase, 70, strlen(phrase));
         strmid(phrase2, phrase, 0, 70);
         format(str,sizeof(str),"%s dit : %s ..." ,Nom, phrase2);
         SendClientMessage(playerid, 0xFFFFFFFF,str);
         format(str,sizeof(str),"* ... %s" ,str2);
         SendClientMessage(playerid, 0xFFFFFFFF,str);
         return 1;
    }
    format(str,sizeof(str),"%s dit : %s" ,phrase, Nom);
    SendClientMessage(playerid, 0xFFFFFFFF,str);
    return 1;
}

Vous pouvez donc l'adapter а proxdetector, la fonction que S4t3k а partagй au dessus, voila voila :)
J'ai pas tester la fonction mais logiquement зa devrait fonctionner.

EDIT : J'avais fait une faute pour "new phrase2;" j'avais mis "new phrase;" qui est dйjа dйfini en paramиtre dans la fonction :)
Reply
#9

Pas mal mais optimisable je crois.

Je tente de le faire de mon cфtй et je poste si je rйussis.
Reply
#10

L'idйal serait que зa boucle autant de fois qu'il faut pour obtenir une longueur donnйe (les mots doivent tout de mкme rester entiers).
Reply
#11

On peut optimiser avec "strins" je pense :)
Reply
#12

Beaucoup mieux : aucun strtruc (et j'ai mкme ajoutй la possibilitй de foutre des %d, %s, %f etc directement dans "phrase")

[pawn]

forward FIX_SYSREQ(); public FIX_SYSREQ()
{
format("", 2, "");
return true;
}

SendMessage(const &playerid, const phrase[], {Float,_}:...)
{
static const ARGUMENTS = 2;
new n = (numargs() - ARGUMENTS) * 4, bool:used = false;
if(!n) goto operating;

new
arg_start,
arg_end,
fstring[145];

#emit CONST.ALT phrase
#emit LCTRL 5
#emit ADD
#emit STOR.S.pri arg_start

#emit LOAD.S.alt n
#emit ADD
#emit STOR.S.pri arg_end

do
{
#emit LOAD.I
#emit PUSH.S
arg_end -= 4;
#emit LOAD.S.pri arg_end
}
while(arg_end > arg_start);

#emit PUSH.S phrase
#emit PUSH.C 145
#emit PUSH.ADR fstring

n += 4 * ARGUMENTS;

#emit PUSH.S n
#emit SYSREQ.C format

n += 4;

#emit LCTRL 4
#emit LOAD.S.alt n
#emit ADD
#emit SCTRL 4

used = true;

operating:
{
new nom[MAX_PLAYER_NAME+1];
GetPlayerName(playerid, nom, MAX_PLAYER_NAME+1);
new l = strlen(phrase);
if(l > 70 && used) return SendClientMessage_(playerid, -1, "%s dit : %.70s", nom, fstring), SendClientMessage(playerid, -1, "* ... %s", fstring[71]);
else if(!used && l > 70) return SendClientMessage_(playerid, -1, "%s dit : %.70s", nom, phrase), SendClientMessage_(playerid, -1, "* ... %s", phrase[71]);
else if(used && l <= 70) return SendClientMessage_(playerid, -1, "%s dit : %s", nom, fstring);
else return SendClientMessage_(playerid, -1, "%s dit : %s", nom, phrase);
}
}

[/pawn]


Fonctionne en partenariat avec SendClientMessage_ :

[pawn]
SendClientMessage_(const &playerid, const &col, const message[], {Float,_}:...)
{
static const ARGUMENTS = 3;
new n = (numargs() - ARGUMENTS) * 4;
if(!n) return SendClientMessage(playerid, col, message);

new
fstring[145],
arg_start,
arg_end
;

#emit CONST.alt message
#emit LCTRL 5
#emit ADD
#emit STOR.S.pri arg_start

#emit LOAD.S.alt n
#emit ADD
#emit STOR.S.pri arg_start

do
{
#emit LOAD.I
#emit PUSH.pri
arg_end -= 4;
#emit LOAD.S.pri arg_end
}
while(arg_end > arg_start);

#emit PUSH.S message
#emit PUSH.C 145
#emit PUSH.ADR fstring

n += 4 * ARGUMENTS;

#emit PUSH.S n
#emit SYSREQ.C format

n += 4;
#emit LCTRL 4
#emit LOAD.S.alt n
#emit ADD
#emit SCTRL 4

return SendClientMessage(playerid, col, fstring);
}
[/pawn]

SendClientMessage_ aura aussi besoin de la fonction FIX_SYSREQ. (cette fonction est lа pour empкcher le compilateur de crash sur une erreur de native non enregistrйe lorsqu'on utilise cette native via #emit SYSREQ.C)
Reply
#13

Ce serait largement mieux d'utiliser [URL="https://sampwiki.blast.hk/wiki/SendPlayerMessageToAll_FR"]SendPlayerMessageToAll[/URL] pour le premier message, зa йvite de rйcupйrer le nom du joueur et la couleur s'adapte а celle du joueur comme un vrai message

A la place de faire "strmid(str2, phrase, 70, strlen(phrase));", tu peux faire
[pawn]format(str2, sizeof(str2), phrase[70])[/pawn]
A la place de faire "strmid(phrase2, phrase, 0, 70);", tu peux йviter d'utiliser une autre variable et faire
[pawn]phrase[70] = EOS;[/pawn]

etc etc, je laisse S4t3K s'occuper du reste uhuhu
Reply
#14

@Kilou : Je vois pas ce que je peux dire de plus, sйrieusement ._.

Sinon, une petite fonction toute mignonne (en deux versions) qui permet d'inverser un nombre

[pawn]

stock neg(const &nbr)
{
#emit LOAD.S.pri nbr
#emit NEG
#emit STOR.S.pri nbr
return true;
}


// version deux

stock neg(const &nbr)
{
nbr -= -1;
return true;
}[/pawn]

Je vous conseille d'utiliser la premiиre version (la deuxiиme existe juste pour que je m'entraine sur #emit ptdr)



Une autre fonction qui permet de check si un nombre est pair ou impar (retourne true si le nombre est pair et false si le nombre est impar)

[pawn]

stock pair(const nbr)
{
return (nbr % 2 == 0);
}
[/pawn]
Reply
#15

Bien vue pour le "SendMessage" s4t3k, tu m'apprend des truck au niveau de la syntax, je connaisais le goto pour d'autre programme mais j'ai jamais songer а l'utiliser en pwn :).

@Kilou : J'utilise le strmid par abitude mais explique moi le fonctionnement de EOS, je connais mais j'en ai pas l'utilitй, mais j'aimerais bien savoir quand mкme ^^
Reply
#16

EOS = NULL = '\0'
Reply
#17

S4t3K;3133193 Wrote:EOS = NULL = '\0'
Non
EOS n'est pas йgal а null, EOS est йgal а 0 et а '\0' certes, mais non EOS n'est pas йgal а null
EOS = End Of String (fin de chaоne en franзais), c'est le caractиre qui indiquera la fin de la chaоne
Et donc, mettre EOS en plein milieu d'une chaоne indiquera que la chaоne se terminera lа, et donc le reste de la chaоne ne sera jamais utilisй
[pawn]new string[] = "Salut ! S4t3k est nul D:";
string[7] = EOS;
print(string);
//affichera "Salut !"[/pawn]
Les mйthodes suivantes sont aussi possibles:
[pawn]string[7] = 0;
string[7] = '\0';[/pawn]
Reply
#18

Un petit truc (plus une astuce qu'autre chose) : faire une boucle sur chaque йlйment d'un enum sans tag mismatch (Merci а ******) :

[pawn]

enum infos (<<= 1)
{
pMoney,
pLevel,
pDrugs,
pMats,
pHome,
pVeh,
pWeapMain,
};

new gInfo[infos];

// dans une fonction

for(new i = 0; i < :_infos; i++)
{
if(tagof(gInfos[infos:i]) == tagof(Float:)) printf("%f", gInfos[infos:i]), continue;
if(gInfos[infos:i][1]) printf(gInfos[infos:i]), continue;
printf("%d", gInfos[infos:i]);
}
[/pawn]
Reply
#19

Une fonction qui permet de "split" un datetime SQL passй en paramиtre en 6 variables (annйe, mois, jour, heures, minutes, secondes) passйes par rйfйrence :

[pawn]

stock SplitDateTime(datetime[20], &annee, &mois, &jour, &heure, &minute, &seconde)
{
new tmp[5], copy[20];
copy = datetime;

strmid(tmp, copy, 0, 4);
strdel(copy, 0, 5);
annee = strval(tmp);

strmid(tmp, copy, 0, 2);
strdel(copy, 0, 3);
mois = strval(tmp);

strmid(tmp, copy, 0, 2);
strdel(copy, 0, 3);
jour = strval(tmp);

strmid(tmp, copy, 0, 2);
strdel(copy, 0, 3);
heure = strval(tmp);

strmid(tmp, copy, 0, 2);
strdel(copy, 0, 3);
minute = strval(tmp);

strmid(tmp, copy, 0, 2);
strdel(copy, 0, 3);
seconde = strval(tmp);
}[/pawn]


PS : J'ai pas vraiment moyen de l'optimiser
Reply
#20

Quote:PS : J'ai pas vraiment moyen de l'optimiser
Tu pourrais йviter de faire des strdel а tout va en utilisant un index, essaie cela (j'sais pas comment je pourrais le tester uhu):
[pawn]stock SplitDateTime(datetime[20], &annee, &mois, &jour, &heure, &minute, &seconde)
{
new tmp[5], index = 0;

strmid(tmp, copy, 0, 4);
index += 5;
annee = strval(tmp);

strmid(tmp, copy, index, index + 2);
index += 3;
mois = strval(tmp);

strmid(tmp, copy, index, index + 2);
index += 3;
jour = strval(tmp);

strmid(tmp, copy, index, index + 2);
index += 3;
heure = strval(tmp);

strmid(tmp, copy, index, index + 2);
index += 3;
minute = strval(tmp);

strmid(tmp, copy, index, index + 2);
index += 3;
seconde = strval(tmp);
}[/pawn]
Aprиs, y'a moyen d'encore plus optimiser en se passant de tout strmid / index / strval: vu que la position des chiffres est toujours la mкme dans la chaоne, tu peux aisйment coller зa sur une variable sans devoir l'extraire et utiliser un strval

Donne-moi donc une chaоne en guise d'exemple que je puisse faire зa
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)