Skocz do zawartości
bocian941

Przydatne funkcje

Rekomendowane odpowiedzi

mix_string

 

Jak sama nazwa wskazuje jest to funkcja do mieszania "stringów" tj. ciągów znaków. (zrobiona na prośbę drifter997).

Parametry:

  • string[] - tablica z ciągiem znaków
  • max_swap - maksymalna ilość zamian, domyślnie 0 czyli sizeof(string) (aby kod nie było zbyt trudny do odgadnięcia)
  • size - domyślnie sizeof(string)
stock mix_string(string[], max_swap=0, size = sizeof string)
{
	new swap;
	for(new i=0; string[i]; i++)
	{
		if( max_swap > 0 && max_swap == swap ) break;
		
		new tmp = string[i], swit = random(size-1);
		
		string[i] = string[swit];
		string[swit] = tmp;
		swap++;
	}
	return string;
}

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

        char_replace

Jak sama nazwa wskazuje jest to funkcja taka sama jak funkcja CeKi niestety jego nie działa

printf("printf: %s", ReplaceCharacter("mrdrifter to ładna dupa ;->", "mrdrifter", "Maniek1997")); efekt:       OK.printf:  to ładna dupa ;->Maniek1997

Więc postanowiłem napisać swoją funkcję. Udało mi się napisać dużo szybszą i sprawniejszą. 

[17:57:12] Filterscript 't.amx' unload failed.

[17:57:12] Checking natives...
[17:57:12] OK.
[17:57:13] [CeKa] zmienono 10000 razy w 873 ms
[17:57:13] [mrdrifter] zmienono 10000 razy w 4 ms

[17:57:13] Filterscript 't.amx' loaded.

Kod testu

 

Parametry: 

  • buffer_ - Napis w którym ma być zmiana
  • ch - co ma zmienić
  • ch2 - zamiennik
  • chars_size - true - nie zwraca uwagi na wielkość liter. false - zwraca uwagę.
stock char_replace(buffer_[512], ch[], ch2[], bool:chars_size = false)
{
	new f;
	
	f = strfind( buffer_, ch, chars_size );
	while ( f >= 0)
	{
		strdel( buffer_, f, f+strlen(ch) );
		strins( buffer_, ch2, f );
		f = strfind( buffer_, ch, chars_size);
	}

	return buffer_;
}

Życzę miłego korzystania.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

IsEmail

Opis działania: Funkcja sprawdza, czy podany tekst jest adresem e-mail, czy nie. Jeżeli nie znajdzie w tekście znaków @ oraz . lub znajdzie je wielokrotnie (w przypadku kropki dopuszcza się jedną przed małpą i jedną po małpie) lub którąkolwiek z nich znajdzie na początku lub końcu tekstu, to zwraca zero. Jeżeli po ostatniej kropce tekst będzie dłuższy niż 3 znaki - zwraca zero. Jeżeli pomiędzy znakiem @, a . nie będzie żadnej treści, zwraca zero. Jeżeli w tekście użyjemy znaków spoza zakresu alfabetu łacińskiego, cyfr arabskich oraz tzw. twardej spacji (_) - zwraca zero. Po przeskanowaniu całego tekstu pod kątem elementów nie stanowiących budowy adresu e-mail, zwróci wartość dodatnią - 1.
Argumenty:
- txt[] - Treść do sprawdzenia.
Zwracanie:
- 0 - W przypadku błędnej treści (nie będącej adresem e-mail)
- 1 - W przypadku prawidłowej treści (będącej adresem e-mail)
Autor: drzymalsw
Kod funkcji:





