C_far

Fonctions & Astuces

90 messages dans ce sujet

Yo, j'reposte un peu dans ce sujet, j'viens de coder en 20 minutes une fonction qui permet d'obtenir le vrai DATA de l'AMX :

stock GetAmxRealData()
{
	/*
		reg.x = registre ...
		hdr.x = header ...
		seg.x = segment ...
		var.x = variable ...
	*/

	new
		addr,
		cod,
		base;
		
	#emit LCTRL 1 // reg.pri = hdr.data
	#emit NEG // reg.pri = -reg.pri
	#emit ADD.C 12 // reg.pri += 12
	#emit STOR.S.pri addr // var.addr = reg.pri
	
	#emit LREF.S.pri addr // reg.pri = *(seg.data + var.addr)
	#emit STOR.S.pri cod // var.cod = reg.pri
	addr += 4;
	
	#emit LREF.S.pri addr // reg.pri = *(seg.data + var.addr)
	#emit NEG // reg.pri = -reg.pri
	#emit STOR.S.pri base // var.base = reg.pri
	cod += base;
		
	amx_nothing();
	
	#emit LCTRL 6 // reg.pri = seg.cip
	#emit ADD.C 0xFFFFFFF4 // reg.pri += 0xFFFFFFF4 (-12) = reg.pri -= 12 (SUB.C n'existe pas/doesn't exist)
	#emit LOAD.S.alt cod // reg.alt = var.cod
	#emit ADD // reg.pri += reg.alt
	#emit STOR.S.pri addr // var.addr = reg.pri
	#emit LREF.S.pri addr // reg.pri = *(seg.data + var.addr)
	#emit SUB // reg.pri -= reg.alt
	#emit CONST.alt amx_nothing 
	#emit SUB // reg.pri -= reg.alt
	#emit MOVE.alt // reg.alt = reg.pri
	#emit LCTRL 1 // reg.pri = hdr.data
	#emit XCHG // reg.pri = reg.alt | reg.alt = reg.pri
	#emit SUB // reg.pri -= reg.alt
	#emit STOR.S.pri addr // var.addr = reg.pri (addr = real address)
	
	return addr - base;
}

 

Modifié par Dutheil

Partager ce message


Lien à poster
Partager sur d’autres sites

Fonction pour obtenir l'adresse locale d'une variable.

stock GetLocalAddress(...)
{
	#emit LOAD.S.pri 12
	#emit LOAD.S.alt 0
	#emit SUB
	#emit RETN

	return 0;
}

 

Partager ce message


Lien à poster
Partager sur d’autres sites

Fonction pour obtenir l'adresse relative d'une variable.

stock GetRelativeAddress(...)
{
	#emit LOAD.S.pri 12
	#emit RETN

	return 0;
}

 

Partager ce message


Lien à poster
Partager sur d’autres sites

J'ai édité le poste et optimisé la fonction GetAmxRealData en supprimant une variable et en modifiant quelques lignes pour diminuer la consommation.

Edit : J'ai ajouté des commentaires au code.

 

Un exemple d'utilisation des trois dernières fonctions postées :

#include "a_samp"

stock
	DATA;

main()
{
	DATA = GetAmxRealData();

	new
		a = 123456789,
		b = 987654321,
		address;
	
	print("\nVariable 'a'");
	
	address = GetLocalAddress(a);
	printf("Local address = %d | 0x%08x", address, address);
	
	address = GetRelativeAddress(a);
	printf("Relative address = %d | 0x%08x", address, address);
	
	address += DATA;
	printf("Global address = %d | 0x%08x", address, address);
	
	print("\nVariable 'b'");
	
	address = GetLocalAddress(b);
	printf("Local address = %d | 0x%08x", address, address);
	
	address = GetRelativeAddress(b);
	printf("Relative address = %d | 0x%08x", address, address);
	
	address += DATA;
	printf("Global address = %d | 0x%08x", address, address);	
}

Vous pourrez constater que les adresses globales sont bonnes grâce à Cheat Engine par exemple :

f4065b9f28a84bdaaac83a7974f67ccf.png

Modifié par Dutheil

Partager ce message


Lien à poster
Partager sur d’autres sites

Random functions