stock IsEmail(txt[]) //by drzymalsw
{
	new g[5];
	for(new c; txt[c]; c++)
	{
		if(txt[c] == '@')
		{
			if(c==0) return 0;
			if(g[1]) return 0;
			if(g[0]) return 0;
			g[0] = 1;
			continue;
		}
		if(g[0] && txt[c] != '.') g[2] ++;
		if(txt[c] == '.')
		{
			if(c==0) return 0;
			if(c==strlen(txt)-1) return 0;
			if(!g[0])
			{
				if(g[4]) return 0;
				else
				{
					g[4] = 1;
					continue;
				}
			}
			if(g[1]) return 0;
			if(!g[2]) return 0;
			g[1] = 1;
			continue;
		}
		if(g[1])
		{
			g[3] ++;
			if(g[3] > 3) return 0;
		}
		if(((txt[c] < 65 && (txt[c] > 57 || txt[c] < 48)) || txt[c] > 122 || (txt[c] > 90 && txt[c] < 97)) && txt[c] != '_') return 0;
	}
	
	if(!g[0] || !g[1]) return 0;
	return 1;
}
Edytowane przez drzymalsw

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

IsMail

Działa tak samo co funkcja napisana powyżej. Tylko, że w formie *Regex.

Kod:

stock IsMail(const text[])
{
	static
		RegEx:rMail;
	if(!rMail) rMail = regex_build("[a-zA-Z0-9_\\.]+@([a-zA-Z0-9\\-]+\\.)+[a-zA-Z]{2,4}");
	return regex_match_exid(text, rMail);
}

Przyklad:

new buf[24] = "mojmail@domena.com";
if(IsMail(buf)) 
{
   print("mail poprawny");
} else print("mail niepoprawny!");
Parametry w RegEx staralem sie dobrac optymalnie, dzieki czemu sprawdzanie ciagu znakow jest dość szybkie.

Uwagi:

1) * - Do działania potrzebna wtyczka RegEx.

2) W razie naglych crash-y serwera podczas jego zamykania lub uzycia komendy RCON: gmx - nalezy uzyc w OnGameModeExit: regex_delete_all();

3) Do tej funkcji zamiast 'static' mozna utworzyc globalna zmienna. Gdzie usuniecie procesu Regexa bedzie proste:

new RegEx:moj_regexowy_proces; // globalna

// W IsMail zamiast rMail dajemy moj_regexowy_proces, w tym usuwany 'static RegEx:rMail'
// W OnGameModeExit dajemy:
regex_delete(moj_regexowy_proces);
Edytowane przez FJT

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

@UP2 Twoja funkcja źle działa.

	printf(" Emial marcincotoejst@wp.pl jest %s a email lubie@i. jest %s",(IsEmail("marcincotoejst@wp.pl") == 1) ? ("Dobry"): ("Zył"), (IsEmail("lubie@i.") == 1) ? ("Dobry"): ("Zły"));

 

 Emial marcincotoejst@wp.pl jest Dobry a email lubie@i. jest Dobry

 

@UP twój z forum samp xd

 

dla tych którzy nie chcą używać źle działające funkcji bądź specjalnie pluginu regex ( który często się crashuje przy rcon exit ), a używają sscanf polecam moją funkcje mailed.

Kod testu funkcji mailed

#include <a_samp>
#include <sscanf2>


public OnFilterScriptInit(){
	printf(" Emial marcincotoejst@wp.pl jest %s a email lubie@i. jest %s",(mailed("marcincotoejst@wp.pl") == 1) ? ("Dobry"): ("Zył"), (mailed("lubie@i.") == 1) ? ("Dobry"): ("Zły"));
	return 1;
}
stock mailed(const buffer_mail[]) //by drzymalsw
{
	new mail[3][31];
	if( !sscanf( buffer_mail, "p<@>s[30]s[10]", mail[0], mail[1] ) ){
		if( !sscanf( mail[1], "p<.>s[30]s[10]", mail[0], mail[1] ) ){
			if( strlen(mail[0]) > 1 &&   strlen( mail[1] ) > 1 ) return 1; 
		}
		else return 0;
	} else return 0;
	return 0;
}

efekt:

 

Emial marcincotoejst@wp.pl jest Dobry a email lubie@i. jest Zły

 

Więc jeśli używasz sscanf - nie zastanawiaj się użyj mojej funkcji.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Hej, czemu piszesz "źle działających funkcji"? Moja funkcja działa dobrze, testowałem dziś. W dodatku nie używa żadnych pluginów i jest dość szybka, do tego nie zajmuje zbyt dużo pamięci.

W dodatku moja funkcja sprawdzająca, czy tekst jest adresem e-mail sprawdza przy okazji czy użyte zostały właściwe znaki, a na przykład dla Twojej funkcji, drifter997, można by napisać przykładowo darek^%&*otwórz@onet.smoleńsk i pokazałoby, że adres jest prawidłowy.

To nie żaden atak na żadnego z Was, Panowie, ale po prostu chciałem zauważyć, że jak na razie moja funkcja najpewniej sprawdza treść adresu.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Wierze że nie jest atak na nas - to jest obrona siebie. 

 

chodzi tutaj oto że działa tylko moja funkcja i Axv. Nie będę się rozpisywał zobacz sam.

sF819DK.jpg

Popatrz też na milisekundy. 

 

Kod testu: http://pastebin.com/26xkferm

Edytowane przez drifter997

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Aaa, gdy testowałem różne pokręcone wersje adresów, musiałem zapomnieć o formie kropki na końcu. Zaraz coś wykombinuję ;) Dzięki za cynk.
@edit, zrobione. Funkcja sprawdzała, czy dany znak jest ostatnim znakiem w tekście warunkiem if(c==strlen(txt)) - funkcja strlen zwraca faktyczną długość tekstu, a więc ostatni znak tekstu będzie zawsze o 1 mniejszy, bo pierwszy ma wartość 0. ;) Już działa dobrze.

Edytowane przez drzymalsw

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

visible_vehicles

 

Opis: Funkcja szuka najbliszego pojazdu przy graczu, jeśli nie znajdzie zwraca INVALID_VEHICLE_ID. 
Parametry:

  • playerid: ID Gracza, koło którego szukamy pojazdu

Zwracanie:

  • w przypadku znalezienia pojazdu w pobliżu gracza zwraca id pojazdu w przypadku nie znalezienia zwraca INVALID_VEHICLE_ID

Kod:

stock visible_vehicles(playerid){

	new Float:distrace,Float:pos[ 4 ], vid ;
	GetPlayerPos( playerid, pos[0], pos[1], pos[2] );

	for(new i;i<MAX_VEHICLES;i++){
		distrace = GetVehicleDistanceFromPoint(i, pos[0], pos[1], pos[2] );
		if( distrace == 0.0 ) continue;
		if( distrace <= pos[ 3 ] ){	
			pos[ 3 ] = distrace;
			vid = i;
		}else if( pos[ 3 ] == 0.0 ){
			pos[ 3 ] = 5000.0;
		}
	}
	if( pos[ 3 ] != 5000.0 ){
		return vid;
	}
	return INVALID_VEHICLE_ID;
}

Przykład użycia.

CMD:puth_to_vehicle( playerid, params[] ){
	
	new vehicle = visible_vehicles(playerid);
	if( vehicle == INVALID_VEHICLE_ID ) return 0;
	printf("vid %d", vehicle);
	PutPlayerInVehicle( playerid, vehicle, 0);
	
	return 1;
}

:)

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

PlayerIP
Funkcja sprawdza i zwraca ip podanego gracza.
Użycie : PlayerIP(playerid);


stock PlayerIP(playerid)
{
    new pIP[16];
    GetPlayerIp(playerid,pIP,sizeof pIP);
    return pIP;
}

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

CheckNumberAndLetter

 

Opis: Funkcja szuka w tekście liter oraz cyfr. Jeżeli w tekście będą litery i cyfry zwróci 1, jeśli w tekście będą same cyfry zwróci 0, jeśli w tekście będą same litery zwróci 0.

Parametry: str - ciąg znaków.

Zastosowanie:

 