GetNearestPlayer(playerid) 
{ 
    if(!IsPlayerConnected(playerid)) return 0; 
     
    static  Float:x, 
            Float:y, 
            Float:z; 
    new        Float:distance = 999.1, 
            player = playerid; 

    for(new i=1; i<GetPlayerPoolSize(); i++) 
    { 
        GetPlayerPos(i, x, y, z); 
        if(GetPlayerDistanceFromPoint(playerid, x, y, z) > distance) continue; 
        else distance = GetPlayerDistanceFromPoint(playerid, x, y, z), player = i; 
    } 
    return player == playerid ? -1 : player; 
} 

//------------------------------------------------------------------------------------------------

IsARPName(const playername[MAX_PLAYER_NAME]) 
{ 
    if(strfind(playername, "_", true) == -1) return false; 

    new psize = strlen(playername); 

    for(new i; i < psize; i++) 
    { 
        if(playername[i] == '_') continue; 
        if('A' > playername[i] || playername[i] > 'Z' && playername[i] < 'a' || playername[i] > 'z') return false; 
    } 
    return true; 
} 

//------------------------------------------------------------------------------------------------

ErrorMessage(playerid, const msg[], va_args<>) 
{ 
    static strinng[200], second[100]; 

    format(second, sizeof(second), "[Error] {FF0000}%s", msg); 
    va_format(strinng, sizeof(strinng), second, va_start<2>); 

    return SendClientMessage(playerid, 0xCC0000FF, strinng); 
} 

//------------------------------------------------------------------------------------------------

IsPlayerConnectedByName(const name[])
{
    foreach(new i : Player)
    {
        if(strcmp(name, GetName(i))) continue;
        return true;
    }
    return false;
} 

//------------------------------------------------------------------------------------------------

GetIDByName(const name[])
{
    foreach(new i : Player)
    {
        if(!strcmp(GetName(i), name)) return i;
    }
    printf("Error : No player found for the name '%s'.", name);
    return -1;
}

//------------------------------------------------------------------------------------------------

SCMF(playerid, couleur, const msg[], va_args<>) 
{ 
    static 
        string[145]; 

    va_format(string, sizeof(string), msg, va_start<3>); 
    return SendClientMessage(playerid, couleur, string); 
} 

//------------------------------------------------------------------------------------------------

SendClientMessageToAllEx(color, const message[], va_args<>) 
{ 
    static msg[190]; 
    va_format(msg, sizeof(msg), message, va_start<2>); 

    return SendClientMessageToAll(color, msg); 
}  

 

Modifié par Dayrion

Partager ce message


Lien à poster
Partager sur d’autres sites
// Retourne le nom d'un joueur
stock PlayerName(playerid)
{
	if(I_PlayerName[playerid][0] == EOS)
	{
		GetPlayerName(playerid, I_PlayerName[playerid], MAX_PLAYER_NAME);
	}
	return I_PlayerName[playerid];
}

// Retourne l'IP d'un joueur
stock PlayerIP(playerid)
{
    if(I_PlayerIP[playerid][0] == EOS)
	{
		GetPlayerIp(playerid, I_PlayerIP[playerid], 16);
	}
	return I_PlayerIP[playerid];
}

 

 

-> Définir I_PlayerIP + le nom.

+ "16" est pas une bonne pratique, préférez utiliser une variable de pré-processeur par exemple.

 

 

Cela permet de retourner le nom/l'IP d'un joueur sans déclarer à chaque fois un tableau, et appeler tout le bazard habituel.

 

NE PAS OUBLIER OnConnect/Disconnect :

 

// Réinitialise les variables internes liées à un joueur
stock ResetInternalPlayerVar(playerid)
{
	if(playerid < MAX_PLAYERS)
	{
		I_PlayerName[playerid][0] = EOS;
		I_PlayerISP[playerid][0] = EOS;
    }
}

 

Partager ce message


Lien à poster
Partager sur d’autres sites

Créer un cercle avec un objet et récupérer les coordonnées de son centre:

CreateCircle(objectid, Float:x, Float:y, Float:z, Float:size, &Float:valA2, &Float:valB2, &Float:valC2)
{
	new Float:valx2,
		Float:valy2,
		Float:valz2;

	for(new i; i < 360; i++) // 3498 - 1214
	{
		if(i == 180)
		{
			valx2 = x;
			valy2 = y;
			valz2 = z;
		}

		x = x+size*floatcos(i,degrees);
      	y = y+size*floatsin(i,degrees);
      
      	if(objectid != 0) CreateObject(objectid, x, y, z, 0.0, 0.0, 0.0);
	}
	GetCoordMid2Pts(valx2, valy2, valz2, x, y, z, valA2, valB2, valC2);
}

stock GetCoordMid2Pts(Float:x1, Float:y1, Float:z1, Float:x2, Float:y2, Float:z2, &Float:rX, &Float:rY, &Float:rZ)
{
	rX = (x1+x2)/2;
	rY = (y1+y2)/2; 
	rZ = (z1+z2)/2;
}

 

Modifié par Dayrion

Partager ce message


Lien à poster
Partager sur d’autres sites

IsVehicleInRangeOfPoint:

stock IsVehicleInRangeOfPoint(vehicleid, Float:range, Float:x, Float:y, Float:z)
{
	new Float:x1,
		Float:y1,
		Float:z1;

	CreateCircle(0, x, y, z, range*0.01, x1, y1, z1);

	GetVehiclePos(vehicleid, x, y, z);

	new Float:dist = GetDistanceBetween2Points(x, y, z, x1, y1, z1);
  
	if(dist < range) 
		return true;
	else
		return false;
}

stock GetNearestVehicleByCoord(Float:x, Float:y, Float:z, Float:precision = 2.0)
{
	new	vehicle = INVALID_VEHICLE_ID;

	for(new i=1; i<MAX_VEHICLES; i++)
	{
		if(GetVehicleDistanceFromPoint(i, x, y, z) == 0.0)
		{
			if(i > GetVehiclePoolSize()) return vehicle;
			else continue;
		}
		if(GetVehicleDistanceFromPoint(i, x, y, z) > precision) continue;
		else precision = GetVehicleDistanceFromPoint(i, x, y, z), vehicle = i;
	}
	return vehicle;
}

stock Float:GetDistanceBetween2Points(Float:x1, Float:y1, Float:z1, Float:x2, Float:y2, Float:z2)
{
    return VectorSize(x1-x2, y1-y2, z1-z2);
}

CMD:exemple(playerid)
{
	new Float:x, 
		Float:y,
		Float:z;
	
	GetVehiclePos(GetPlayerVehicleID(playerid), x, y, z);

	if(IsVehicleInRangeOfPoint(1, 10, x, y, z)) 
		return SCM(playerid, GREEN, "In range!");
	else
		return SCM(playerid, RED, "Out of range");
}

J'attends vos avis & conseils avec impatience.

Modifié par Dayrion

Partager ce message


Lien à poster
Partager sur d’autres sites
Il y a 13 heures, Dayrion a dit :

floatround(floatsqroot(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2 )) + ((z1 - z2) * (z1 - z2))));

BEURK !!

 

Tiens, look ça : https://wiki.sa-mp.com/wiki/VectorSize

Partager ce message


Lien à poster
Partager sur d’autres sites
Il y a 14 heures, C_far a dit :

BEURK !!

 

Tiens, look ça : https://wiki.sa-mp.com/wiki/VectorSize

Désolé, je savais pas que cette fonction existée et qu'elle retournée la norme d'un vecteur. Je me suis basé sur la fonction de base. :$

Je modif' ça.

Partager ce message


Lien à poster
Partager sur d’autres sites
Il y a 2 heures, Dayrion a dit :

Désolé, je savais pas que cette fonction existée et qu'elle retournée la norme d'un vecteur. Je me suis basé sur la fonction de base. :$

Je modif' ça.

Au lieu d'en faire une fonction, fais une macro (#define)

Modifié par C_far

Partager ce message


Lien à poster
Partager sur d’autres sites

Avoir une date depuis le UNIX Timestamp (du gettime()):

TimeToDate(time, &annee = 0, &mois = 0, &jour = 0, &heure = 0, &minute = 0, &seconds = 0)
{
	seconds = time % 60;
	minute = time / 60;
	heure = minute / 60;
	if(minute >= 60)
		minute %= 60;

	jour = heure / 24;
	if(heure >= 24)
		heure %= 24;

	mois 	= jour / 30;
	if(jour >= 30)
		heure %= 30;

	annee = mois / 12;
	if(mois >= 12)
		mois %= 12;
}

 