CheckNumberAndLetter("MlodyMaKota") - Zwróci 0.
CheckNumberAndLetter("696969") - Zwróci 0.
CheckNumberAndLetter("MlodyMaKota696969") - Zwróci 1.

 

Kod: http://pastebin.com/gj717AiU

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Maniek, mówiłeś wczoraj żebym zajrzał do twojej funkcji. Proszę, poprawiłem teraz wykonuje się troszku szybciej.

stock CheckNumberAndLetter(str[]) // By Mlody954
{
        static bool:z[2];
		z[0] = false;
		z[1] = false;
        for(new x, l2 = strlen(str); x != l2; x++)
        {
				if(((str[x] >= 'a' && str[x] <= 'z') || (str[x] >= 'A' && str[x] <= 'Z')) && !z[0])
					z[0] = true;
                
 
                if((str[x] >= '0' && str[x] <= '9') && !z[1])
					z[1] = true;
                
 
                if((z[0]) && (z[1])) break;
        }
 
        if((!z[0]) || (!z[1])) return false;
        else return true;
}

vfxd.png

 

"c -> 43" to Twój kod bez mojej edycji. 

Edytowane przez drifter997

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Funkcja napisana z nudów, z tel, sorki za brak ułożenia, ale na tel nie ma TABa

CheckPlayerNextToPlayer(playerid, playerid2, range)

Funkcja sprawdza czy gracze są obok Siebie. Zwraca fałsz (0) jeżeli nie są, a prawdę (1) jeżeli są.

playerid - Gracz pierwszy

playerid2 - Gracz drugi

range - Odległość w jakiej muszą się znaleźć gracze od siebie, aby zaliczyć ich jako stojących obok Siebie

Kod

@down Zrobił lepszą wersję

Edytowane przez Failed

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Funkcja napisana z nudów, z tel, sorki za brak ułożenia, ale na tel nie ma TABa

CheckPlayerNextToPlayer(playerid, playerid2, range)

Funkcja sprawdza czy gracze są obok Siebie. Zwraca fałsz (0) jeżeli nie są, a prawdę (1) jeżeli są.

playerid - Gracz pierwszy

playerid2 - Gracz drugi

range - Odległość w jakiej muszą się znaleźć gracze od siebie, aby zaliczyć ich jako stojących obok Siebie

Kod

stock CheckPlayerNextToPlayer(playerid, playerid2, range)
{
new Float:x, Float:y, Float:z;
GetPlayerPos(playerid2, x, y, z);
if(IsPlayerInRangeOfPoint(playerid, x, y, z, range))
{
return true:
}
return false;
}

Po pierwsze to brak tagu Float: przez co będą ostrzeżenia o nieprawidłowym tagu. Po drugie, zla kolejnosc argumentow. Po tzecie, nie lepiej tak?

stock Float:CheckPlayerNextToPlayer(playa, playa2, Float:range = 20.0)
{
   new Float:pp[3];
   GetPlayerPos(playa2, pp[0],pp[1],pp[2]);
   return (GetPlayerDistanceFromPoint(playa, pp[0],pp[1],pp[2]) >= range);
}
Edytowane przez FJT

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Maniek, mówiłeś wczoraj żebym zajrzał do twojej funkcji. Proszę, poprawiłem teraz wykonuje się troszku szybciej.

stock CheckNumberAndLetter(str[]) // By Mlody954
{
        static bool:z[2];
		z[0] = false;
		z[1] = false;
        for(new x, l2 = strlen(str); x != l2; x++)
        {
				if(((str[x] >= 'a' && str[x] <= 'z') || (str[x] >= 'A' && str[x] <= 'Z')) && !z[0])
					z[0] = true;
                
 
                if((str[x] >= '0' && str[x] <= '9') && !z[1])
					z[1] = true;
                
 
                if((z[0]) && (z[1])) break;
        }
 
        if((!z[0]) || (!z[1])) return false;
        else return true;
}

vfxd.png

 

"c -> 43" to Twój kod bez mojej edycji. 

 

Pozwoliłem sobie jeszcze trochę podrasować tę funkcję

stock CheckNumberAndLetter(const str[])
{
        static 
		bool:z[2 char],
		i = 0;
			
        while(EOS != str[i])
        {
		switch(str[i]) {
			case 'a'..'z', 'A'..'Z': {
				z{0} = true;
			}
			case '0'..'9': {
				z{1} = true;
			}
		}
			
		if(z{0} && z{1}) return true;
		++i;
        }
	return false;
}
Edytowane przez Misiur

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

 

Pozwoliłem sobie jeszcze trochę podrasować tę funkcję

stock CheckNumberAndLetter(const str[])
{
        static 
		bool:z[2 char],
		i = 0;
			
        while(EOS != str[i])
        {
		switch(str[i]) {
			case 'a'..'z', 'A'..'Z': {
				z{0} = true;
			}
			case '0'..'9': {
				z{1} = true;
			}
		}
			
		if(z{0} && z{1}) return true;
		++i;
        }
	return false;
}

XcHADL0.png

 

Kod: Tutaj

 

Tutaj mała poprawka: Klik

 

Tak na przyszłość dałeś za dużą tablice skoro operowałeś bajtami. 

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Magiczne słówko char - 2 elementowa tablica zajmuje całą 1 komórkę. Loose indentation jest przez to że mój wklejony kod źle wyglądał i go przez edycję postu pozmieniałem (przez co źle wygląda w edytorze >>)

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Nie wiem po co poprawiacie tą funkcje skoro działa ona prawidłowo. 

 

89672d1363961700-fiatecuscan_pl-facepalm

 

Jak macie potrzebe sobie zmodyfikować funkcje, to modyfikujcie do woli - ale po co wstawiać drugi raz to samo skoro kod niewiele się różni (jak i czas wykonywania, pare ms? głupota) 

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Nie wiem po co poprawiacie tą funkcje skoro działa ona prawidłowo.

 

Jak macie potrzebe sobie zmodyfikować funkcje, to modyfikujcie do woli - ale po co wstawiać drugi raz to samo skoro kod niewiele się różni (jak i czas wykonywania, pare ms? głupota) 

This is war.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Coś w stylu BindKey('klawisz') w MTA, przeniesione do SA:MP:

#define BindKey(%1) 		if(newkeys & BindKey_(%1))
	
stock BindKey_(key[]) {
	if(!strcmp("action", key, true)) return KEY_ACTION;
	else if(!strcmp("crouch", key, true)) return KEY_CROUCH;
	else if(!strcmp("fire", key, true)) return KEY_FIRE;
	else if(!strcmp("sprint", key, true)) return KEY_SPRINT;
	else if(!strcmp("attack", key, true)) return KEY_SECONDARY_ATTACK;
	else if(!strcmp("jump", key, true)) return KEY_JUMP;
	else if(!strcmp("lookr", key, true)) return KEY_LOOK_RIGHT;
	else if(!strcmp("lookl", key, true)) return KEY_LOOK_LEFT;
	else if(!strcmp("lookb", key, true)) return KEY_LOOK_BEHIND;
	else if(!strcmp("handbrake", key, true)) return KEY_HANDBRAKE;
	else if(!strcmp("submission", key, true)) return KEY_SUBMISSION;
	else if(!strcmp("walk", key, true)) return KEY_WALK;
	else if(!strcmp("aup", key, true)) return KEY_ANALOG_UP;
	else if(!strcmp("adown", key, true)) return KEY_ANALOG_DOWN;
	else if(!strcmp("aleft", key, true)) return KEY_ANALOG_LEFT;
	else if(!strcmp("aright", key, true)) return KEY_ANALOG_RIGHT;
	else if(!strcmp("yes", key, true)) return KEY_YES;
	else if(!strcmp("no", key, true)) return KEY_NO;
	else if(!strcmp("ctrlback", key, true)) return KEY_NO;
	else if(!strcmp("up", key, true)) return KEY_UP;
	else if(!strcmp("down", key, true)) return KEY_DOWN;
	else if(!strcmp("left", key, true)) return KEY_LEFT;
	else if(!strcmp("right", key, true)) return KEY_RIGHT;
	else return false;
}
Zastosowanie:

public OnPlayerKeyStateChange(playerid, newkeys, oldkeys) {
	BindKey("submission") {
		RepairVehicle(GetPlayerVehicleID(playerid));
		GameTextForPlayer(playerid,"~y~Pojazd naprawiony!",2000,5);
		PlayerPlaySound(playerid, 1133, 0.0, 0.0, 0.0);
	}
	return false;
}
Edytowane przez Shiny

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Ponieważ nie wiem jak to w dziale jest z przydatnymi funkcjami oraz pisaniem kilku postów pod rząd, prosiłbym o zostawienie tego postu pod poprzednim. Jeżeli komuś on nie pasuje, zawartość tego proszę skopiować i wkleić do poprzedniego, natomiast ten - usunąć.

Funkcja dotyczy SA:MP GDK:

int SetTimer(TimerCallback callback, int interval, bool repeat, void * param = 0) {
	return SetTimer(interval, repeat, callback, param);
}
Jak wiadomo (lub nie), w SA:MP GDK funkcja SetTimer wygląda nieco inaczej, niż w SA:MP. Postanowiłem więc ją przeładować i... wyszło. Jedyną wadą tej funkcji jest fakt, że pierwszy argument nie może być ciągiem znaków, tylko nazwą funkcji publicznej, która się odświeża. Tak więc mając taki kod:

static void SAMPGDK_CALL RepeatingTimer(int, void *) {
	sampgdk_logprintf("I repeat!");
}
możemy w wywołaniu funkcji OnGameModeInit:

PLUGIN_EXPORT bool PLUGIN_CALL OnGameModeInit() {
    // Coś
    SetTimer(1000, true, RepeatingTimer, 0);
    return true;
}
zrobić tak:

PLUGIN_EXPORT bool PLUGIN_CALL OnGameModeInit() {
    // Coś
    SetTimer(RepeatingTimer, 1000, true);
    return true;
}
Kolejna "paczka funkcji" w SA:MP GDK, które pozwalają na używanie prawie wszystkich funkcji typu float w taki sam sposób, jak to jest w SA:MP:
float floatsqroot(float &value) {
	return sqrt(value);
}

float floatadd(float &oper1, float &oper2) {
	return oper1 + oper2;
}

float floatpower(float &value, float &exponent) {
	return pow(value, exponent);
}
		
float floatsub(float &oper1, float &oper2) {
	return oper2 - oper1;
}

float floatabs(float &value) {
	return abs(value);
}

float floatmul(float &oper1, float &oper2) {
	return oper1 * oper2;
}
Nazwy te są identyczne, jak opisane na Wiki SA:MP, tak więc po "instrukcję obsługi" odsyłam właśnie tam.

Kolejna funkcja dotyczy już samego PAWN i SA:MP (nie SA:MP GDK):

stock GivePlayerScore(playerid, score) {
	return SetPlayerScore(playerid, GetPlayerScore(playerid) + score);
}
Jest to prosta funkcja, która pozwala DAĆ/ZMIENIAĆ graczowi ilość punktów, zamiast ponownie USTAWIAĆ. Zastosowanie:

public OnPlayerUpdate(playerid) { // Co 80 ms będziemy dodawać graczowi 1 punkt
    GivePlayerScore(playerid, 1);
    return true;
}
I ostatnie... makro. W ilości sztuk - 2. Pozwalają one w przyjazny sposób "zapętlać" wszystko, o czym można sobie wymarzyć:

#define foreach_P(%0,%1)		\
	for(%0; %0 != %1; %0++) if(IsPlayerConnected(%0))
#define foreach(%0,%1)			\
	for(%0; %0 != %1; %0++)
Zastosowanie foreach_P:

public OnPlayerConnect(playerid) {
// Wiem, że to beznadziejny przykład, wiem też, że jest SendClientMessageToAll
// Ale ta funkcja jako pierwsza mi wpadła do głowy
// PS: najpierw MUSIMY zainicjalizować zmienną, w innym wypadku będzie ona nieużywana (testowane na SA:MP GDK - powodowało zawieszanie serwera)!
    new i, playa[MAX_PLAYER_NAME], str[128];
    GetPlayerName(playerid, playa, sizeof(playa));
    foreach_P(i, MAX_PLAYERS) {
        format(str, sizeof(str), "%s dołącza do Nas!", playa);
        SendClientMessage(i, -1, str);
    }
    return true;
}
Zastosowanie foreach:

main() {
    new i = 0;
    foreach(i, 999) {
        printf("I wynosi: %d.", i);
    }
    return false;
}
Edytowane przez Shiny

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
// Color management by promsters

stock Convert_HexToRGB(color, r, g, b)
{
	r = (color >> 24) & 0xFF;
    g = (color >> 16) & 0xFF;
    b = (color >> 8) & 0xFF;
}

stock Convert_RGBToHex(r, g, b)
{
	return (((r & 0xFF) << 16) | ((g & 0xFF) << 8) | ((b & 0xFF) << 0));
}

stock Convert_HexToDecimal(color)
{	
	return color >>> 8;
}

stock MakeColorDarker(color, percent)
{
	new 
		r, 
		g, 
		b, 
		Float:percentage = (100 - percent) + 0.1;
		
	Convert_HexToRGB(color, r, g, b);
	
	r = floatround(r * percentage / 100);
	g = floatround(g * percentage / 100);
	b = floatround(b * percentage / 100);
	
	return Convert_RGBToHex(r, g, b)
}

stock MakeColorLighter(color, percent)
{
	new 
		r, 
		g, 
		b, 
		Float:percentage = (100 - percent) + 0.1;
	
	Convert_HexToRGB(color, r, g, b);
	
	r = floatround(r * percentage / 100) + floatround(255 - percentage / 100 * 255);
	g = floatround(g * percentage / 100) + floatround(255 - percentage / 100 * 255);
	b = floatround(b * percentage / 100) + floatround(255 - percentage / 100 * 255);
	
	return Convert_RGBToHex(r, g, b)
}

Komuś może się przydać funkcja na jaśniejszy bądź ciemniejszy kolor(np. czat rp).

 

Użycie:

COMMAND:test(playerid, params[])
{
	new
		color_red = 0xFF0000FF,
		lighter_color = MakeColorLighter(color_red, 40); // 40 to procentowy stopień rozjaśnienia ->  "jasniejszy od podstawowego o 40%"
		
	SendClientMessage(playerid, color_red, "Ten tekst jest koloru czerwonego.");
	SendClientMessage(playerid, lighter_color, "Ten tekst jest jasniejszy o 40 procent od czerwonego.");
	return 1;
}

P.S Dodatkowo dzięki funkcji Convert_HexToDecimal możemy łatwo przechować kolory w bazie ;)

Edytowane przez promsters

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Może uznacie to za dziwne, ale zauwarzyłem że pętla for w pawn ma jakies odchyły, otóż gdy skrypt ma ich sporą ilość zaczyna się bugować, więc wymyśliłem prostą makrodefinicję by to ominąć, i jest to spore ułatwienie dla programistów, oto ona:

#define loop(%1;%2;%3){  for(new %1 = 0;;%3){if(%1>=%2){break;}

i użycie jej jest takie:

loop(i; MAX_PLAYERS; i++){
    //tutaj co ma robić pętla
}

i klamra otwierająca musi być za raz po loop(...), bo będzie wywalał undef symbol, a tak wywala tylko warna loose indenation (ale kompilar radzi sobie z tym, także nie ma problemu :-))


// CeKa: poprawione

Edytowane przez IRON

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

  • Przeglądający   0 użytkowników

    Brak zarejestrowanych użytkowników przeglądających tę stronę.

×