Partager ce message


Lien à poster
Partager sur d’autres sites
il y a 34 minutes, Dayrion a dit :

Avoir une date depuis le UNIX Timestamp (du gettime()):

TimeToDate(time, &annee = 0, &mois = 0, &jour = 0, &heure = 0, &minute = 0, &seconds = 0)
{
	seconds = time % 60;
	minute = time / 60;
	heure = minute / 60;
	if(minute >= 60)
		minute %= 60;

	jour = heure / 24;
	if(heure >= 24)
		heure %= 24;

	mois 	= jour / 30;
	if(jour >= 30)
		heure %= 30;

	annee = mois / 12;
	if(mois >= 12)
		mois %= 12;
}

 

Sera incorrect car il faut prendre en compte :

- Les années bissextiles donc : le nombre de jour dans le mois de février

- Les mois qui ont 31 jours

 

Edit : voir ceci : https://github.com/Crayder/Time-Conversion/blob/master/timestamp.inc

Modifié par C_far

Partager ce message


Lien à poster
Partager sur d’autres sites

random modifié.

randomEx(min, max, ...) // random avec min & max et nombre exclus. Ex: randomEx(0, 5, 3, 4) : Random entre 0 & 5 en excluant les nombres 3 & 4 (ils tomberont jamais) | Prend les nombres négatifs
// Ici max est compris dans les nombres aléatoires car.. je l'ai tjrs vus comme ça
{
	max++;
	new
		maxarg = numargs()-1,
		nb = random(max - min) + min;

	while(maxarg+1 != 2)
	{
		if(nb == getarg(maxarg))
		{
			maxarg = numargs()-1;
			nb = random(max - min) + min;
		}
		else
			maxarg--;
	}
	
	return nb;
}

 

Modifié par Dayrion

Partager ce message


Lien à poster
Partager sur d’autres sites
Il y a 8 heures, Dayrion a dit :

random modifié.

Fonction super utile !

Partager ce message


Lien à poster
Partager sur d’autres sites

Une autre, un peu moins utile.
 

NumberWithSign(number, const sign[2] = ".") // permet d'avoir des nombres plus faciles à la lecture : 999999999 = 999.999.999
{
	new
		str[10 + EOS],
		bool:negative;
	
	if(number < 0)
	{
		negative = true;
		number = 0 - number;
	}

	format(str, sizeof(str), "%i", number);

	for(new j = strlen(str)-3; j > 0; j -= 3)
		strins(str, sign, j);

	if(negative)
		format(str, sizeof(str), "-%s", str);

	return str;
}

 

Partager ce message


Lien à poster
Partager sur d’autres sites

Changer la valeur de deux nombres sans utiliser de troisième.

ReverseNumber(&a, &b)
	a = a + b - (b = a);

 

Partager ce message


Lien à poster
Partager sur d’autres sites
Il y a 1 heure, Dayrion a dit :

Changer la valeur de deux nombres sans utiliser de troisième.

ReverseNumber(&a, &b)
	a = a + b - (b = a);

 

Cette fonction porte un nom, c'est swap().

 

Sinon ta méthode est plus lente que de créer une variable locale dans la fonction.

Si on veut vraiment faire une fonction rapide et sans créer de nouvelle variable :

swap(&a, &b)
{
	#emit LREF.S.pri a
	#emit LREF.S.alt b
	#emit SREF.S.pri b
	#emit SREF.S.alt a
}

 

1 personne aime ça

Partager ce message


Lien à poster
Partager sur d’autres sites
Il y a 6 heures, C_far a dit :

Cette fonction porte un nom, c'est swap().

 

Sinon ta méthode est plus lente que de créer une variable locale dans la fonction.

Si on veut vraiment faire une fonction rapide et sans créer de nouvelle variable :

swap(&a, &b)
{
	#emit LREF.S.pri a
	#emit LREF.S.alt b
	#emit SREF.S.pri b
	#emit SREF.S.alt a
}

 

Pourquoi elle est plus lente?

Partager ce message


Lien à poster
Partager sur d’autres sites
Il y a 5 heures, Dayrion a dit :

Pourquoi elle est plus lente?

 

Ta fonction :

swap(&a, &b)
{
	a = a + b - (b = a);
}

 

proc	; swap
lref.s.pri c
push.pri
lref.s.pri 10
pop.alt
add
push.pri
lref.s.pri c
sref.s.pri 10
pop.alt
sub.alt
sref.s.pri c
zero.pri
retn

 

La fonction simple :

swap(&a, &b)
{
	new
		c = a;
		
	a = b;
	b = c;
}

 

proc	; swap
stack fffffffc
lref.s.pri c
stor.s.pri fffffffc
lref.s.pri 10
sref.s.pri c
load.s.pri fffffffc
sref.s.pri 10
stack 4
zero.pri
retn

 

Modifié par C_far

Partager ce message


Lien à poster
Partager sur d’autres sites

Une pour ceux qui un peu flemmard sur les bords. :$

Inclusion(ref, min, max)
	return ref >= min && ref <= max ? true : false; 

 

Partager ce message


Lien à poster
Partager sur d’autres sites

Je vais peut être me planter mais ont est la pour sa ^^

WarnBadPingPlayer(playerid)
{
	if (GetPlayerPing(playerid) > 150);
    	SendClientMessage(playerid, -1, "Attention, votre ping est instable);
	return 1;
}

J'ai pas tester mais si c'est ok faite moi signe ^^

Modifié par Foobar

Partager ce message


Lien à poster
Partager sur d’autres sites
il y a 34 minutes, Foobar a dit :

Je vais peut être me planter mais ont est la pour sa ^^

WarnBadPingPlayer(playerid)
{
	if (GetPlayerPing(playerid) > 150);
    	SendClientMessage(playerid, -1, "Attention, votre ping est instable);
	return 1;
}

J'ai pas tester mais si c'est ok faite moi signe ^^

En soit ta fonction est correcte mais elle n'est pas valable, car le ping est mesuré en millisecondes et il symbolise le temps de réponse entre deux ordinateurs. Donc il est normal pour quelqu'un en campagne, au bled ou au Québec d'avoir souvent un ping comme ça quand le serveur est hébergé en France !

Partager ce message


Lien à poster
Partager sur d’autres sites
il y a 34 minutes, C_far a dit :

En soit ta fonction est correcte mais elle n'est pas valable, car le ping est mesuré en millisecondes et il symbolise le temps de réponse entre deux ordinateurs. Donc il est normal pour quelqu'un en campagne, au bled ou au Québec d'avoir souvent un ping comme ça quand le serveur est hébergé en France !

J'y ai penser juster après avoir poster mais en cherchant un peut je pense qu'il y a possibilité de trouver un juste millieu pour chaque pays étranger "Francophone". Mais entre nous j'ai fait sa vraiment rapidement.

Partager ce message


Lien à poster
Partager sur d’autres sites

J'ai réfléchi un peu sur mon code pour "l’optimiser", j'ai pris model sur la connexion d'un ami algérien sur mon Teamspeak héberger dans le nord de la France. Il à 80ms et 0.02% de paquet perdu donc sa connexion est stable même à 80ms. Donc mon code et bon comme tu as dis mais on va plutôt récupérer les paquet perdu.

WarnBadPingPlayer(playerid)
{
	if (NetStats_PacketLossPercent(playerid) > 1.0%)
    	SendClientMessage(playerid, -1, "Attention, votre connexion est instable);
	return 1;
}

Enfin j'espère j'ai pas encore toute les compétences nécessaire pour confirmer ce code à vous de me dire ci le NetStats samp est logique. Et si ce code fonctionne ont pourraient l'utiliser pour l'état de connexion du serveur et prévenir les joueurs que le serveur reçoit une attaque ou simplement reçoit une perte de connexion.

Modifié par Foobar

Partager ce message


Lien à poster
Partager sur d’autres sites

Créer un compte ou se connecter pour commenter

Vous devez être membre afin de pouvoir déposer un commentaire

Créer un compte

Créez un compte sur notre communauté. C’est facile !


Créer un nouveau compte

Se connecter

Vous avez déjà un compte ? Connectez-vous ici.


Connectez-vous maintenant