Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation since 08/09/2014 in all areas

  1. 24 points
    Salutare, astăzi vreau să discut cu voi nişte lucruri legate de optimizarea unui GM şi tot în acelaşi timp cum să faci lucrurile mai simple în GM. Q: Mai simple? Cum mai simple? A: Urmăreşte-mă şi vei află. În primul rând să discutăm despre optimizare. Optimizarea este esenţială pentru un GM, adică reduce timpul de execuţie a unei/unor functi. Q: Bun, şi dacă îl reduce ce? A: În timpul de executare a unei/unor funcţii lagul va creşte, şansă de crash devine mai mare şi nimeni nu e mulţumit. Dacă optimizăm, timpul de lag va fi redus substanţial cea ce scade şansă de crash. Q: Dar lagul acela de ce se produce? A: Că să înţelegeţi mai bine imaginativă un calculator mai vechi, cu componente slabe de genu: 1 GB ram , placă video 64 , procesor AMD 2.0 GH. Acum ganditiva că el lucrează. cu cât deschizi mai multe programe cu atât funcţionează din ce în ce mai greu , până se blochează. Acum imaginativă un calculator mai bun de genu 4GB ram , placă video 1GB, procesor i3 şi punetil să ruleze aceleaşi programe. Cu siguranţă veţi observă diferenţa şi anume că se mişcă mai rapid la acele programe şi nu se mai blochează aşa de repede. Aşa ceva este şi cu GM-ul. El trebuie să gândească în acelaşi timp ce face fiecare player în parte. Dacă GM nu este optimizat atunci clientul(adică voi) de a se bloca(crash) este mai mare. Acum că am lămurit aceste aspecte haideţi să discutăm despre cum putem face un GM mai optim şi totodată introducem şi simplitatea. Mai întâi voi începe cu sistemul de stocare a datelor MYSQL. MYSQL Observ că mulţi se plâng că nu mai sunt GM-uri pe ini(dini, yini sau alte derivări ale acestuia).Dacă tot am pomenit de derivările lui ini, pentru cei care nu ştiu sistemul de stocare a datelor ini este cel care crează un fişier .txt în scriptfiles>user(account/conturi/akk/etc). Dini, yini şi mai sunt câteva derivări sunt pentru a face puţină parformantă, adică să fie creat fişierul .txt mai rapid. Ok , am lămurit şi acest aspect, acum hai să facem diferenţa mai întâi între ini şi mysql.Mai există şi SQLLite, dar habar nu am cu ce se mânca ăla... Mysql este în momentul actual cel mai rapid şi mai de folos sistem de creare a datelor. Este cel mai avantajos dintre toate, iar conturile sunt într-o deplină siguranţă. Q: Ok , şi ce treaba are cu siguranţă conturilor? A: Hai să va zic ce mi să întâmplat mie personal după un restart. Eram pe un server de să-mp, şi numai văd că se da restart la server, eu aveam nivelul 5 , aveam 2.000.000 $ , 2 maşini, totul bine şi frumos , dar după ce să dat restart , mă văd că trb să mă înregistrez din nou, singurul de pe server, m-am înregistrat şi văd că am lvl 1 şi cele 2 maşini, iar ceilalţi nu aveau contul afectat. La mysql nu să întâmplat nici odată această. Am zis că e şi mai rapid. Da este mult mult mai rapid decât ini , deoarece un cont pe mysql poate fi creat în baza de date într-un interval scurt de timp (0.0001-0.0010 secunde, tastaţi o comandă şi vedeţi timpul de execuţie dacă nu mă credeţi), iar la dini este undeva la 0.1 - 0.9 secunde , poate ajunge dacă este lag pe server chiar şi la 1 - 1.3 - 1.5 secunde. Personal cred că este şi mai uşor de folosit. La mysql trebuie să fi atent la query-uri, pentru că ele trimit în baza de date informaţiile, în rest conturile se verifică cu if(Rows)- adică dacă se găsesc rânduri la acel cont, la dini de exemplu se verifică cu if(dini_Exists(file)) şi , personal mă bucur că e mai greu de făcut legătură cu baza de date, deoarece nu tot puştiul poate să-şi deschidă server. Acum să vorbim despre procesoarele de comenzi. ZCMD(cel mai cunoscut) şi altele Văd că încă se foloseşte strcmp pe unele GM-uri. STRCMP este extrem de lent. STRCMP este o funcţie ce verifică mesajul din chat. Adică, uitaţi cum arată o comandă pe strcmp: if (strcmp("/mycommand", cmdtext, true, 10) == 0) - verifică dacă a fost scris /mycomand. Aici intervine zcmd, care e are 2 avantaje. Aici se poate spune de simplitate, adică e mai simplu să scri CMD:mycomand(playerid,params[]) decât if (strcmp("/mycommand", cmdtext, true, 10) == 0) , clar e mult mai simplu de scris. Acum , haideţi să va vorbesc de ce strcmp e mult mai lent. Să zicem că eu am 100 de comenzi pe strcmp. Eu folosesc ultima comandă, adică comandă cu numărul 100. STRCMP verifică 99 de comenzi şi când ajunge la a 100-a se aplică. În timp ce se verifică se produce lag, într-adevăr , lag-ul ăla se nu e vizibil , dar el există. ZCMD e conceput să fie mai rapid. El foloseşte CallLocalFunction cea ce "se aruncă" direct în comandă şi nu stă să verifice cele 99 de comenzi , cea ce e vizibil mai rapidă comandă la executare. Acum există nenumărate procesoare de comenzi LIFE-CMD MCMD(cel mai rapid la ora actuală), aceste procesoare au nevoie de plugin, iar în pluginul respectiv, este folosit memory hack, cea ce îl face mult mai rapid decât zcmd, dar e puţin vizibil ochiului că e mai rapid , dar că lag, e redus substanţial. SSCANF Când vorbim de sscanf putem spune clar simplitate în folosire. Sscanf este un strtok dar cu mai multe atribuiri şi este mult mult mai rapid în verificare. Am să va dau o comandă care foloseşte strtok să vedeţi şi cum se foloseşte. CMD:givemoney(playerid,params[]) { if(IsPlayerConnected(playerid)) { tmp = strtok(cmdtext, idx); if(!strlen(tmp)) { SendClientMessage(playerid, COLOR_GRAD2, "USAGE: /givemoney [playerid/PartOfName] [money]"); return 1; } new playa; new money; playa = ReturnUser(tmp); tmp = strtok(cmdtext, idx); money = strval(tmp); if (PlayerInfo[playerid][pAdmin] >= 1339) { if(IsPlayerConnected(playa)) { if(playa != INVALID_PLAYER_ID) { GivePlayerMoney(playa, money); } } } else { SendClientMessage(playerid, COLOR_GRAD1, "Nu esti autorizat sa folosesti aceasta comanda"); } } return 1; }Vedeţi voi, în comandă există 2 strtok-uri şi acele strtok-uri se leagă şi de strlen. Strtok-ul , în comandă are atribuţia de a îi pune un parametru, în cazul nostru, la comandă de mai sus, avem 2 parametri şi anume "playerid/PartOfName" şi "money". Ele sunt definite în felul următor cu strtok: tmp = strtok(cmdtext, idx); - face legătură cu money, adică pune că parametru şi money(suma de bani pe care o atribuim) playa = ReturnUser(tmp); - transformă playa în jucător, adică oricare playa este jucător(playa este ţintă, persoană pe care aplicăm comandă) tmp = strtok(cmdtext, idx); - cu strtok îl definim că parametru în comandă money = strval(tmp); - cu strval money este definită că număr. Deci avem nevoie de 4 functi pentru o comandă simplă. Pare inutil să le scri , dar sunt esenţiale şi fără ele nu poţi face comandă corectă, mai ales că trebuie să transformăm definirile în valori playa - jucător, money - suma de bani şi să le facem că parametru. Aici intervine sscanf care e mult mult mai simplu de folosit şi mai rapid, adică noi transformăm definirile în valori şi totodată le facem şi parametri. Putem face în felul următor comandă, în loc să scriem atât o simplificăm şi o şi optimizăm. CMD:givemoney(playerid,params[]) { if(IsPlayerConnected(playerid)) { new playa, money; if(sscanf(params,"ud", playa, money)) return SendClientMessage(playerid, COLOR_GRAD2, "USAGE: /givemoney [playerid/PartOfName] [money]"); if (PlayerInfo[playerid][pAdmin] >= 1339) { if(IsPlayerConnected(playa)) { if(playa != INVALID_PLAYER_ID) { GivePlayerMoneyEx(playa, money); } } } else { SendClientMessage(playerid, COLOR_GRAD1, "Nu esti autorizat sa folosesti aceasta comanda"); } } return 1; }Acum să analizăm. Noi avem parametri următori, eu vii prezint pe cei mai folosiţi: s - String(sir de caractere, sau mesaj) i, d - Integer(sau numar intreg) -> 1, 42, -10 c - Caracter -> a, o, * l - Logical -> true, false b - Binary -> 01001, 0b1100 h, x - Hex -> 1A, 0x23 o - Octal -> 045 12 n - Numar -> 42, 0b010, 0xAC, 045 f Float(numar cu virgula sau pozitie) -> 0.7, -99.5 u Username(Nume jucator sau id jucator) -> WiDuAlK(numele), 0(id-ul meu) Bun şi acum să analizăm situaţia următoare: new playa, money; - eu am definit 2 lucruri: playa - care vreau să fie playerul şi money - care vreau să fie suma de bani pe care o atribui. if(sscanf(params,"ud", playa, money)) sscanf - funcţia (params - vine de la CMD:givemoney(playerid,params[]), dacă folosiţi strcmp, cea ce nu va recomand, în loc de params puneţi "cmdtext" din funcţia if (strcmp("/givemoney", cmdtext, true, 10) == 0) "ud", playa, money - fac 2 chestii 1 definesc valorile : "u" i se atribuie lui playa, "d" i se atribuie lui money, dacă era "ud", money, playa "u" i se atribuia lui money iar "d" lui playa. Deci revenim, această funcţie if(sscanf(params,"ud", playa, money)) este exact că funcţiile menţinute mai sus, adică : playa = ReturnUser(tmp); money = strval(tmp); deci respectivul "u" îl transformă pe playa în jucător, iar respectivul "d" îl transformă pe money în număr întreg. Tot în acelaşi timp, transformă cele acele 2 definiri în condiţi pentru comandă , adică dacă nu scrie /givemoney Widualk/0(id meu) 1000(suma de bani) să îi dea mesaj cu parametri comenzii. Totodată sscanf verifică dacă a scris parametri , nu doar îi transformă, deci if(sscanf(params,"ud", playa, money)) verifică dacă sau scris greşiţi parametri şi îi returnează un mesaj cu ei, sau cu ce vreţi voi. Că o concluzie la sscanf , ea are mai multe atribuţii , e şi simplă şi elegantă şi optimă şi ce vreţi voi. Deci e recomandabil să îl folosiţi la orice GM. Foreach Foreach-ul , este că un loop rapid. Loop-ul arată ceva de genu: for(new i = 0; i < MAX_PLAYERS; i++) , adică i să fie egal cu toţi jucători, adică să atribuie o funcţie tuturor jucătorilor. de genu: for(new i = 0; i < MAX_PLAYERS; i++) { GivePlayerMoney(i,100); } sau for(new i = 0; i < MAX_PLAYERS; i++) { GivePlayerWeapon(i,46(id arma),1(nr de munitii/gloante)); }Acest "i" creşte de la 0 şi ajunge la nr playerilor conectaţi pe server, adică dacă voi aveţi 46 de playeri pe server, i = 46, dacă voi aveţi 600 playeri, i = 600 şi se atribuie la toţi 600 nu doar unuia. În timp ce creşte i la nr max de playeri, adică se verifică playeri conectaţi, apoi creşte, se face într-un timp , pe care noi nu îl vedem , dar el există şi timpul acela, bine înţeles este încărcat cu lag. Aici intervine foreach şi prin simplitate şi pentru că este şi mai rapid, deci simplu pentru că scri aşa: foreach(Player, i) în loc de acel cod mărişor şi include-ul foreach este structurat să fie mai rapid decât loop-ul normal, deci timp de lag scăzut. Streamer Streamer este un include, care depinde şi de plugin . Şi cam atât pot să va zic... Glumesc , cu streamer poţi introduce obiecte în joc. Cu funcţia CreateObject poţi introduce doar 1000 de obiecte, deci voi puteţi pune 2000 de obiecte, dar primele 1000 le va citi. Streamer nu are limita şi poate fi configurat că obiectele să se vadă mai de la distanţă, mai de aproape. Q: Bun , dar de ce e limita de 1000 de obiecte? A: Limita respectivă este pentru binele clientului(voi când intraţi pe server sunteţi client, hostul e serverul), deci dacă marea limita era nevoie de resurse de pc, RAM şi alte resurse, deci limita este pentru binele clientului. Streamer nu are nevoie de multe resurse, doar dacă puneţi hărţi stricate, în sens cu multe obiecte într-o zona , ele fiind şi dublicate, poate chiar de mai multe ori, în rest nu produce lag, serverele de stunt au o groază de linii numai cu obiecte, dar nu prea au lag. Array-uri Array-ul e ceva de genu: new string[200]; acesta este array pt că are "[200]". Este un simplu array, el poate fi şi dublu de genu: new PlayerInfo[MAX_PLAYERS][pInfo] sau new număr[100][25]; sau mai mare. Dacă vedeţi, lungimea strîng-ului meu este de 200 de caractere(caracterele însemnând litere, cifre, simboluri sau spaţiul dintre 2 cuvinte). Deci va citi un mesaj de 200 caractere, în caz că va avea mai mult, caracterele în + nu vor fi afişate. De multe ori strîng-urile mari sunt inutile şi consumă biţi. În chat se pot vedea maxim 144 de caractere, deci strîng-ul nostru este mai mare cu 56 de caractere, care mănâncă biţi. Ce va recomand eu, este să faceţi strîng-urile mici, cam de 144 , mai mult nu aveţi nevoie, sau calculaţi în minte câte cuvinte scrieţi, şi îl puteţi face şi mai mic. Dacă e necesar, de exemplu pui comandă /stats pe dialog MSGBOX, da , ai nevoie de strîng mai mare, pentru că te foloseşti de el, dar în rest nu e necesar, şi e recomandabil să îl faci mai mic. Stilul Tot acum vreau să va vorbesc despre stilul în care scriptati. Eu personal folosesc tab-ul de multe ori, şi fac economie de new-uri, de genu: new strîng[100], targetid, suma = 0; în loc de new strîng[200]; new targetid; new suma = 0; şi mereu folosesc 2 tab-uri la aliniere de genu: if(sscanf(params,"ud", playa, money)) return SendClientMessage(playerid, COLOR_GRAD2, "USAGE: /givemoney [playerid/PartOfName] [money]");sau if(PlayerInfo[playerid],[pAdmin] < 1) return SendClientMessage(playerid, COLOR_GRAD2, "Nu poti folosi aceasta comanda!");Sau alţi folosesc SPACE între caracterele din functi, dar mie personal nu prea îmi place, dar dacă vouă va place e ok. Sau dacă aveţi multe enum-uri de genu: new engine, lights, alarm, doors, bonnet, boot, objective; putem face aşa: new engine, lights, alarm, doors, bonnet, boot, objective;Sau dialogurile să le aduceţi într-un enum nu în define, puteţi face ceva de genu: #define DIALOG_LOGIN 1 #define DIALOG_REGISTER 2 #define DIALOG_STATS 3 #define DIALOG_HELP 4 il faceti asa: enum { DIALOG_LOGIN, DIALOG_REGISTER, DIALOG_STATS, DIALOG_HELP };Şi iese mult mai frumos. Eu nu sunt fan acoladelor foarte lungi, de exemplu: CMD:fixveh(playerid,params[]) { if(IsPlayerConnected(playerid)) { if(PlayerInfo[playerid][pAdminServer] < 1337) { SendClientMessage(playerid, COLOR_GRAD1, " Nu esti autorizat sa folosesti comanda asta!"); return 1; } if(IsPlayerInAnyVehicle(playerid)) { RepairVehicle(GetPlayerVehicleID(playerid)); SendClientMessage(playerid, COLOR_GREY, " Masina a fost reparata !"); } } return 1; } transformam in: CMD:fixveh(playerid,params[]) { if(PlayerInfo[playerid][pAdminServer] < 1337) return SendClientMessage(playerid, COLOR_GRAD1, " Nu esti autorizat sa folosesti comanda asta!"); if(!IsPlayerInAnyVehicle(playerid)) return SendClientMessage(playerid, COLOR_GRAD1, " Nu esti intr-un vehicul!"); RepairVehicle(GetPlayerVehicleID(playerid)); SendClientMessage(playerid, COLOR_GREY, " Masina a fost reparata !"); return 1; } Observaţi că am scăpat de acoladele în exces, când se tastează comandă îşi face verificările, după ce trece de verificări se execută, dacă rămâne la o verificare îi da mesaj. Observaţi că am scăpat şi de verificarea if(IsPlayerConnected(playerid)) deoarece, cel care tastează comandă este mereu conectat, dar dacă folosim o comandă pe cineva, şi el nu este conectat, trebuie să facem verificarea dar în loc de if(IsPlayerConnected(playerid)) punem if(IsPlayerConnected(playa)) sau în loc de playa cum am definit noi jucătorul. Cam atât am avut de zis, dacă cunoaşteţi şi alte metode , puteţi să le ziceţi printr-un reply aici. Mic anunţ!! Am decis că la fiecare tutorial dacă acumulez 5 puncte de + şi câteva reply uri voi mai poştă un tutorial. Nu imediat, ci doar când observ acest lucru. Deci dacă acumulez câte 5 puncte + la aceste tutoriale: http://www.sa-mp.ro/forums/topic/20174-sscanf-si-zcmd/? http://www.sa-mp.ro/forums/topic/20256-cum-sa-tii-un-server-din-pc-folosind-hamachi/? http://www.sa-mp.ro/forums/topic/20286-tutorial-cum-sa-creez-un-radio-pe-server-si-cum-sa-iti-creezi-melodi-pentru-ascultat-pe-server/? http://www.sa-mp.ro/forums/topic/20173-foreach-inlocuieste-loopul/? Am câteva topicuri care mai au +-uri dar nu au câte vreau eu. Q: Ce faci tu cu +, la ce îţi trebuie, de ce tot inişti? A: Acel + şi reply reprezintă mai multe pentru mine... Un lucru ar fi ăla că apreciez ce am făcut eu, ce am încercat să explic, ce am vrut să arăt, apreciezi faptul că am făcut ceva pentu ţine/voi sau pentru această comunitate, luaţi-o cum vreţi, şi îmi mai spuneţi că v-am ajutat prin tutorialul meu şi mai doriţi să mai fac, la fel prin reply mai creşte şi activitatea pe forum.
  2. 16 points
    Salutare, azi am sa va prezint cum sa faceti un tutorial register/login mysql R39. Mai intai o sa va trebuiasca pluginul si includeul mysql care ip puteti gasi AICI! Mai intai o sa punem la inceputul GM-ului include-ul mysql. #include <a_mysql> Acum o sa definim datele de conectare #define mysql_host "localhost" // aici punem ip hostului. Daca folosim in PC GM lasam localhost #define mysql_db "bazadate"// aici punem numele bazei de date. #define mysql_user "root"// aici punem numele userului de la host. Daca folositi PC lasati root. #define mysql_pass ""//Aici puneti parola de la host(de la phpmyadmin al hostului). In caz de folositi PC lasati asa. Vom crea 2 Enum-uri. Unul cu dialogurile de register/login si altul cu datele pe care le va avea playerul enum { DIALOG_LOGIN, // dialogul de login DIALOG_REGISTER// dialogul de register }; enum pInfo //numele enumului este pInfo. in el vom pune datele playerului gen Admin/Level/ Money/Experianta si altele. { pParola,//cu pParola vom lua parola din baza de date a playerului pID// cu pID vom lua ID-ul din baza de date a playerului }; new P_Data[MAX_PLAYERS][pInfo];// Aceasta variabila este array. cu ea vom verifica 2 lucruri. id playerului si datele lui gen P_Data[playerid][pID] == 1; Vom crea acum un new care ne va ajuta sa conectam datele de conectarea cu baza de date new handle; // handle(mâner) este cea de care ne vom folosi sa facem lagatura intre baza de date si server Acum vom crea legatura intre baza de date si server. forward MySQLConnect();// se creaza un nou callback cu forward public MySQLConnect()// se face callback-ul { handle = mysql_connect(mysql_host, mysql_user, mysql_db, mysql_pass);// definim handle(manerul) ca fiind conectarea mysql la host, baza de date, parola si user-ul if(mysql_errno() != 0)// in caz ca aceasta va fi diferita de 0(0 inseamna ca e conectat, 1 inseamna ca nu e conectat , fiind un vector) { printf("Conexiunea la baza de date %s a esuat ---> Server Inchis ~~~", mysql_db);// va trimite un mesaj in consola SendRconCommand("exit");// se inchide serverul } else// altfel daca este 0(daca se face legatura) { printf("Conexiunea la baza de date '%s' cu user-ul '%s' a reusit!!!", mysql_db, mysql_user);// ne va da acest mesaj in consola } return 1; } Callback-ul MySQLConnect se va pune la OnGameModeInit pentru a fi finalizata conectarea la baza de date. public OnGameModeInit() { MySQLConnect(); return 1; } Se va crea un stock simplu cu care vom selecta numele playerului stock GetName(playerid) { new Name[MAX_PLAYER_NAME]; GetPlayerName(playerid, Name, sizeof(Name)); return Name; } Acum vom se va crea un nou callback , la care vom apela cand playerul se conecteaza. El va arata daca are cont sau nu. forward OnPlayerLogin(playerid);// se creaza callbac-ul public OnPlayerLogin(playerid)//Se creaza publicul { new rows, fields;// definim rows(randurile)si fields(domeniile) cache_get_data(rows, fields);//cache_get_data interogheaza date din baza de date. acele date sunt rows si fields if(rows)// atunci cand playerul se inregistreaza i se va crea niste randuri. Daca i se gasesc atunci cand se va conecta ii va da: { ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD, "Logheaza-te!", "Te rog sa-ti introduci parola contuului mai jos!", "Logare", "Exit");// dialogul register } else// daca nu i se gasesc randuri, adica daca contul nu exista, atunci i se va da urmatorul dialog { ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_INPUT, "Inregistrare", "Trebuie sa iti creezi un cont ca sa joci pe server. nTasteaza mai jos o parola, pentru a te inregistra!", "Inregistreaza", "Exit");// dialogul register } return 1; } Acum ca am creat dialogul care ne ajuta sa verificam daca playerul are cont sau nu , mergem la OnPlayerConnect si punem urmatoarele: public OnPlayerConnect(playerid) { new query[100];// definim query(interogare) mysql_format(handle, query, sizeof(query), "SELECT * FROM conturi WHERE Nume = '%s'", GetName(playerid));// mysql format face interogarile/setarile/obtiunile/updateurile la baza de date //handle reprezinta conectarea la mysql, query si sizeof(queri) reprezinta interogarea //"SELECT * FROM conturi WHERE Nume = '%s'"- Selecteaza de la tabelul cu conturi, unde numele este %s(de exemplu eu am numele Widualk pe sa-mp. Mi se va extrage numele si mysql_tquery(handle, query, "OnPlayerLogin", "i", playerid);// se va interoga OnPlayerLogin. Adica mai pe scurt , cand se conecteaza se va verifica daca are cont sau nu acel player. return 1; } Acum ca am terminat cu callback-urile de la conectare, vom crea dialogurile. public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[]) { new query[128], ip[25];// se creaza interogarea si ip. switch(dialogid)// se va folosi switch pentru a selecta dialogul { case DIALOG_REGISTER:// daca se va selecta dialogul register { if(!response) return Kick(playerid);// daca se va apasa pe butonul Exit ii va da kick if(response)// daca se apasa pe Butonul inregistrare se vor face urmatoarele verificari { if(!strlen(inputtext))// daca nu e scris nimic la parola return ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_PASSWORD, "Parola incorecta!", "Introdu-ti o parola pentru a te inregistra pe server! n", "Inregistreaza", "Exit");// ii va da din nou dialogul register cu mesajul specific GetPlayerIp(playerid, ip, sizeof(ip));// definim ip-ul de mai sus mysql_format(handle, query, sizeof(query), "INSERT INTO conturi (Nume, Parola, IP) VALUES ('%s', '%e', '%s')", GetName(playerid), inputtext, ip);// se insereaza in tabelul cu conturi numele playerului, parola pe care a scris-o si ip pe care il are mysql_query(handle, query);// se va trimite setarile si se va interoga callback-ul OnRegistration SpawnPlayer(playerid); // ii da spawn } return 1; } case DIALOG_LOGIN:// daca se va selecta dialogul de login { if(!response) return Kick(playerid);// si se va apasa pe butonul exit ii va da kick if(response)//daca se apasa pe butonul LOGARE se va face urmatoarele verificari { if(!strlen(inputtext))// daca nu a scris nimic la parola return ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD, "Parola incorecta!", "Te rog sa iti introduci parola corecta, pentru a te loga pe server.", "Logare", "Exit");// ii va da dialogul cu login cu mesajul specific // daca se va trece peste aceasta verificare se vor face urmatoarele: mysql_format(handle, query, sizeof(query), "SELECT * FROM `conturi` WHERE `Nume`='%e' AND `Parola` = '%e'", GetName(playerid),inputtext);// va fi selectata parola de la tabelul cu conturi mysql_tquery(handle, query, "OnLogin", "i", playerid);// se va face apel la baza si se va interoga CallBackUl OnLogin (Tquery = take query sau ia interogare in romana) } return 1; } } return 1; } Acum , ca am facut dialogurile , vom crea calback-urile care se interogheaza la dialogurile de mai sus. Vom crea callback-ul pentrul dialogul de register. Acum , vom crea callback-ul la care apeleaza dialogul de login forward OnLogin(playerid);// definim callback ul public OnLogin(playerid)// facem publicul { new rows, fields,temporar[200];// definim randurile si domeniile, iar temporar se va folosi la extragerea stringurilor cache_get_data(rows, fields);// facem interogarea lor if(rows)// daca playerul are randuri(adica daca are cont creat, odata cu contul se creeaza randurile) { //deci daca are randuri cache_get_field_content(0, "Parola",temporar), format(P_Data[playerid][pParola], 25, temporar);// i se vaextrage parola si i se verifica daca coincide cu numele. Se foloseste new-ul temporar pentru extragerea parolei, ea retinandu-se temporar(pana cand se deconecteaza jucatorul) P_Data[playerid][pID] = cache_get_field_content_int(0, "ID");// i se vaextrage ip-ul //un exemplu ar fi , daca are Admin , va fi ceva de genu P_Data[playerid][pAdmin] = cache_get_field_content_int(0,"Admin)"; i se va extrage din baza de date levelul de admin si i se va returna pe server, mai precis, cand se conecteaza are levelul de admin , care i-a fost setat de owner SpawnPlayer(playerid);// si se va da spawn } else// altfel , daca parola este gresita { ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD, "Parola incorecta!", "Te rog sa iti introduci parola corecta, pentru a te loga pe server.", "Logare", "Exit");// ii va da dialogul cu mesajul specific. } return 1; } Iar la final punem la OnGameModeExit(); public OnGameModeExit() { mysql_close( handle ) ;// deconectam serverul de la baza de date, daca se inchide return 1; } Acum , o sa recapitulam. Playerul are nevoie de ID, Nume, Parola si IP, deci 4 coloane in tabel. Tabelul se numeste "conturi", deoarece interogarea se face acolo "mysql_format(handle, query, sizeof(query), "SELECT * FROM conturi"-conturi este tabelul unde vor aparea ID ,Nume, Parola, IP Baza de date se numeste "bazadate" din: #define mysql_db "bazadate" O sa va arat acum cum se creaza tabelul. Pasul 1. Definim baza de date cu numele "basedate": Pasul 2: Se selecteaza noua baza: Pasul 3: Se creaza tabelul cu cele 4 coloane: Pasul 4: Se definesc coloanele , cu fiecare setare La tip INT = intenger= numar de cifre. Varchar = string = sir de caractere(litere) la Lungimea / setare se selecteaza cat spatiu se acorda, adica cate caractere incap maxim in acel tabel la id va fi maxim 9999999999(sun 10 cifre consecutive de "9", adica acel numar va fi maximul de playeri care pot avea cont) la nume, se va putea salva doar numele care contine doar 25 de caractere(adica daca numele depaseste 25 litere, doar primele 25 se vor salva) la interclasare la Varchar , mereu sa puneti latin1_sweadich_ci, de ce, asta nu pot spune nici eu , dar , stiu ca asa trebuie La ID tot timpul sa bifati casuta "A_I(auto Increment)" care va genera singur id-ul, altfel nu va merge tabelul conturi Asa ar trebui sa va arata , atunci cand va inregistrati: Atentie tutorial creat 100% de Widualk. Nerespectarea creditelor va duce la sanctiuni!
  3. 16 points
    Mai întâi de toate, va rog să citiţi TOT ce am spus eu prin acest topic , pentru că sunt uni , uni mai mulţi defapt, care copie dintr-o parte în altă dar nu ştiu ce înseamnă acele functi/callback-uri/variabile sau ce atributi au. Introducere Căutând idei pentru a construi un sistem de engine, menţionez că un sistem că acesta nu este aşa complex, m-am uitat prin diferite posturi pe să-mp.com , dar şi pe alte GM-uri care le mai am eu prin pc, orientativ, nu de a lua dintr-o parte în altă ci doar pentru a mă documenta în scripturile mele. Am văzut ce mă interesat, mi-am creat singur sistemul de engine, merge perfect(mie personal) şi sunt mulţumit de el. M-am folosit în crearea mea de 2 sisteme. Primul pe care l-am văzut pe un GM(nu dau nume, pentru că nu îl veţi găsi pe internet, a fost odată) şi unul de pe internet, unul cam ciudat din punctul meu de vedere pt că folosea TogglePlayerControllable , la care puteai da /unfreeze şi porneai cu maşină. Cel din GM se folosea de funcţia ManualVehicleEngineAndLights(). Ce face această funcţie? Dacă o folosiţi în sine, veţi vedea că nu va mai porneşte vehiculul când intraţi în el(am avut problema cu el, am şi postat o problema legată de el aici, eu iniţial credeam că nu porneşte farurile şi nu vehiculul) şi bine înţeles nu pornesc singure farurile de la maşină când se face noapte.De această funcţie m-am folosit şi eu, menţionez că era în GM, dar pe fs nu era, ci era , repet, TogglePlayerControllable. În acel GM era o mică eroare de concepţie , adică dacă porneai un vehicul,ieşeai fără să îl închizi şi încercai să îl porneşti pe al 2-lea îl închizi defapt, pentru că respectivă variabilă era asupra playerului, nu a vehiculului. Din acestea 2 m-am ghidat eu şi a fost foarte folositor. Mod de gândire În primul rând trebuie să definim o variabilă cu care atribuim unui vehicul o valoare. În ce constă acea valoare, ei bine dacă este engine off sau on. În al 2-lea rând ne trebuie să punem şi ManualVehicleEngineAndLights , pentru a nu porni vehiculul când intrăm în el, şi a nu fi nevoie de freeze. Menţionez că variabilă de care v-am spus o atribuim unui vehicul, nu la toate, ci doar respectivului vehicul în care ne aflăm , aşa nu vom avea parte de probleme la alte vehicule, functi eronate menţionate în introducere. Ne gândim şi la 2 metode pentru a porni vehiculul.Prima metodă este ce a comenzi,prin această metodă nu ne vom folosi de variabilă menţionată pentru că vor există 2 comenzi /engine şi /stopengine care nu au nevoie să verifice dacă vehiculul este deschis sau nu, ele înţelese de la sine. A 2-a metodă este cea a apăsării unei taste, cea mai folosită este tasta 2, pe care o vom folosi şi acum, dacă voi vreţi altă tasta, căutaţi aici şi înlocuiţi: http://wiki.sa-mp.com/wiki/Keys. La această metodă ne vom folosi de variabilă menţinută mai sus. Totodată cu ea verificăm dacă acel vehicul este pornit sau nu. Acestea fiind spuse, să trecem şi la partea de scripting. Mai întâi mergem la începutul GM-ului şi punem: new EngineVehicle[MAX_VEHICLES]; // Aceasta variabila am facut-o sa se atribuie vehiculelor de pe server insemnand toate nu doar primelor 10 20 30 si asa mai departe. Acum mergem şi punem funcţia această la publicul OnGameModeInit: ManualVehicleEngineAndLights(); //Aceasta functie face ca noi din pawn sa ii atribuim comenzi, nu ca pe GTA San Andreas , cand te urci intr-un vehicul imediat pleci cu el. Mergem tot la începutul GM-ului şi definim părţile unui vehicul, la care veţi vedea unde le vom folosi. new engine, lights, alarm, doors, bonnet, boot, objective; // acestea sunt componentele vehiculului pe partea de functie. Cu ele vom porni alarma, masina, usile(incuiate/descuiate) etc. Trecem pe partea de comandă unde vom face cele 2 comenzi. Comenzile /engine şi /stopengine care le vom crea fără a ne volosi de variabilă EngineVehicle pentru că ele sunt exact la obiect, nu trebuie să verificăm dacă e pornit vehiculul sau nu. CMD:engine(playerid,params[]) { new vehicleid = GetPlayerVehicleID(playerid);// definim vehicleid ca fiind id masinii in care ne urcam if(vehicleid == INVALID_VEHICLE_ID)// daca vehicleid este invalid, adica nu suntem in nici un vehicul return SCM(playerid,-1,"Nu esti intr-un vehicul");// ne da acest mesaj // aceasta este singura verificare de care avem nevoie. Tastand comanda, aceasta se verifica prima data. GetVehicleParamsEx(vehicleid, engine, lights, alarm, doors, bonnet, boot, objective);// definim parametri vehiculului in care ne-am urcat, adica cei mentionati mai sus SetVehicleParamsEx(vehicleid,VEHICLE_PARAMS_ON,lights,alarm,doors,bonnet,boot,objective);// setam vehiculul ca pornit, inlocuind engine cu VEHICLE_PARAMS_ON return 1; } CMD:stopengine(playerid,params[]) { new vehicleid = GetPlayerVehicleID(playerid);// definim vehicleid ca fiind id masinii in care ne urcam if(vehicleid == INVALID_VEHICLE_ID)// daca vehicleid este invalid, adica nu suntem in nici un vehicul return SCM(playerid,-1,"Nu esti intr-un vehicul");// ne da acest mesaj // aceasta este singura verificare de care avem nevoie. Tastand comanda, aceasta se verifica prima data. GetVehicleParamsEx(vehicleid, engine, lights, alarm, doors, bonnet, boot, objective);// definim parametri vehiculului in care ne-am urcat, adica cei mentionati mai sus SetVehicleParamsEx(vehicleid,VEHICLE_PARAMS_OFF,lights,alarm,doors,bonnet,boot,objective);// setam vehiculul ca pornit, inlocuind engine cu VEHICLE_PARAMS_OFF return 1; } Observaţie: Putem înlocui fiecare din acei parametri cu VEHICLE_PARAMS_ON sau VEHICLE_PARAMS_OFF, la funcţia SetVehicleParamsEx deoarece aşa activăm acei parametri. Voi puteţi să îi puneţi şi un mesaj acestei comenzi, eu nu m-am complicat pt simplul fapt că lumea foloseşte cel mai des metodă prin tasta, de dragul comodităţii sau că este mai rapidă. Acum că am creat comenzile, mergem la partea de apăsare prin tasta. Acum ne vom folosi de variabilă EngineVehicle, dar şi de tasta 2. Tasta 2, conform wiki este: KEY_SUBMISSION când te afli în vehicul. Mergem la publicul OnPlayerKeyStateChange şi facem în felul următor: if(newkeys & KEY_SUBMISSION)// tasta 2 , pe care am ales-o { new vehicleid = GetPlayerVehicleID(playerid); if(vehicleid == INVALID_VEHICLE_ID) return SCM(playerid,Rosu,"Nu esti intr-un vehicul"); GetVehicleParamsEx(vehicleid, engine, lights, alarm, doors, bonnet, boot, objective); // pana aici, am explicat anterior // precum noi am facut variabila EngineVehicle, ea are la inceput valoarea = 0. Noi ne vom folosi de aceasta. //EngineVehicle are ca parametru nr max de vehicule, nu este pus aiurea, in cazul nostru putem atribui fiecarui vehicul in parte o valoare. Acum o vom face folosind vehicleid if(EngineVehicle[vehicleid] == 0)// in caz ca vehiculul in care ne-am urcat are valoarea 0 la EngineVehicle, vom face urmatoarele: { SetVehicleParamsEx(vehicleid,VEHICLE_PARAMS_ON,lights,alarm,doors,bonnet,boot,objective);// il pornim prin aceasta functie SCM(playerid,-1,"Ai pornit vehiculul!");// ii dam acest mesaj ca l-am pornit EngineVehicle[vehicleid] = 1;// ii stabilim valoarea 1, adica ca este pornit. } else if(EngineVehicle[vehicleid] == 1)// altfel, daca vehiculul are EngineVehicle = 1(adica este pornit) ii vom face urmatoarele: { SetVehicleParamsEx(vehicleid,VEHICLE_PARAMS_OFF,lights,alarm,doors,bonnet,boot,objective);// il inchidem SCM(playerid,-1,"Ai inchis vehiculul!");// ii dam mesaj ca l-am inchis EngineVehicle[vehicleid] = 0;// ii stabilim valoarea 0(adica este inchis) } } Prin acestea, noi vom observă următoarele lucruri: -Dacă un player se urcă în vehicul şi îl porneşte, apoi se coboară şi pleacă lăsând-ul pornit, aşa va rămâne pentru fiecare jucător -Dacă un alt player se urcă în ACELAŞI vehicul, va putea merge cu el , şi îl va putea închide, şi va rămâne închis pentru toată lumea Acum, trebuie să facem că atunci când jucătorul se urcă în vehicul, şi vehiculul este închis , să îi spună ce trebuie să facă că să fie pornit vehiculul, în caz că este pornit, să nu îi dea nici un mesaj. Cum facem asta? Simplu. Mergem la publicul OnPlayerEnterVehicle şi punem următoare verificare if(EngineVehicle[vehicleid] == 0)// daca vehiculul este inchis, are valoarea EngineVehicle = 0 { SCM(playerid,-1,"Scrie /engine sau apasa 2, pentru a porni vehiculul!");// ii da mesaj sa ii spuna ce trebuie sa faca. } NOTĂ!! Aveţi măcar bunul simt de a nu copia tutorialul şi a-l poştă în altă parte şi ai modifică creditele. Eu am muncit la acest tutoriale, aşa că, nu vreau că altul să fie apreciat pentru muncă depusă de mine, nu de el. Cam atât şi cu acest tutorial, dacă ţi-a fost de folos dai +1, şi sper să ne auzim cu bine până la următorul tutorial.
  4. 12 points
    Salutare, la cererea lui david1995 am decis să fac un tutorial despre cum să faceţi un register mai dezvoltat, anume punem condiţii de înregistrare. Va anunţ de la început că eu folosesc aceste scripturi pe tutorialul acesta: TUTORIALVom face 4 dialoguri corespunzătoare cu : Vârstă, Sex, Email, Refferal(opţional).Dar vom face şi o verificare de stagiul de register. Acest stagiu va fi folosit pentru a termină registerul dacă ai închis inaine de a termină de completat. Mergem la enum-ul cu dialogurile şi adăugăm: enum { DIALOG_LOGIN, // dialogul de login DIALOG_REGISTER,// dialogul de register DIALOG_VARSTA, DIALOG_SEX, DIALOG_EMAIL, DIALOG_REFFERAL }; acum mergem la enumeraţia pInfo şi adăugăm: enum pInfo { pParola, pID, pVarsta, pSex, pEmail, pRefferal, pRegisterStep// aceasta ne ajuta la verificare. }; Acum că am adăugat acestea, mergem şi la OnDialogResponse şi facem o completare la dialogul de register, adică după ce ai băgat parolă să-ţi dea direct dialogurile de vârstă, sex, email refferal, apoi le creăm. Mergem la OnDialogResponse la DIALOG_REGISTER şi înlocuim în loc de SpawnPlayer(playerid) cu: ShowPlayerDialog(playerid, DIALOG_VARSTA, DIALOG_STYLE_INPUT, "Varsta", "Ce varsta doresti sa aiba caracterul?", "OK", ""); apoi sub case DIALOG_LOGIN punem: case DIALOG_VARSTA: { if(response) { new varsta = strval(inputtext);// strval convertete un string in intenger(numar natural) if(varsta < 6 || varsta > 40)// daca numarul pe care il introduce e mai mare decat 40 de ani sau mai mic decat 6 ii returnam din nou dialogul de varsta: return ShowPlayerDialog(playerid, DIALOG_VARSTA, DIALOG_STYLE_INPUT, "Varsta", "Ce varsta doresti sa aiba caracterul?\n Trebuie sa ai intre 6 si 40 de ani!", "OK", ""); // daca trece peste aceasta verificare se vor intampla urmatoarele: P_Data[playerid][pVarsta] = varsta;// variabila varsta va fi egala cu numarul introdus in casuta mysql_format(handle, query, sizeof(query), "UPDATE `conturi` SET `Varsta`='%d' WHERE `Nume`='%e'", P_Data[playerid][pVarsta], GetName(playerid));// introducem varsta sa fie egala cu cea care am introdus-o in casuta mysql_query(handle, query);// trimitem mesajul catre baza de date P_Data[playerid][pRegisterStep] = 1; mysql_format(handle, query, sizeof(query), "UPDATE `conturi` SET `RegisterStep`='%d' WHERE `Nume`='%e'", P_Data[playerid][pRegisterStep], GetName(playerid));// se updateaza mysql_query(handle, query);// se trimite interogarea ShowPlayerDialog(playerid, DIALOG_SEX, DIALOG_STYLE_MSGBOX, "Sex", "Ce sex doresti sa aiba caracterul?", "Masculin", "Feminin");// il timitem la dialogul de sex } } Am făcut dialogul de vârstă, dar trebuie să apelăm la cel de sex, şi vom face uite aşa: case DIALOG_SEX: { if(response)// daca apasa pe primul buton(masculin) { P_Data[playerid][pSex] = 1;//Seteaza pSex = 1(adica baiat) mysql_format(handle, query, sizeof(query), "UPDATE `conturi` SET `Sex`='%d' WHERE `Nume`='%e'", P_Data[playerid][pSex], GetName(playerid));// se updateaza sex-ul jucatorului mysql_query(handle, query);// se trimite catre baza de date. P_Data[playerid][pRegisterStep] = 2; mysql_format(handle, query, sizeof(query), "UPDATE `conturi` SET `RegisterStep`='%d' WHERE `Nume`='%e'", P_Data[playerid][pRegisterStep], GetName(playerid));// se updateaza mysql_query(handle, query);// se trimite interogarea ShowPlayerDialog(playerid, DIALOG_EMAIL, DIALOG_STYLE_INPUT, "Email", "Ce email ai?", "OK", "");// il timitem la dialogul de email } if(!response) { P_Data[playerid][pSex] = 2;//Seteaza pSex = 1(adica baiat) mysql_format(handle, query, sizeof(query), "UPDATE `conturi` SET `Sex`='%d' WHERE `Nume`='%e'", P_Data[playerid][pSex], GetName(playerid));// se updateaza sex-ul jucatorului mysql_query(handle, query);// se trimite catre baza de date. P_Data[playerid][pRegisterStep] = 2; mysql_format(handle, query, sizeof(query), "UPDATE `conturi` SET `RegisterStep`='%d' WHERE `Nume`='%e'", P_Data[playerid][pRegisterStep], GetName(playerid));// se updateaza mysql_query(handle, query);// se trimite interogarea ShowPlayerDialog(playerid, DIALOG_EMAIL, DIALOG_STYLE_INPUT, "Email", "Ce email ai?", "OK", "");// il timitem la dialogul de email } } Acum adăugăm şi dialogul de email: case DIALOG_EMAIL: { if(response) { if(strlen(inputtext) < 10 || strlen(inputtext) > 100)// strlen obtine lungimea de string. Daca mesajul introdus in caseta(emailul) este mai mic de 10 caractere sau mai mare de 100 caractere return ShowPlayerDialog(playerid, DIALOG_EMAIL, DIALOG_STYLE_INPUT, "Email", "Ce email ai?\nTrebuie sa fie intre 10 si 100 caractere!", "OK", "");// ii returneaza acelasi dialog strmid(P_Data[playerid][pEmail],inputtext, 0, strlen(inputtext), 100);// strmid obtine lungimea unui string. // in acest caz lungimea este introdusa in pEmail, adica P_Data[playerid][pEmail] = inputtext, dar va da eroare, asa ca ne folosim de strmid. mysql_format(handle, query, sizeof(query), "UPDATE `conturi` SET `Email`='%s' WHERE `Nume`='%e'", P_Data[playerid][pEmail], GetName(playerid));// se face update la baza de date a playerului mysql_query(handle, query);// se trimite mesajul catre baza de date. P_Data[playerid][pRegisterStep] = 3; mysql_format(handle, query, sizeof(query), "UPDATE `conturi` SET `RegisterStep`='%d' WHERE `Nume`='%e'", P_Data[playerid][pRegisterStep], GetName(playerid));// se updateaza mysql_query(handle, query);// se trimite interogarea ShowPlayerDialog(playerid, DIALOG_REFFERAL, DIALOG_STYLE_INPUT, "Refferal", "Te-a adus cineva pe server?", "OK", "SKIP");// il timitem la dialogul de refferal } } Iar ultimul dialog, cel de refferal case DIALOG_REFFERAL: { new rows, fields; if(response)// primul buton { mysql_format(handle, query, sizeof(query), "SELECT * FROM `conturi` WHERE `Nume` = '%e'",inputtext);// selecteaza numele din baza de date mysql_query(handle, query);// se trimite interogarea catre baza cache_get_data(rows, fields);// definim randurile si domeniile if(rows)// daca acel player are cont(are randuri in baza de date) { strmid(P_Data[playerid][pRefferal],inputtext,0,strlen(inputtext),25);// i se seteaza refferal-ul mysql_format(handle, query, sizeof(query), "UPDATE `conturi` SET `Refferal`='%e' WHERE `Nume`='%e'", P_Data[playerid][pRefferal], GetName(playerid));// se updateaza refferalul playerului mysql_query(handle, query);// se trimite interogarea P_Data[playerid][pRegisterStep] = 4; mysql_format(handle, query, sizeof(query), "UPDATE `conturi` SET `RegisterStep`='%d' WHERE `Nume`='%e'", P_Data[playerid][pRegisterStep], GetName(playerid));// se updateaza mysql_query(handle, query);// se trimite interogarea } else// daca nu are cont(nu i se gaseste randuri in baza de date) { ShowPlayerDialog(playerid, DIALOG_REFFERAL, DIALOG_STYLE_INPUT, "Refferal", "Cine te-a adus pe server?", "OK", "SKIP");// ii da din nou dialogul cu refferal } } if(!response)// al 2-lea buton { SendClientMessage(playerid,-1,"Bine, deci nimeni nu te-a adus!"); P_Data[playerid][pRegisterStep] = 4; mysql_format(handle, query, sizeof(query), "UPDATE `conturi` SET `RegisterStep`='%d' WHERE `Nume`='%e'", P_Data[playerid][pRegisterStep], GetName(playerid));// se updateaza mysql_query(handle, query);// se trimite interogarea SpawnPlayer(playerid);// ii da spawn } } Acum mergem la OnLogin şi punem următoarele verificări : Acestea vor verifică dacă ai parcurs fiecare etapă a register-ului. if(P_Data[playerid][pRegisterStep] == 0) return ShowPlayerDialog(playerid, DIALOG_VARSTA, DIALOG_STYLE_INPUT, "Varsta", "Ce varsta doresti sa aiba caracterul?", "OK", ""); if(P_Data[playerid][pRegisterStep] == 1) return ShowPlayerDialog(playerid, DIALOG_SEX, DIALOG_STYLE_MSGBOX, "Sex", "Ce sex doresti sa aiba caracterul?", "Masculin", "Feminin"); if(P_Data[playerid][pRegisterStep] == 2) return ShowPlayerDialog(playerid, DIALOG_EMAIL, DIALOG_STYLE_INPUT, "Email", "Ce email ai?", "OK", ""); if(P_Data[playerid][pRegisterStep] == 3) return ShowPlayerDialog(playerid, DIALOG_REFFERAL, DIALOG_STYLE_INPUT, "Refferal", "Cine te-a adus pe server?", "OK", "SKIP"); Mergem tot la OnLogin şi la verificare if(rows) punem: if(rows) { //deci daca are randuri P_Data[playerid][pParola] = cache_get_field_content(0, "Parola",temporar); P_Data[playerid][pID] = cache_get_field_content_int(0, "ID"); //extragem din baza de date urmatoarele: P_Data[playerid][pVarsta] = cache_get_field_content_int(0, "Varsta"); P_Data[playerid][pSex] = cache_get_field_content_int(0, "Sex"); P_Data[playerid][pEmail] = cache_get_field_content(0, "Email",temporar); P_Data[playerid][pRefferal] = cache_get_field_content(0, "Refferal",temporar); P_Data[playerid][pRegisterStep] = cache_get_field_content_int(0, "RegisterStep"); SpawnPlayer(playerid); } Acum trebuie să mergem în localhost/phpmyadmin şi să decurgem următorii paşi: Mulţumesc pentru atenţie! Dacă ţi-a fost de folos nu uită să dai +1 rep la topic.
  5. 12 points
    Salutare, astazi vin cu un nou tutorial in 3 pasi. Mi-am propus in cei 3 pasi sa va arat cum se creaza o factiune de la 0, pentru ca si voi sa va concepeti un GM de la 0 , si sa stiti cum se adauga factiunile. Atentie, inainte tin sa mentionez ca eu ma folosesc de registerul mysql din tutorialul acesta: . Parcurgeti acest tutorial doar daca v-ati creat sistemul de inregistrare dupa tutorial, deoarece eu aduc o contribuire lui. In partea 1 o sa creem variabilele de la factiune pe care le vom folosi si anume pLeader, pMember si pRank in baza de date , dar si in GM. Tot aici vom crea publicul Update, care ne va usura updateul la baza de date. Am vazut la unele GM-uri ca se foloseau de acest public(R33 Ideal pentru RPG by wopss, RedzMax parca asa se chema si alte GM-uri care nu imi mai aduc aminte denumirea lor ) si m-am gandit ca e foarte bine sa il folositi. Vom crea si un nou enum cu datele de update. Vom crea comenzile /invite , /makeleader(cu rconul) /giverank, /uninvite , /fpk(cu rcon). Acum ca am facut introducerea sa trecem si la treaba practica. Mergem la enum-ul "pInfo" si vom adauga cele 3 variabile in felul urmator: enum pInfo { pParola, pID, pLeader,// variabila playerului cand are lider pMember,// variabila playerului cand are membru pRank// variabila playerului cand are rank }; creem un enum cu cele 3 upload-uri enum { LeaderUpdate, MemberUpdate, RankUpdate }; si callback-ul forward Update(playerid, type);// creem callback-ul public Update(playerid, type) // facem publicul { if(IsPlayerConnected(playerid))// verificam daca playerul este conectat { new query[256];// se creaza o interogare in public pentru baza de date switch(type)// aplicam la swich pentru a face mai rapida apelarea la callback { switch(type) { case LeaderUpdate:// dupa cum am creat enum-ul , verificam cazul de update, adica lider { mysql_format(handle, query, sizeof(query), "UPDATE `conturi` SET `Leader`='%d' WHERE `Nume`='%e'", P_Data[playerid][pLeader], GetName(playerid));// facem update-ul la baza de date mysql_query(handle, query);// trimitem update-ul } case MemberUpdate:// cazul memnerului { mysql_format(handle, query, sizeof(query), "UPDATE `conturi` SET `Memner`='%d' WHERE `Nume`='%e'", P_Data[playerid][pMember], GetName(playerid));// facem update-ul la baza de date mysql_query(handle, query);// trimitem update-ul } case RankUpdate:// cazul rank-ului { mysql_format(handle, query, sizeof(query), "UPDATE `conturi` SET `Memner`='%d' WHERE `Nume`='%e'", P_Data[playerid][pMember], GetName(playerid));// facem update-ul la baza de date mysql_query(handle, query);// trimitem update-ul } } } } return 1; } Acum facem comenzile , dar mai intai aveti nevoie de urmatparele scripturi: ZCMD SSCANF CMD:makeleader(playerid,params[]) { if(IsPlayerConnected(playerid)) { new string[100], lider, factiuneid;// se creaza variabilele, lider = persoana pe care aplicam comanda, factiuneid = id factiunii la care va fi acea persoana if(!IsPlayerAdmin(playerid))// verificam daca playerul nu este conectat cu rcon-ul return SendClientMessage(playerid, -1, "Trebuie sa fi conectat cu Rcon-ul!"); if(sscanf(params,"ud",lider,factiuneid))// verificam daca playerul nu scrie comanda completa return SendClientMessage(playerid,-1,"Romania Reality: /makeleader [Nume_Player/ID] [FactiuneID]"); if(factiuneid > 11 && factiuneid < 1)//punem conditie la cate factiuni avem return SendClientMessage(playerid, -1, "Trebuie sa fie intre 1 si 11!"); if(!IsPlayerConnected(lider))// verificam daca playerul nu este conectat return SendClientMessage(playerid,-1,"Acest jucator nu este conectat"); P_Data[lider][pLeader] = factiuneid;// persoana pe care aplicam comanda va fi liderul factiunii pe care am scris-o P_Data[lider][pMember] = factiuneid;// persoana pe care aplicam comanda va fi membrul factiunii pe care am scris-o P_Data[lider][pRank] = 6; // ii va da rank 6 Update(lider, LeaderUpdate);// se va face update catre baza de date a liderului Update(lider, MemberUpdate);// se va face update catre baza de date a liderului ca este si membru in factiune Update(lider, RankUpdate);// se va face update la bazaz de date a liderului care are rank 6 format(string, sizeof(string), "Ai fost promovat ca lider de catre %s", GetName(playerid)); SendClientMessage(lider, -1, string);// ii da mesaj liderului de cine a fost promovat format(string, sizeof(string), "%s este noul lider al factiunii %d.", GetName(lider), factiuneid); SendClientMessage(playerid, -1, string);// ii da mesaj adminului pe cine a promovat SpawnPlayer(lider);// il spawneaza pe lider } return 1; } Facem comanda /fpk CMD:fpk(playerid,params[]) { if(IsPlayerConnected(playerid)) { new concediat, motiv[200], string[200];// se creaza noile variabile care vor fi folosite la verificarea comenzii in scriere if(sscanf(params,"us[199]", concediat, motiv))// verificam ca comanda sa se scrie corect return SendClientMessage(playerid,-1,"SERVER: /fpk [Nume_Player] [MOTIV]");// daca nu e scrisa corect , atunci sa ii dea mesajul cum sa se scrie if(!IsPlayerAdmin(playerid))// verificam daca playerul nu este conectat cu rcon-ul return SendClientMessage(playerid, -1, "Trebuie sa fi conectat cu Rcon-ul!"); if(!IsPlayerConnected(concediat))// verificam daca playerul nu este conectat return SendClientMessage(playerid,-1,"Acest jucator nu este conectat"); if(sscanf(params,"us[199]", concediat, motiv))// verificam ca comanda sa se scrie corect return SendClientMessage(playerid,-1,"SERVER: /fpk [Nume_Player] [MOTIV]"); P_Data[concediat][pLeader] = 0;// il facem lider 0 P_Data[concediat][pMember] = 0;// il facem membru 0 P_Data[concediat][pRank] = 0; // ii dam rank 0 Update(concediat, LeaderUpdate);// se va face update la bazaz de date a concediatului Update(concediat, MemberUpdate);// se va face update la bazaz de date a concediatului Update(concediat, RankUpdate);// se va face update la bazaz de date a concediatului format(string, sizeof(string), "Ai fost concediat de catre OWNERUL %s, pe motivul: %s", GetName(playerid), motiv); SendClientMessage(concediat, -1, string);// ii da mesaj concediatului de cine a fost concediat format(string, sizeof(string), "%s este concediat pe motivul: %s", GetName(concediat), motiv); SendClientMessage(playerid, -1, string);// ii da mesaj adminului pe cine a concediat SpawnPlayer(concediat);// il spawneaza pe lider } return 1; } Facem comanda /uninvite CMD:uninvite(playerid,params[]) { if(IsPlayerConnected(playerid)) { new concediat, motiv[200], string[200];// creem variabilele de care ne folosim in comanda if(P_Data[playerid][pLeader] < 0)// verificam daca playerul este lider(persoana care foloseste comanda) return SendClientMessage(playerid,-1,"SERVER: Nu esti lider"); if(sscanf(params,"us[199]", concediat, motiv))//verificam daca comanda e scrisa bine return SendClientMessage(playerid,-1,"SERVER: /uninvite [Nume_Player/ID] [MOTIV]"); if(P_Data[playerid][pLeader] != P_Data[concediat][pMember])// verificam daca liderul foloseste comanda pe ai sai prieteni return SendClientMessage(playerid,-1,"SERVER: Nu poti folosi comanda decat pe cei din factiune la tine!"); if(concediat == P_Data[concediat][pLeader])// verificam daca concediatul nu e lider return SendClientMessage(playerid,-1,"SERVER: Nu poti folosi comanda pe un lider!"); // daca este ii dam mesaj corespunzator P_Data[concediat][pMember] = 0;// il facem membru 0 P_Data[concediat][pRank] = 0; // ii dam rank 0 Update(concediat, MemberUpdate);// se va face update la bazaz de date a concediatului Update(concediat, RankUpdate);// se va face update la bazaz de date a concediatului format(string, sizeof(string), "Ai fost concediat de catre Liderul %s, pe motivul", GetName(playerid), motiv); SendClientMessage(concediat, -1, string);// ii da mesaj "victimei" de cine a fost concediat format(string, sizeof(string), "%s este concediat pe motivul: %s", GetName(concediat), motiv); SendClientMessage(playerid, -1, string);// ii da mesaj liderului pe cine a concediat SpawnPlayer(concediat);// il spawneaza pe lider } return 1; } Facem comanda /invite CMD:invite(playerid,params[]) { if(IsPlayerConnected(playerid)) { new membru, string[200];// se creaza variabilele folosite in comanda if(P_Data[playerid][pLeader] < 0)// verificam daca playerul este lider return SendClientMessage(playerid,-1,"SERVER: Nu esti lider"); if(sscanf(params,"u", membru))//verificam daca comanda e scrisa bine return SendClientMessage(playerid,-1,"SERVER: /uninvite [Nume_Player/ID]"); if(P_Data[membru][pLeader] > 1) return SendClientMessage(playerid,-1,"SERVER: Nu poti folosi comanda pe alti lideri!"); if(P_Data[membru][pMember] > 1) return SendClientMessage(playerid,-1,"SERVER: Nu poti folosi comanda pe alti membri!"); P_Data[membru][pMember] = P_Data[playerid][pLeader];// il facem membru la factiunea in care este si cel care invita P_Data[membru][pRank] = 0; // ii dam rank 0 Update(membru, MemberUpdate);// se va face update la bazaz de date a membrului Update(membru, RankUpdate);// se va face update la bazaz de date a membrului format(string, sizeof(string), "Ai fost promovat membru de catre Liderul %s, pe motivul", GetName(playerid)); SendClientMessage(membru, -1, string);// ii da mesaj membrului de cine a fost invitat format(string, sizeof(string), "%s este membru la tine in factiune", GetName(membru)); SendClientMessage(playerid, -1, string);// ii da mesaj liderului pe cine a invitat SpawnPlayer(membru);// il spawneaza pe lider } return 1; } Comanda /giverank CMD:giverank(playerid,params[]) { if(IsPlayerConnected(playerid)) { new membru, rank, string[200];// creem variabilele cu care vom face conditie in comanda if(P_Data[playerid][pLeader] < 1)// verificam daca playerul este lider return SendClientMessage(playerid,-1,"SERVER: Nu esti lider"); if(sscanf(params,"ud", membru, rank))//verificam daca comanda e scrisa bine(ne folosim de cele de mai sus) return SendClientMessage(playerid,-1,"SERVER: /uninvite [Nume_Player/ID] [NRRank]"); if(P_Data[membru][pLeader] == P_Data[playerid][pLeader]) return SendClientMessage(playerid,-1,"SERVER: Nu poti folosi comanda pe tine!"); if(P_Data[membru][pLeader] > 0) return SendClientMessage(playerid,-1,"SERVER: Nu poti folosi comanda pe alti lideri!"); if(P_Data[membru][pMember] != P_Data[playerid][pLeader])// verificam daca comanda se foloseste pe membri altei factiune return SendClientMessage(playerid,-1,"SERVER: Nu poti folosi comanda pe alti membri!"); if(P_Data[membru][pMember] != P_Data[playerid][pLeader]) P_Data[membru][pRank] = rank; // ii dam rank 0 Update(membru, RankUpdate);// se va face update la bazaz de date a membrului format(string, sizeof(string), "Ai fost promobat cu rank %d de catre liderul %s", rank, GetName(playerid)); SendClientMessage(membru, -1, string);// ii da mesaj membrului de cine a fost promovat in rank format(string, sizeof(string), "%s este membru la tine in factiune cu rank: %d", GetName(membru), rank); SendClientMessage(playerid, -1, string);// ii da mesaj liderului pe cine a promovat } return 1; } Acum un pas foarte important, mergem la callback-ul OnLogin si punem sub P_Data[playerid][pID] = cache_get_field_content_int(0, "ID"); urmatoarele: P_Data[playerid][pLeader] = cache_get_field_content_int(0, "Leader"); P_Data[playerid][pMember] = cache_get_field_content_int(0, "Member"); P_Data[playerid][pRank] = cache_get_field_content_int(0, "Rank"); Iar acum mergem la baza de date si parcurgem urmatorii pasi: Bun, aceasta a fost partea 1. Daca gasiti greseli pe la comenzi , asta e din cauza ca acuma, seara, l-am facut si sunt putin cam obosit(se vede si dupa data de postare a tutorialului). Sper ca ati inteles pana aici, voi reveni cu a 2-a parte maine. Tutorial 100% scris de WIDUALK. Postarea acestui tutorial fara acordul meu va fi reclamata! Pana data viitoare(maine) PACE!
  6. 11 points
    Noțiuni de bază pentru limbajul PAWN Cuprins Despre PAWNDespre algoritmiDespre iniţializatoriDespre tipuri de dateDespre formatoriDespre expresiiDespre prioritatea operaţiilorDespre structuri Despre PAWNPAWN este un limbaj specific serverelor de San Andreas Multiplayer. Acesta a fost derivat din limbajul de programare C. Atenţie! Mulţi confundă PAWN cu PAWNO care sunt două lucruri diferite. PAWN este limbajul în care se programează serverele de San Andreas Multiplayer, iar PAWNO este programul în care se realizează (se scriu) scripturile / game mode-urile pentru aceste servere, mai pe scurt un IDE (integrated development environment sau interactive development environment). Desigur, în directorul pawno din folderul serverului se află un executabil numit pawncc. Aceste este compilatorul, adică programul care transformă textul care poate să fie citit de om în cod binar (codul binar reprezintă numerele 0 şi 1, datorită tranzistorului) care este înţeles de calculator. Despre algoritmiAlgoritmul este o metodă de rezolvare a unei probleme. Algoritmii au 3 proprietăţi importante: FinititudineGeneralitateCorectitudineOptimalitate 1. Finititudinea Finititudinea reprezintă proprietatea algoritmului de a se termină într-un număr finit de paşi. 2. Generalitate Generalitatea reprezintă proprietatea algoritmului de a rezolva o întreagă clasă de probleme. 3. Corectitudine Corectitudinea reprezintă proprietatea algoritmului de a oferi o rezolvare corectă în urmă executari acestuia. 4. Optimalitate Optimalitatea reprezintă proprietatea algoritmului de se execută într-un număr de minim de paşi. Exemplu: Să zicem că avem un altgorim pentru a verifică dacă Player-ul X se află în jurul Player-ului Y. Player-ul Y are rază 8.0 (pentru IsPlayerInRangeOfPoint). stock IsPlayerInRangeOfPointEx(playerid, targetid, Float:Radius) { new Float:X, Float:Y, Float:Z; GetPlayerPos(playerid, X, Y, Z); if(IsPlayerInRangeOfPoint(targetid, Radius, X, Y, Z)) return 1; return 0; }Acest algoritm are toate proprietăţiile, adică: 1. Finititudine - Se execută într-un număr finit de paşi. 2. Generalitate - Se poate execută pentru orice player de pe server, nu doar pentru player-ul X. 3. Corectitudine - Este corect scris din punct de vedere al limbajului PAWN. 4. Optimalitate - Se execută o singură dată, nu merge de la 0 până la MAX_PLAYERS (499). Acest algoritm este făcut de mine, el va retura valoarea 1 în cazul în care Player-ul X se află în rază Player-ului Y sau 0 în caz contrar. Despre iniţializatori1. const const nu este modificată pe parcursul algoritmului. Exemplu: new const Float:PI = 3.14; 2. enum Enumeratiile sunt un sistem bun de reprezentare a grupurilor mari de date şi modificări rapide. Exemplu: enum pInfo { pLevel, pAdmin }; new PlayerInfo[MAX_PLAYERS][pInfo]; public OnPlayerConnect(playerid) { PlayerInfo[playerid][pLevel] = 1; PlayerInfo[playerid][pAdmin] = 6; } 3. forward forward îi spune compilatorului că o funcţie o să urmeze mai târziu, fie că are sau nu parametrii. Exemplu: forward FunctiaMea(playerid, const string[]); public FunctiaMea(playerid, const string[]) { } 4. native native defineşte o funcţie în maşină abstractă / calculator, dar NU în script. Se poate defini o funcţie native doar dacă ea este inclusă în SA:MP sau într-un plugin. Exemplu: native printf(const format[], {Float,_}:...); 5. new new iniţializează o variabilă globală sau locală, indiferent de fişier (în caz că este globală). Exemplu: new Variabila = 5; 6. public public face o funcţie visibila pentru maşină abstractă / calculator, poate să fie chemată direct într-un script. Exemplu: forward FunctiaMea(); main() { CallLocalFunction("FunctiaMea", ""); } public FunctiaMea() { printf("Asta e functia mea."); } 7. static static face variabilă să fie globală doar în fişierul respectiv. Exemplu: fisier1.pwn: FunctiaMea1() { // Eroare, Variabila_Globala nu este definită. printf("%d", Variabila_Globala); } // Variabila_Globala este definită aici. new Variabila_Globala = 10; FunctiaMea2() { // Nu se întâmplă nimic, Variabila_Globala a fost definită anterior printf("%d", Variabila_Globala); } // Includem un alt fişier #include "fisier2.pwn"fisier2.pwn: FunctiaMea3() { // Aici iar nu este o eroare pentru că fişier2 este inclus după ce am definit Variabila_Globala. printf("%d", Variabila_Globala); }Acum să modificăm Variabila_Globala în static. Exemplu: FunctiaMea1() { // Eroare, Variabila_Globala nu este definită. printf("%d", Variabila_Globala); } // Variabila_Globala este definită aici. static Variabila_Globala = 10; FunctiaMea2() { // Nu se întâmplă nimic, Variabila_Globala a fost definită anterior printf("%d", Variabila_Globala); } // Includem un alt fişier #include "fisier2.pwn"fisier2.pwn: FunctiaMea3() { // Eroare, deoarece Variabila_Globala a fost limitată doar la fişierul 1. printf("%d", Variabila_Globala); } 8. stock stock se foloseşte pentru a initializa variabile, dar dacă nu e folosită nu va apărea warningul că variabilă respectivă nu este folosită. Exemplu: main() { Functia1(); } Functia1() { printf("Functia1 bună"); } Functia2() { printf("Functia2 salut"); }Aici o să fie un warning cum că Functia2 nu este folosită. main() { Functia1(); } stock Functia1() { printf("Functia1 bună"); } stock Functia2() { printf("Functia2 salut"); }Aici NU o să fie un warning cum că Functia2 nu este folosită. Despre tipuri de dateDatele sunt clasificate după: Natură lorconstantevariabileDupă tipnumericeîntregirealeLogiceCaractere Datele constante Datele constante nu îşi modifică valoare pe tot parcursul algoritmului. Se initializeaza cu const. Datele variabile Datele variabile îşi pot modifică valoare pe parcursul algoritmului. Acestea se caracterizează prin nume, tip de dată şi locaţia de memorie. Se initializeaza cu new. Datele de tip numeric Datele de tip numeric sunt numerele. Acestea sunt întregi (exemplu 3 sau 5, zise şi integer) şi reale (exemplu 4.25 şi 9.16, zise şi float). Se initializeaza cu new nume_variabila sau new Float:nume_variabila. Datele de tip logic Datele de tip logic pot avea doar două valori (Adevărat / True / 1 sau Fals / False / 0).Se initializeaza cu new Bool:. Datele de tip caracter Datele de tip caracter (string) sunt datele cuprinse între ghilimele (" ", exemplu "Date de tip caracter sau string"). Se initializeaza cu new nume_variabila[lungime_string] Despre formatoriDupă cum am spus mai sus, PAWN este derivat de la C, deci a moştenit şi câte ceva de la el. Formatori sunt argumente adiţionale urmate de format, în locul acestora sunt inserate string-ul rezultat în funcţie de tipul formatorului. Tipuri de formatori: %i - afişază un număr întreg (tot numărul).%d - afişază un număr întreg (tot numărul).%s - afişază un string.%f - afişază un număr real / float. (trebuie să aibă tagul Float:)%c - afişază caracter ASCII.%x - afişază un număr Hexadecima.%b - afişază un număr binar.%% - afişază caracterul "%" Exemplu: Întreg: new a = 54; format(string, sizeof(string), "Număr a este %i.", a); SendClientMessage(playerid, 0xFFFFFFAA, string);Se va afişa: Număr a este 54.Exemplu #2: new string[64]; format(string, sizeof(string), "Ai scorul: %d", GetPlayerScore(playerid)); SendClientMessage(playerid, 0xFFFFFFAA, string);Se va afişa: Ai scorul: 1 (depinde ce scor are playerul) String: new string[20]; format(string, sizeof(string), "Învăţ despre %s.", "formatori"); SendClientMessage(playerid, 0xFFFFFFAA, string);Se va afişa: Învăţ despre formatori. Float: new string[20]; format(string, sizeof(string), "4 împărţit la 3 este %f.", 4.0 / 3.0); SendClientMessage(playerid, 0xFFFFFFAA, string);Se va afişa: 4 împărţit la 3 este 1.333333. Despre expresiiO expresie este o succesiune de operanzi legaţi între ei de operator. Sunt grupaţi cu ajutorul parantezelor după reguli bine stabilite. Sunt mai multe tipuri de operatori: Aritmetici"+" - adunare"-" - scădere"*" - înmulţire"/" - împărţire"%" - restul împărţiriLogici"!" - negaţie / not"&&" - şi / and"||" - sau / orRaţionali"<" - mai mic">" - mai mare"<=" - mai mic sau egal">=" - mai mare sau egal"!=" - diferit de Exemplu: new a = 15, b = 10; // Initializam variabilele a şi b, care o să aibă valorile 15 şi 10. (a o să aibă valoare 15 şi b o să aibă valoare 10, pe baza "Primul venit, primul servit") Puteţi să luaţi orice numere vreţi. printf("Suma: %i", a + b; // Calculăm suma şi o afişăm printf("Scădere: %i", a - b; // Calculăm scăderea şi o afişăm printf("Înmulţire: %i", a * b; // Calculăm înmulţirea şi o afişăm printf("Împărţire: %i", a / b; // Calculăm împărţirea şi o afişăm printf("Rest: %i", a % b; // Calculăm restul împărţiri lui a la b şi o afişămSe va afişa: Suma: 25 Scădere: 5 Înmulţire: 150 Împărţire: 1 Rest: 5Putem să nu facem variabilele a şi b. printf("Suma: %i", 15 + 10); // Calculăm suma şi o afişăm printf("Scădere: %i", 15 - 10); // Calculăm scăderea şi o afişăm printf("Înmulţire: %i", 15 * 10); // Calculăm înmulţirea şi o afişăm printf("Împărţire: %i", 15 / 10); // Calculăm împărţirea şi o afişăm printf("Rest: %i", 15 % 10); // Calculăm restul împărţiri lui a la b şi o afişămSe va afişa: Suma: 25 Scădere: 5 Înmulţire: 150 Împărţire: 1 Rest: 5 Despre prioritatea operaţiilorÎn funcţie de prioritatea maximă se calculează expresile în următoarea ordine: Cele în care apar operatorii "&&", "*", "/", "%".Cele în care apar operatorii "+", "-", "||".Cele în care apar operatorii "<", ">", "<;=", ">=", "!=". Despre structuri1. Structura if / dacă Structura if, zisă şi dacă în pseudocod. Are rolul de verificare. Formă: if(condiţie) { Structura1(); } else if(condiţie2) { Structura2(); } else { Structura3(); }Explicaţie: Se verifică dacă condiţia este adevărată, dacă este adevărată se execută Structura1, dacă prima condiţie este falsă se verifică condiţia2, dacă este adevărată se execută Structura2, în caz contrar (când conditile de mai sus sunt false) se execută Structura3. Nu se pun paranteze decât atunci când ai decât o linie după structura de mai sus. Exemplu: if(condiţie) { Structura1(); } else if(condiţie2) { Structura2(); } else { Structura3(); }else este opţional! 2. Structura while / cât timp Structura while, zisă şi cât timp în pseudocod. Are rolul de a execută structura din interior cât timp condiţia este adevărată. Formă: while(condiţie) { Structura1(); }Explicaţie: Se verifică dacă condiţia este adevărată, dacă este adevărată se execută Structura1 până când condiţia este falsă. Când condiţia este falsă se termină de executat structura while şi se trece la structura imediat următoare. Nu se pun paranteze decât atunci când ai decât o linie după structura de mai sus. Exemplu: while(condiţie) { Structura1(); } 3. Structura for / pentru Structura for, zisă şi pentru în pseudocod. Are rolul de a execută structura din interior cât timp variabilă noastră îndeplineşte condiţia. Formă: for(new variabilă = valoare_iniţială; condiţie; pas_de_executare) { Structura1(); }Explicaţie: Variabilei i se atribuie valoare iniţială. Se verifică dacă variabilă a depăşit valoarea finală (condiţia), dacă s-a depăşit se termină de executat structura for şi se trece la structura imediat următoare, în caz contrar se execută Structura1 şi se creşte valoarea variabilei cu pasul de executare. Nu se pun paranteze decât atunci când ai decât o linie după structura de mai sus. Exemplu: for(new variabilă = valoare_iniţială; condiţie; pas_de_executare) { Structura1(); } 4. Exemple main() { StructuraIf(5, 4); // Chemam functia "StructuraIf" cu parametrii a = 5 si b = 4. StructuraIf(9, 9); // Chemam functia "StructuraIf" cu parametrii a = 9 si b = 9. StructuraIf(2, 3); // Chemam functia "StructuraIf" cu parametrii a = 2 si b = 3. StructuraWhile(5); // Chemam functia "StructuraWhile" cu parametrul NumarMaxim = 5. StructuraFor(3); // Chemam functia "StructuraFor" cu parametrul NumarMaxim = 3. } stock StructuraIf(a, b) // Cream functia "StructuraIf" cu parametrii a si b care sunt obligatorii. { if(a > b) // Verificam daca a este mai mare ca b. { print("a este mai mare ca b"); // Daca a este mai mare ca b afisam mesajul. } else if(a == b) // Verificam daca a este egal cu b. { print("a este egal cu b"); // Daca a este egal cu b afisam mesajul. } else { print("b este mai mare ca a"); // Daca nici o conditie de mai sus nu este adevarata afisam mesajul. } } stock StructuraWhile(NumarMaxim) // Cream functia "StructuraWhile" cu parametriul NumarMaxim care este obligatoriu. { new i = 1; // Initializam variabila locala i, îi atribuim valoare 1. while(i < NumarMaxim) // Executam structura print si i++ cât timp conditia este adevarata. { print("Execut While"); // Afisam mesajul cât timp conditia este adevarata. i++; // Crestem i-ul cu 1, cât timp conditia este adevarata. } } stock StructuraFor(NumarMaxim) // Cream functia "StructuraWhile" cu parametriul NumarMaxim care este obligatoriu. { for(new i = 1; i <= NumarMaxim; i++) // Executam conditia cât timp i este mai mic sau egal cu NumarMaxim si îl creste cu 1 (i++). (se poate creste si cu 2, dar atunci trebuie scris i += 2 sau i = i + 2) { printf("%i ", i); // Afisam mesajul care este de tip întreg. } print("FOC!"); // Dupa ce terminam de executat for-ul afisam mesajul "FOC!". }
  7. 10 points
    Salut, sunt Chuck si aceasta este a doua mea mapa. Am facut-o pentru cineva si nu mai avea nevoie si m-am gandit sa o postez, deoarece, poate cineva imi va aprecia munca :). In fine, mapa am facut-o in 8 ore, are aproximativ 250 de obiecte si sunt Dynamice. Mapa: DS.txt Masina: Ds.pwn Poze: Un +1 daca va place mapa! Multumesc :D.
  8. 10 points
    Astăzi va prezint câteva funcţii, care vor putea fi folosite la crearea unu GM de la 0, când apăsaţi pe butonul "NEW" din partea de sus al pawn-ului şi intraţi o să vedeţi că sunt câteva chestii , că şi în GTA San Andreas, clasicul de exemplu uşi , în care poţi intră, dacă o să va adăugaţi 1-2 maşini , şi o să vedeţi că săriţi, drifting şi alte chestii o să vi se dea o suma de bani în fine , eu va arăt cum să le scoateţi, după preferinţă şi să le modificaţi după bunul plac şi nu numai atât. Următoarele funcţii vor fi puse la publicul OnGameModeInit() Când intraţi prima dată pe serverul "NEW" o să vedeţi că aveţi un mers ciudat, unele servere îl acceptă, altele nu , după preferinţă voastră, cu această funcţie veţi putea opri. Dacă nu aveţi nevoie de ea puteţi să o ştergeţi.Funcţia se numeşte: UsePlayerPedAnims(); După cum v-am spus şi în intro-ul tutorialului veţi remarcă, dacă va puneţi vro maşină , că atunci când săriţi cu ea, faceţi stunting într-un cuvânt o să va dea o suma de bani. ei de aceea, pentru a opri STUNTING-UL folosiţi funcţia: EnableStuntBonusForAll(0); Pentru a bloca interioarele, să nu intri la bună voie, să îţi creezi tu comenzi de teleportare şi alte chestii, te vei folosi de: DisableInteriorEnterExits(); Pe harta(minimap) apar playerii. Sunt 3 stagii ale unei funcţii, pentru a apărea playerii pe server şi a nu apărea. ShowPlayerMarkers(0); // nu apar playerii pe minimap ShowPlayerMarkers(1); // apar playerii pe minimap şi se văd de oriunde ar fi ei, indiferent de distanţă între ei ShowPlayerMarkers(2); // apar playerii pe minimap doar când sunt aproape unii de alţi, altfel nu vor apărea Şi dacă tot am vorbit de apărut playerii pe minimap , este o funcţie asemănătoare care face vizibilitatea numelui jucătorului în joc de la o anumită distanţă pe care o setaţi dvs. Funcţia este: SetNameTagDrawDistance(10.0); SetNameTagDrawDistance este funcţia, iar 10.0 este valoarea distanţei la care se vede numele, adică trebuie să te apropi de playerul X la distanţă de 10 m pentru a-i vedea numele. Valoarea o modificaţi voi după bunul plac. Ultima funcţie pe care v-o prezint în acest tutorial este cea care da nume modului din joc, adică , atunci când deschideţi icoană SĂ-MP-ului pentru a va alege serverul în care doriţi să intraţi, o să apară o căsuţa cu "MODE" în care scrie ceva. La GM "NEW"o să apară BlankScript, voi modificaţi în ce doriţi.Functia este: SetGameModeText("BlankScript");// intre ghilimele inlocuiti voi cu modul de joc. Pentru serverele de RPG am vazut "Los Santos" , pe la serverele de STUNT am vazut"DM/STUNT/DRIVING" , voi puneti ce doriti. Sper că v-a fost de folos tutorialul, şi îl veţi folosi pentru că "EDITUL nu are valoare!"
  9. 10 points
    Salut , nu cred ca va convine ca pe serverul vostru sa intre un jucator cu un HACK . Asa ca urmati pasii urmatori. Define la inceputul gamemodului : #define FREEZE_SECONDS 5 // Timpul cat playerul are freeze #define red 0xF22E59FF // Culuarea rosie #define green 0x6FF22EFF // Culuarea verde Acum variabilele si forward : new Hacker[MAX_PLAYERS]; forward HackCheck(playerid); La OnPlayerConnect punem Hacker[playerid] = 0; La OnPlayerSpawn punem SetTimerEx("HackCheck", FREEZE_SECONDS * 1000, 0, "i", playerid);// Acest timer ii da startul functiei HackCheck pentru a verifica daca are s0B TogglePlayerControllable(playerid, 0); Si la jumate sau la sfarsitul gamemodului punem : public HackCheck(playerid) { new Float:x, Float:y, Float:z, str[258], pName[MAX_PLAYER_NAME]; GetPlayerName(playerid, pName, sizeof(pName)); GetPlayerCameraFrontVector(playerid, x, y, z); #pragma unused x #pragma unused y if(z < -0.8) { Hacker[playerid] = 1; format(str, sizeof(str), "[ANTICHEAT]: %s[%d] a intat cu s0B. (/hackers)", pName, playerid); for(new i = 0; i < MAX_PLAYERS; i++) { if(PlayerData[playerid][pAdmin] < 1) { SendClientMessage(i, red, str); } } TogglePlayerControllable(playerid, 1); } else { TogglePlayerControllable(playerid, 1); Hacker[playerid] = 0; } return 1; } Si acum sa facem comana : CMD:hackers(playerid, params[]) { if(PlayerData[playerid][pAdmin] < 1) return SendClientMessage(playerid, red, "[ERROR]: Nu esti admin"); SendClientMessage(playerid, 0x5DE85FFF, "|---- Playeri Online cu s0B -----|"); new count = 0, str[200], pName[MAX_PLAYER_NAME]; GetPlayerName(playerid, pName, sizeof(pName)); { for(new i = 0; i < MAX_PLAYERS; i++) { if(Hacker == 1) { count++; format(str, sizeof(str), "%s[%d] ,", count, pName, i); SendClientMessage(playerid, 0xEF88F2FF, str); } } } { if(count == 0) return SendClientMessage(playerid, 0x99D45BFF, "Nu ai nici un player cu s0B pe server"); } return 1; }
  10. 10 points
    Salutare stimaţi utilizatori, am revenit cu partea a 3-a a tutorialului "Cum să creezi o nouă facţiune de la 0".În tutorialele precedente aţi învăţat cum să adăugaţi facţiunea, cum să faceţi spawn, culoare playerului şi celelalte functi. În acest tutorial vom face 2 lucruri. Primul lucru este că vom adaugă respectivei facţiuni maşini.Am văzut că se plânge lumea, au adăugat nişte maşini şi că i sau dat peste cap id lor. Ei în tutorialul acesta vom explică de ce se întâmplă această, şi cum să o evităm. Partea a 2-a a tutorialului va constă în adăugarea GATE-urilor(porţilor) cu restricţie dacă eşti liderul facţiunii x sau membrul facţiunii x. Ne vom folosi de MAP EDITOR pentru adăugarea mai rapidă a facţiunilor. Dacă nu ştiţi să folosiţi Map Editor, aveţi AICI un tutorial. Bun , dacă tot am vorbit despre ce o să facem, să îi dăm drumul şi practicii. Mergem în Map Editor şi plasăm 5 vehicule. Noi în momentul de faţă, nu avem nici un vehicul introdus.Că să vedeţi id vehiculelor mergeţi aici: Vehicule Adăugăm vehiculele la publicul OnGameModeInit. // acestea sunt vehiculele de la PD CreateVehicle(596, 1544.9691, -1650.9399, 5.4536, 90.0000, -1, -1, 100); CreateVehicle(596, 1544.9491, -1654.9799, 5.4536, 90.0000, -1, -1, 100); CreateVehicle(596, 1544.9491, -1658.9999, 5.4536, 90.0000, -1, -1, 100); CreateVehicle(596, 1544.9491, -1662.8599, 5.4536, 90.0000, -1, -1, 100); CreateVehicle(596, 1544.9491, -1667.7000, 5.4536, 90.0000, -1, -1, 100); Acum mergem la inceput şi facem un callback de restricţie a id-urilor vehiculelor. Mai întâi vedem în GM id vehiculelor introduse cu "/dl" şi le notăm pe o foaie. Noi am pus 5 vehicule deci id-urile lor sunt 1 , 2 ,3 ,4 , 5. ATENŢIE!!! Nu este necesar să trecem toate vehiculele pe o foaie. Putem trece doar primul vehicul şi ultimul vehicul, pentru că de ele ne vom folosi. Mergem în pawn şi facem următoarele: forward PoliceCar(carid);// Se creaza callback-ul de restrictie public PoliceCar(carid)// se face publicul de restrictie { if((carid >= 1) && (carid <=5))// daca id la vehicul este intre 1 si 5 { return 1;// ii returnam 1 } return 0;// daca nu se afla intre 1 si 5 nu se returneaza nimic. } Bun , aşa facem şi la celelalte facţiuni, chiar dacă au return 0 la primul callback nu au nici o problema. Acum că am pus verificarea la id vehiculelor punem şi restricţie. Trebuie să facem următoarele: Mergem la publicul OnPlayerStateChange şi punem aşa: public OnPlayerStateChange(playerid, newstate, oldstate) { new newcar = GetPlayerVehicleID(playerid);// definim newcar ca id masinii in care sa urcat playerul. if(PoliceCar(newcar))// daca playerul se afla in masina de politie si { if(P_DATA[playerid][pMember] == 1 || P_DATA[playerid][pLeader] == 1) // daca este membru 1 sau lider 1 {}// Nu se intampla nimic. else//altfel , daca nu este nici lider 1 si nici member 1 { RemovePlayerFromVehicle(playerid); // il scoate din masina SendClientMessage(playerid,-1,"Nu faci parte din Police Departament!");// si ii da acest mesaj. } } return 1; } Perfect, acum mergem şi şi verificăm. Vedem că merge totul perfect. Aşa faceţi şi la celelalte facţiuni. Dacă observaţi, când băgaţi un filescript pe server, filescriptul respectiv conţinând nişte maşini, o să va dea id vehiculelor peste cap. De ce? Pentru că serverul ia mai întâi ce e pe filescripturi(în ordinea în care aţi adăugat în server.cfg) şi pe urmă ce e în GM, deci cumva dacă aveţi 5 maşini într-un filescript, ele vor avea id 1 2 3 4 5 iar cele de la Police Departament vor avea id 6 7 8 9 10. Că să nu se întâmple această aveţi posibilitatea de a face 2 chesti. 1) Introduceţi tot filescriptul în GM, vehiculele din fs punându-le ultimele ori 2)Copiaţi maşinile din fs(filescript) , le puneţi ultimele, ştergeţi din fs vehiculele, compilaţi fs şi compilaţi GM. Aşa nu veţi mai întâmpina probleme. Acum că ştim să restricţionăm maşini , mai trebuie şi porţi(gate). Aceste porţi vom face să se deschidă şi să se închidă. Se va închide într-un număr de timp. Noi vom seta 5 secunde pentru a se închide, adică după 5 secunde ce să coborât se va urcă înapoi. Mergem în map editor şi vom face următoarea: Potitia initiala Pozitia de coborare Acum mergem în pawn şi definim poartă aşa. // la inceputul GM new GatePD1; //La OnGameModeInit: GatePD1 = CreateObject(980, 1586.81323, -1637.93604, 14.95745, 0.00000, 0.00000, 0.00000); Acum că am definit poartă şi am adăugat-o, luăm poziţia coborâtă, adică unde se va duce poartă, adică o coboram. Bine , acum am demonstrat că am coborât-o. Voi trebuie să o coborâti sub pământ deoarece nu trebuie să se vadă. Salvăm undeva ambele coordonate ale obiectului: -poziţia iniţială -poziţia coborâtă adică acestea: CreateObject(980, 1586.81323, -1637.93604, 14.95745, 0.00000, 0.00000, 0.00000);// pozitia initiala CreateObject(980, 1586.81323, -1637.93604, 9.52512, 0.00000, 0.00000, 0.00000);// pozitia coborata. Acum trebuie să facem că poartă să se deschidă. Putem face prin 2 metode: -metodă comenzii -metodă apăsării pe tasta Facem mai întâi metodă apăsării pe tasta, cred şi cea mai la îndemână şi elegantă, deoarece playerul nu mai trebuie să stea să scrie /deschidegate(exemplu), ci doar apasă o tasta. Tastele le luăm de aici: Tasta După cum am spus, la ambele metode trebuie să apelăm la un timer de move, adică poartă trebuie să coboare, dar şi să se ridice la loc(bine înţeles). Aşa că facem următoarele: Mergem la publicul OnPlayerKeyStateChange şi punem aşa: // alegem o tasta, eu amales tasta KEY_CROUCH deoarece apasa "H" cand e in masina si "C" cand nu este in masina. Voi alegeti orice tasta credeti ca vi s-ar potrivi. public OnPlayerKeyStateChange(playerid, newkeys, oldkeys) { if (newkeys & KEY_CROUCH )// daca apasa tasta KEY_CROUCH { if(P_DATA[playerid][pMember] == 1 || P_DATA[playerid][pLeader] == 1)// daca este lider sau member la factiunea cu nr 1(Police Departament) { if(IsPlayerInRangeOfPoint(playerid, 15, 1586.81323, -1637.93604, 14.95745))// daca este in raza portii //1586.81323, -1637.93604, 14.95745 - locatia portii //15 - distanta dintre poarta si player, adica daca este la max 15 metri de poarta { MoveObject(GatePD1, 1586.81323, -1637.93604, 9.52512, 5.0, 0.00000, 0.00000, 0.00000);// se muta obiectului // GatePD1 - dupa cum am definit obiectul, GatePD1 este poarta noastra // 586.81323, -1637.93604, 9.52512- pozitia lui de coborare // 5.0 viteza de deplasare in jos // 0.00000, 0.00000, 0.00000 - rotatiile acestuia, in cazul nostru nu se roteaza. Rotatiile sunt doar la alegere, dar e mai bine ca sa punem si aceasta pentru a nu intampina probleme SetTimer("MoveGatePd1",5000,0);// apelam la callback-ul MoveGatePd1 pentru a se inchide poarta, adica dupa 5 secunde sa se apeleze la callback SendClientMessage(playerid,-1,"Ai deschis poarta 5 secunde!");// ii da acest mesaj } } } return 1; } // facem si callback-ul la care am apelat: forward MoveGatePd1();// cream callback-ul public MoveGatePd1()// cream publicul { MoveObject(GatePD,11586.81323, -1637.93604, 14.95745, 5.0, 0.00000, 0.00000, 0.00000);// mutam poarta // la fel ca in pasii de sus // GatePD1- obiectul nostru // 11586.81323, -1637.93604, 14.95745 - pozitia initiala // 5.0 - viteza de deplasare // 0.00000, 0.00000, 0.00000 - rotatiile obiectului, in momentul de fata nu se roteste deloc, deoarece a plecat de la aceasi rotatie si a ajuns la aceasi rotatie. return 1;// returnam 1. } -Metoda prin comanda Mergem la OnPlayerCommandText si punem asa: if (strcmp("/deschidepoarta", cmdtext, true, 10) == 0) { if(P_DATA[playerid][pMember] == 1 || P_DATA[playerid][pLeader] == 1)// daca este lider sau member la factiunea cu nr 1(Police Departament) { if(IsPlayerInRangeOfPoint(playerid, 15, 1586.81323, -1637.93604, 14.95745))// daca este in raza portii //1586.81323, -1637.93604, 14.95745 - locatia portii //15 - distanta dintre poarta si player, adica daca este la max 15 metri de poarta { MoveObject(GatePD1, 1586.81323, -1637.93604, 9.52512, 5.0, 0.00000, 0.00000, 0.00000);// se muta obiectului // GatePD1 - dupa cum am definit obiectul, GatePD1 este poarta noastra // 586.81323, -1637.93604, 9.52512- pozitia lui de coborare // 5.0 viteza de deplasare in jos // 0.00000, 0.00000, 0.00000 - rotatiile acestuia, in cazul nostru nu se roteaza. Rotatiile sunt doar la alegere, dar e mai bine ca sa punem si aceasta pentru a nu intampina probleme SetTimer("MoveGatePd1",5000,0);// apelam la callback-ul MoveGatePd1 pentru a se inchide poarta, adica dupa 5 secunde sa se apeleze la callback SendClientMessage(playerid,-1,"Ai deschis poarta 5 secunde!");// ii da acest mesaj } } return 1; } ATENŢIE!!! Noi folosim CreateObject şi MoveObject. Dacă folosiţi STREAMER şi le creaţi cu CreateDynamicObject OBLIGATORIU mutaţi cu MoveDynamicObject, la fel şi invers. Nu va funcţiona nici odată altfel. Eu v-aş recomandă să folosiţi SREAMER-ul şi să creaţi obiectele cu el. De ce? Pentru că limita de obiecte în SĂ-MP este de 1000 de obiecte. De aceea, pentru a va lasă obiectele mai importante să le creaţi cu CreateObject. De ce e pusă această limita? Pentru binele clientului(când intraţi pe un server, voi sunteţi clientul adică jocul, nu serverul) deoarece mănâncă din RAM şi veţi avea lag dacă limita e mai mare sau infinită. NOTĂ! Ştiu că mulţi dintre voi începători , sau persoane puţin mai avansate citiţi aşa "răsfoind" sau mai deloc de am scris eu după "//" ,dar eu am explicat ce e cu fiecare funcţie şi cum se foloseşte, deoarece dacă nu ştiţi să creaţi aşa ceva , nu veţi putea dezvoltă un server , şi veţi veni la noi şi veţi spune "Nu , că nu ştiu, fă-mi tu.". Eu va explic, şi voi dacă citiţi şi încercaţi o dată, a două oară, a 3-a oară până va iese şi deprindeţi modul de gândire, veţi avansa, altfel nu aveţi cum. NOTĂ2!! Aveţi măcar bunul simt de a nu copia tutorialul şi a-l poştă în altă parte şi ai modifică creditele. Eu am muncit la aceste tutoriale, am adăugat si diacritice unde sa putut şi am încercat să explic pe cât posibil pe înţelesul tutuor. Această este marea mea rugăminte. Notă secundară! Dacă va plăcut acest tutorial, dacă va folosit acest tutorial sau dacă măcar îmi respectaţi muncă depusă, daţi + 1 la tutorialele postate de mine. Aşa văd că muncă mea e apreciată , şi voi poştă în continuare tutoriale. Cam atât a fost cu cele 3 părţi ale tutorialului, am încercat să va prezint cum se face o facţiune de la 0, nu că alte tutoriale pe care le-am văzut, şi care sunt cam pe lângă. Sper că va fost de folos , şi încercaţi să gândiţi când citiţi. Luaţi fiecare funcţie în parte şi o gândiţi, astfel veţi face performanţă.
  11. 9 points
    Salutare, după cum am şi spus, am revenit cu partea a 2 -a a tutorialului "Cum să creezi o nouă facţiune de la 0". În acest tutorial voi arată cum o să va puneţi locul de spawn, comenzile de enter-exit, iar la enter-exit ne vom juca puţin cu VirtualWorld-urile, şi ne vom juca şi cu 3DText-urile şi Pick-urile. Spawn-ul îl vom face la 2 din facţiuni Police Departament şi Police Blue Berry(cred că aşa se numea acel sat), fiecăruia îi vom pune şi o sala de antrenament, iar la spawnare să primească o culoare, când vorbeşte să arate o culoare, şi să primească diferite beneficii de gen arme, bani sau viaţă plină.... Va mai urmă o ultima parte. O să vedeţi la timpul potrivit în ce va constă şi a 3-a parte, dar să rămânem la "oile noastre" şi să începem. Pentru început avem nevoie de poziţii, aşa că mergem pe server şi salvăm cateva poziţii. 4 poziţii sunt la Police Departament Los Santos, ele fiind: 1)locul de spawn 2)locul de unde intră poliţistul în secţie(în partea de jos, lângă spawn, o să vedeţi voi) 3)Locul de unde intră civili în secţie 4)Locul de unde va intră şi va ieşi poliţistul din sala de antrenament Celelalte poziţii sunt la fel, dar sunt poziţiile de la Police Blue Berry. ACUM, MERGETI DUPA URMATORII PASI: IAR NOI NE VOM FOLOSI DE COORDONATELE ACESTEA: O să aveţi nevoie de tutorialul: Ne vom folosi de aceste coordonate, ele reprezintă poziţiile de spawn în San Andreas: Acum, că am făcut rost de coordonate, vom merge şi vom face în felul următor. Ne vom uită după interioarele dorite de AICI. Mergem acum la publicul OnPlayerSpawn şi punem aşa: public OnPlayerSpawn(playerid) { if(IsPlayerConnected(playerid))//verificăm dacă playerul este conectat { if(P_Data[playerid][pMember] == 1 || P_Data[playerid][pLeader] == 1)//verificăm dacă playerul are lider sau member = 1 { SetPlayerPos(playerid,1532.0398, -1677.7267, 5.8906);// dacă va avea lider sau member = 1, sau amândouă sau una dintre ele, îl va spawna la locul unde am vrut, //SetPlayerPos- funcţia ; playerid- playerul care se spawneaza, iar restu , sunt coordonatele de la care am plecat, cele din poză pe care le-am scos în evitenta. SetPlayerInterior(playerid,0);// nu este într-o clădire sau altcv , deci îi vom seta 0 când se spawneaza SetPlayerVirtualWorld(playerid, 0);// îi setăm VirtualWorld-ul 0 , deoarece în virtual world 0 sunt maşinile şi obiectele şi altele, despre virtual world vorbim puţin mai încolo } else if(P_Data[playerid][pMember] == 2 || P_Data[playerid][pLeader] == 2)// verificăm dacă playerul are lider sau member = 2 { SetPlayerPos(playerid, 627.3973, -571.4391, 17.9145);// dacă va avea lider sau member = 2, sau amândouă sau una dintre ele îl va spawna în faţă uşii, va fi acolo şi coordonată de /enter SetPlayerInterior(playerid,0);// nu este într-o clădire sau altcv , deci îi vom seta 0 când se spawneaza SetPlayerVirtualWorld(playerid, 0); } else// aici vom verifică dacă nu are lider să îl spawneze la locul dorit { SetPlayerPos(playerid, 1479.6548, -1725.2207, 13.5469); SetPlayerInterior(playerid,0);// nu este într-o clădire sau altcv , deci îi vom seta 0 când se spawneaza SetPlayerVirtualWorld(playerid, 0); } } return 1; } Aici dacă vrem mai îi adăugăm o armă şi , dacă vrem, îi scădem 50$ la fiecare spawn, pe unele servere era denumit Medic Bill, adică îi da viaţă plină şi de aceea trebuie să plătească taxa de sănătate... doar dacă credeţi că e necesar, poftim şi un model: if(P_Data[playerid][pMember] == 1 || P_Data[playerid][pLeader] == 1)// verificăm dacă playerul are lider sau member = 1 { SetPlayerPos(playerid,1532.0398, -1677.7267, 5.8906); SetPlayerInterior(playerid,0); SetPlayerVirtualWorld(playerid, 0); GivePlayerWeapon(playerid, 31, 250);// îi da armă cu id 31(M4A) cu 250 gloanţe GivePlayerMoney(playerid,-50);// îi scade suma de 50$ din cont SetPlayerArmour(playerid, 100);// pentru că e poliţai îi da şi 100 armură //Voi puteţi şterge ce nu va convine, treaba voastră , eu am arătat că se poate şi treaba asta, o putem lungi foarte mult , dar nu cred că are sens } Voi adăugaţi care cum vreţi de preferinţă. Acuma că am făcut spawn ul mergem şi facem comenzile de enter şi exit. Mergem pe site-ul care l-am propus mai sus, şi alegem interiorul, interiorul fiind cu id 6 şi cu poziţia 246.783996,63.900199,1003.640625 , interiorul de la Police Departamant Los Santos. Facem prin 2 metode. Prima metodă comenzii , comandă e prin zcmd, totu simplu şi uşor , şi metodă 2 , metodă prin tasta, care e mai elegant să o foloseşti, pentru că jucătorul nu se chinuie să scrie "/enter" ci apasă doar o tasta, de preferat F. Prima metodă(metodă prin comandă): Mai întâi mergem şi ne punem o ordine în coordonate, adică care sunt de enter, care sunt de spawn , care sunt de intrare, de ieşire, în fine adică de unde îl luăm şi unde îl ducem. Eu mi-am pus deja o ordine şi facem în felul următor. 2 comenzi /enter şi /exit, ambele fiind pentru toate comenzile. Aici vreau să va vorbesc despre VirtualWorld-uri . ele pot fi denumite şi "dimensiuni" deoarece 2 playeri pot fi în aceaşi poziţie , dar în VirtualWorld-uri diferite, deci ei nu se văd, dar sunt în aceaşi poziţie nu se văd, nu se ating, cu VirtualWorld vom crea şi sala de antrenament , adică vom folosi acelaşi interior, dar fiecare facţiune va avea virtual World ul ei , pentru că playerii din 2 facţiuni diferite să nu se întâlnească, adică cumva vom avea 2 construcţii identice , dar în zone diferite(sau cu asta putem păcăli necunoscătorii). mcmd:enter(playerid,params[]) { if(IsPlayerConnected(playerid))// verificãm dacã playerul care foloseºte comandã este conectat { // facem comandã pentru civili: if(IsPlayerInRangeOfPoint(playerid,2, 1554.6113, -1675.6897, 16.1953))// verificãm dacã este în jurul coordonatei pe care am salvat-o , primul "2" de lângã playerid reprezintã distanþã dintre poziþie ºi player, adicã 2 metri {// dacã este în jurul poziþiei respective, la 2 metri distanþã TogglePlayerControllable(playerid, 1);// îl facem sã se poatã miºcã SetPlayerPos(playerid, 246.783996,63.900199,1003.640625);// îl teleportãm în poziþia interiorului SetPlayerInterior(playerid, 6);// îi dãm interior = 6, deoarece în acea poziþie, are nevoie de interiorul setat pe 6 cã sã vadã playerul obiectele, dacã nu , va cãdea în gol SetPlayerVirtualWorld(playerid, 1);// îl punem în Virtual World 1 deoarece este în interior, ºi aºa ar fi frumos dacã folosim interiorul. } // facem comandã pentru poliþist if(P_Data[playerid][pMember] == 1 || P_Data[playerid][pLeader] == 1)// verificãm dacã playerul are lider sau member = 1 { if(IsPlayerInRangeOfPoint(playerid,2, 1524.5369, -1677.8561, 6.2188))// verificãm dacã este în jurul coordonatei pe care am salvat-o ea fiind în parcarea poliþiei, deci va intrã din parcare în clãdire , nu din faþã clãdirii în clãdire {// dacã este în jurul poziþiei respective, la 2 metri distanþã TogglePlayerControllable(playerid, 1);// îl facem sã se poatã miºcã SetPlayerPos(playerid, 246.783996,63.900199,1003.640625);// îl teleportãm în poziþia interiorului SetPlayerInterior(playerid, 6);// îi dãm interior = 6, deoarece în acea poziþie, are nevoie de interiorul setat pe 6 cã sã vadã playerul obiectele, dacã nu , va cãdea în gol SetPlayerVirtualWorld(playerid, 1); } // facem pentru sala de antrenament if(IsPlayerInRangeOfPoint(playerid,2, 1568.4191, -1689.9735, 6.2188))// verificãm dacã este în jurul coordonatei pe care am salvat-o ea fiind în parcarea poliþiei , locul care vrem sã fie intrarea în sala de antrenament {// dacã este în jurul poziþiei respective, la 2 metri distanþã TogglePlayerControllable(playerid, 1);// îl facem sã se poatã miºcã // cãutãm pe forum ul respectiv interiorul de la sala de antrenament, ea având interior = 1, poziþie:1412.639892,-1.787510,1000.924377 SetPlayerPos(playerid, 1412.639892,-1.787510,1000.924377);// îl teleportãm în poziþia interiorului SetPlayerInterior(playerid, 1);// îi dãm interior = 1, deoarece în acea poziþie, are nevoie de interiorul setat pe 1 cã sã vadã playerul obiectele, dacã nu , va cãdea în gol SetPlayerVirtualWorld(playerid, 1);// aici apare virtual world 1 } } //dacã nu are lider/member = 1 , ºi folosesc comandã în preajma poziþiei, nu se vor teleporta. // voi trece peste enter-ul ºi exitul la facþiunea 2 referitor la interiorul secþiei ºi voi aratã cum mã folosesc la sala de antrenament if(P_Data[playerid][pMember] == 2 || P_Data[playerid][pLeader] == 2)// verificãm dacã playerul are lider sau member = 2 { if(IsPlayerInRangeOfPoint(playerid,2, 611.1915, -583.4981, 18.2109))// verificãm dacã este în jurul coordonatei pe care am salvat-o ea fiind în preajma poliþiei BlueBery, locul care vrem sã fie intrarea în sala de antrenament {// dacã este în jurul poziþiei respective, la 2 metri distanþã TogglePlayerControllable(playerid, 1);// îl facem sã se poatã miºcã // cãutãm pe forum ul respectiv interiorul de la sala de antrenament, ea având interior = 1, poziþie:1412.639892,-1.787510,1000.924377 SetPlayerPos(playerid, 1412.639892,-1.787510,1000.924377);// îl teleportãm în poziþia interiorului SetPlayerInterior(playerid, 1);// îi dãm interior = 6, deoarece în acea poziþie, are nevoie de interiorul setat pe 6 cã sã vadã playerul obiectele, dacã nu , va cãdea în gol SetPlayerVirtualWorld(playerid, 2);// aici apare virtual world 2 pentru a nu se întâmpina cu cei de la Police Departament Los Santos } } } return 1; } Iar în comandă /exit vom înlocui coordonatele de la IsPlayerInRangeOfPoint cu cele de la SetPlayerPos aşa: mcmd:exit(playerid,params[]) { if(IsPlayerConnected(playerid))// verificãm dacã playerul care foloseºte comandã este conectat { // facem comandã pentru civili: if(IsPlayerInRangeOfPoint(playerid,2, 246.783996,63.900199,1003.640625))// verificãm dacã este în jurul coordonatei de la intrare,în faþã uºii în police departament {// dacã este în jurul poziþiei respective, la 2 metri distanþã TogglePlayerControllable(playerid, 1);// îl facem sã se poatã miºcã SetPlayerPos(playerid, 1554.6113, -1675.6897, 16.1953);// îl teleportãm în poziþia din parcare SetPlayerInterior(playerid, 0);// îi dãm interior = 0 deoarece nu este într-un interior, ci este afarã SetPlayerVirtualWorld(playerid, 0);// îl punem în Virtual World 0 deoarece este în parcare ºi maºinile trebuie sã aparã pe harta, ele fiind în virtualWorld 0 } // facem comandã pentru poliþist if(P_Data[playerid][pMember] == 1 || P_Data[playerid][pLeader] == 1)// verificãm dacã playerul are lider sau member = 1 { if(IsPlayerInRangeOfPoint(playerid,2, 246.783996,63.900199,1003.640625))// verificãm dacã este în jurul coordonatei pe care am salvat-o ea fiind în parcarea poliþiei, deci va intrã din parcare în clãdire , nu din faþã clãdirii în clãdire {// dacã este în jurul poziþiei respective, la 2 metri distanþã TogglePlayerControllable(playerid, 1);// îl facem sã se poatã miºcã SetPlayerPos(playerid, 1524.5369, -1677.8561, 6.2188);// îl teleportãm în poziþia din parcare SetPlayerInterior(playerid, 0);// îi dãm interior = 6, deoarece în acea poziþie, are nevoie de interiorul setat pe 6 cã sã vadã playerul obiectele, dacã nu , va cãdea în gol SetPlayerVirtualWorld(playerid, 0);// la fel cã sus } // facem pentru sala de antrenament if(IsPlayerInRangeOfPoint(playerid,2, 1412.639892,-1.787510,1000.924377))// verificãm dacã este în jurul coordonatei pe care am salvat-o ea fiind în parcarea poliþiei , locul care vrem sã fie intrarea în sala de antrenament {// dacã este în jurul poziþiei respective, la 2 metri distanþã TogglePlayerControllable(playerid, 1);// îl facem sã se poatã miºcã // cãutãm pe forum ul respectiv interiorul de la sala de antrenament, ea având interior = 1, poziþie:1412.639892,-1.787510,1000.924377 SetPlayerPos(playerid, 1568.4191, -1689.9735, 6.2188);// îl teleportãm în poziþia ieºirii SetPlayerInterior(playerid, 1);// îi dãm interior = 6, deoarece în acea poziþie, are nevoie de interiorul setat pe 1 cã sã vadã playerul obiectele, dacã nu , va cãdea în gol SetPlayerVirtualWorld(playerid, 0);// aici îi dãm virtualWorld 0 pentru a apãrea maºinile, el fiind ºi VirtualWorld-ul în care se joacã playerii } } //dacã nu are lider/member = 1 , ºi folosesc comandã în preajma poziþiei, nu se vor teleporta. // voi trece peste enter-ul ºi exitul la facþiunea 2 referitor la interiorul secþiei ºi voi aratã cum mã folosesc la sala de antrenament if(P_Data[playerid][pMember] == 2 || P_Data[playerid][pLeader] == 2)// verificãm dacã playerul are lider sau member = 2 { if(IsPlayerInRangeOfPoint(playerid,2, 1412.639892,-1.787510,1000.924377))// verificãm dacã este în jurul coordonatei din interiorul sãlii de antrenament {// dacã este în jurul poziþiei respective, la 2 metri distanþã TogglePlayerControllable(playerid, 1);// îl facem sã se poatã miºcã // cãutãm pe forum ul respectiv interiorul de la sala de antrenament, ea având interior = 1, poziþie:1412.639892,-1.787510,1000.924377 SetPlayerPos(playerid, 611.1915, -583.4981, 18.2109);// îl teleportãm în poziþia de afarã, în faþã secþiei SetPlayerInterior(playerid, 0);// îi dãm interior = 0, deoarece în acea poziþie el nu mai este în interior SetPlayerVirtualWorld(playerid, 0);// aici apare virtual world 0 la fel cã ºi cel de sus, al Police-ului departament , pentru cã ambele poziþii vor avea ieºire în virtualWorld 0 } } } return 1; } Aţi observat că v-am vorbit de virtual world-uri. ATENŢIE!!!! aveţi grijă cu ele, dacă nu , playerii vor fi rătăciţi printre ele. Am mai spus şi sus, ele sunt făcute că să nu se întâlnească playerii, şi va dau şi un exemplu pe care sigur l-aţi văzut. Mergem pe un server RPG. Şi aici mergem la benzinărie , în magazin şi vedem un interior. Merge un prieten de-al vostru în alt 24/7 dar când intră, vede acelaşi interior. Ei au intrat unul de la benzinărie , celălalt din altă parte, dar sunt în aceaşi poziţie , dar nu se văd. Asta pentru că sunt în VirtualWorld-uri diferite, dar după ce ies se pot întâlni, pentru că sunt în Virtual World 0. Sper că am lămurit până aici cu interioarele şi virtualWorild-urile. Metodă a două(metodă prin tasta): Mai întâi alegem o tasta de AICI. Eu am ales tasta F/ENTER adică "KEY_SECONDARY_ATTACK ". Avem nevoie de public-ul OnPlayerKeyStateChange, iar în comandă vom înlocui în loc de CMD:enter(playerid,params[]) cu if (newkeys & KEY_SECONDARY_ATTACK) Şi va sună cam aşa: public OnPlayerKeyStateChange(playerid, newkeys, oldkeys) { if (newkeys & KEY_SECONDARY_ATTACK) { // punem poziþiile de enter if(IsPlayerConnected(playerid))// verificãm dacã playerul care foloseºte comandã este conectat { // facem comandã pentru civili: if(IsPlayerInRangeOfPoint(playerid,2, 1554.6113, -1675.6897, 16.1953))// verificãm dacã este în jurul coordonatei pe care am salvat-o , primul "2" de lângã playerid reprezintã distanþã dintre poziþie ºi player, adicã 2 metri {// dacã este în jurul poziþiei respective, la 2 metri distanþã TogglePlayerControllable(playerid, 1);// îl facem sã se poatã miºcã SetPlayerPos(playerid, 246.783996,63.900199,1003.640625);// îl teleportãm în poziþia interiorului SetPlayerInterior(playerid, 6);// îi dãm interior = 6, deoarece în acea poziþie, are nevoie de interiorul setat pe 6 cã sã vadã playerul obiectele, dacã nu , va cãdea în gol SetPlayerVirtualWorld(playerid, 1);// îl punem în Virtual World 1 deoarece este în interior, ºi aºa ar fi frumos dacã folosim interiorul. } // facem comandã pentru poliþist if(P_Data[playerid][pMember] == 1 || P_Data[playerid][pLeader] == 1)// verificãm dacã playerul are lider sau member = 1 { if(IsPlayerInRangeOfPoint(playerid,2, 1524.5369, -1677.8561, 6.2188))// verificãm dacã este în jurul coordonatei pe care am salvat-o ea fiind în parcarea poliþiei, deci va intrã din parcare în clãdire , nu din faþã clãdirii în clãdire {// dacã este în jurul poziþiei respective, la 2 metri distanþã TogglePlayerControllable(playerid, 1);// îl facem sã se poatã miºcã SetPlayerPos(playerid, 246.783996,63.900199,1003.640625);// îl teleportãm în poziþia interiorului SetPlayerInterior(playerid, 6);// îi dãm interior = 6, deoarece în acea poziþie, are nevoie de interiorul setat pe 6 cã sã vadã playerul obiectele, dacã nu , va cãdea în gol SetPlayerVirtualWorld(playerid, 1); } // facem pentru sala de antrenament if(IsPlayerInRangeOfPoint(playerid,2, 1568.4191, -1689.9735, 6.2188))// verificãm dacã este în jurul coordonatei pe care am salvat-o ea fiind în parcarea poliþiei , locul care vrem sã fie intrarea în sala de antrenament {// dacã este în jurul poziþiei respective, la 2 metri distanþã TogglePlayerControllable(playerid, 1);// îl facem sã se poatã miºcã // cãutãm pe forum ul respectiv interiorul de la sala de antrenament, ea având interior = 1, poziþie:1412.639892,-1.787510,1000.924377 SetPlayerPos(playerid, 1412.639892,-1.787510,1000.924377);// îl teleportãm în poziþia interiorului SetPlayerInterior(playerid, 1);// îi dãm interior = 1, deoarece în acea poziþie, are nevoie de interiorul setat pe 1 cã sã vadã playerul obiectele, dacã nu , va cãdea în gol SetPlayerVirtualWorld(playerid, 1);// aici apare virtual world 1 } } //dacã nu are lider/member = 1 , ºi folosesc comandã în preajma poziþiei, nu se vor teleporta. // voi trece peste enter-ul ºi exitul la facþiunea 2 referitor la interiorul secþiei ºi voi aratã cum mã folosesc la sala de antrenament if(P_Data[playerid][pMember] == 2 || P_Data[playerid][pLeader] == 2)// verificãm dacã playerul are lider sau member = 2 { if(IsPlayerInRangeOfPoint(playerid,2, 611.1915, -583.4981, 18.2109))// verificãm dacã este în jurul coordonatei pe care am salvat-o ea fiind în preajma poliþiei BlueBery, locul care vrem sã fie intrarea în sala de antrenament {// dacã este în jurul poziþiei respective, la 2 metri distanþã TogglePlayerControllable(playerid, 1);// îl facem sã se poatã miºcã // cãutãm pe forum ul respectiv interiorul de la sala de antrenament, ea având interior = 1, poziþie:1412.639892,-1.787510,1000.924377 SetPlayerPos(playerid, 1412.639892,-1.787510,1000.924377);// îl teleportãm în poziþia interiorului SetPlayerInterior(playerid, 1);// îi dãm interior = 6, deoarece în acea poziþie, are nevoie de interiorul setat pe 6 cã sã vadã playerul obiectele, dacã nu , va cãdea în gol SetPlayerVirtualWorld(playerid, 2);// aici apare virtual world 2 pentru a nu se întâmpina cu cei de la Police Departament Los Santos } } } // punem ºi poziþiile de exit if(IsPlayerConnected(playerid))// verificãm dacã playerul care foloseºte comandã este conectat { // facem comandã pentru civili: if(IsPlayerInRangeOfPoint(playerid,2, 246.783996,63.900199,1003.640625))// verificãm dacã este în jurul coordonatei de la intrare,în faþã uºii în police departament {// dacã este în jurul poziþiei respective, la 2 metri distanþã TogglePlayerControllable(playerid, 1);// îl facem sã se poatã miºcã SetPlayerPos(playerid, 1554.6113, -1675.6897, 16.1953);// îl teleportãm în poziþia din parcare SetPlayerInterior(playerid, 0);// îi dãm interior = 0 deoarece nu este într-un interior, ci este afarã SetPlayerVirtualWorld(playerid, 0);// îl punem în Virtual World 0 deoarece este în parcare ºi maºinile trebuie sã aparã pe harta, ele fiind în virtualWorld 0 } // facem comandã pentru poliþist if(P_Data[playerid][pMember] == 1 || P_Data[playerid][pLeader] == 1)// verificãm dacã playerul are lider sau member = 1 { if(IsPlayerInRangeOfPoint(playerid,2, 246.783996,63.900199,1003.640625))// verificãm dacã este în jurul coordonatei pe care am salvat-o ea fiind în parcarea poliþiei, deci va intrã din parcare în clãdire , nu din faþã clãdirii în clãdire {// dacã este în jurul poziþiei respective, la 2 metri distanþã TogglePlayerControllable(playerid, 1);// îl facem sã se poatã miºcã SetPlayerPos(playerid, 1524.5369, -1677.8561, 6.2188);// îl teleportãm în poziþia din parcare SetPlayerInterior(playerid, 0);// îi dãm interior = 6, deoarece în acea poziþie, are nevoie de interiorul setat pe 6 cã sã vadã playerul obiectele, dacã nu , va cãdea în gol SetPlayerVirtualWorld(playerid, 0);// la fel cã sus } // facem pentru sala de antrenament if(IsPlayerInRangeOfPoint(playerid,2, 1412.639892,-1.787510,1000.924377))// verificãm dacã este în jurul coordonatei pe care am salvat-o ea fiind în parcarea poliþiei , locul care vrem sã fie intrarea în sala de antrenament {// dacã este în jurul poziþiei respective, la 2 metri distanþã TogglePlayerControllable(playerid, 1);// îl facem sã se poatã miºcã // cãutãm pe forum ul respectiv interiorul de la sala de antrenament, ea având interior = 1, poziþie:1412.639892,-1.787510,1000.924377 SetPlayerPos(playerid, 1568.4191, -1689.9735, 6.2188);// îl teleportãm în poziþia ieºirii SetPlayerInterior(playerid, 1);// îi dãm interior = 6, deoarece în acea poziþie, are nevoie de interiorul setat pe 1 cã sã vadã playerul obiectele, dacã nu , va cãdea în gol SetPlayerVirtualWorld(playerid, 0);// aici îi dãm virtualWorld 0 pentru a apãrea maºinile, el fiind ºi VirtualWorld-ul în care se joacã playerii } } //dacã nu are lider/member = 1 , ºi folosesc comandã în preajma poziþiei, nu se vor teleporta. // voi trece peste enter-ul ºi exitul la facþiunea 2 referitor la interiorul secþiei ºi voi aratã cum mã folosesc la sala de antrenament if(P_Data[playerid][pMember] == 2 || P_Data[playerid][pLeader] == 2)// verificãm dacã playerul are lider sau member = 2 { if(IsPlayerInRangeOfPoint(playerid,2, 1412.639892,-1.787510,1000.924377))// verificãm dacã este în jurul coordonatei din interiorul sãlii de antrenament {// dacã este în jurul poziþiei respective, la 2 metri distanþã TogglePlayerControllable(playerid, 1);// îl facem sã se poatã miºcã // cãutãm pe forum ul respectiv interiorul de la sala de antrenament, ea având interior = 1, poziþie:1412.639892,-1.787510,1000.924377 SetPlayerPos(playerid, 611.1915, -583.4981, 18.2109);// îl teleportãm în poziþia de afarã, în faþã secþiei SetPlayerInterior(playerid, 0);// îi dãm interior = 0, deoarece în acea poziþie el nu mai este în interior SetPlayerVirtualWorld(playerid, 0);// aici apare virtual world 0 la fel cã ºi cel de sus, al Police-ului departament , pentru cã ambele poziþii vor avea ieºire în virtualWorld 0 } } } } return 1; } Acum putem testa şi vedem că putem intră în clădiri , putem ieşi, fără nici o problema. Acum , se pune problema , că jucătorul să vadă că acolo se intră, şi marcăm cu un pick-up şi un text 3D. Mergem AICI şi căutăm un pick-up care ne convine , şi îl vom crea. Eu am ales pickup cu id 1239. Mergem la public-ul OnGameModeInit şi adăugăm aşa: AddStaticPickUp(model, type, Float:X, Float:Y, Float:Z, Virtualworld) model- modelul pickup-ului, în cazul nostru 1239 type- tipul de pick-up, adică dacă va dispărea , dacă nu, căutaţi pe wiki PickupTypes şi gătiţi detalii Float x y z sunt poziţiile VirtualWorld este virtual-word-ul în care suntem Eu voi crea 2 Pick-up-uri şi 2 3Dtext-uri , adică cel de la intrarea în Police Departament a civililor şi unul în secţie. Create3DTextLabel(text[], color, Float:X, Float:Y, Float:Z, Float:DrawDistance, virtualworld, testLOS) text[] este textul, el se pune între ghilimele "" color- culoarea textului Float:X, Float:Y, Float:Z poziţiile 3Dtext-ului Float:DrawDistance - distanţă maximă de care să se vadă 3DText-ul virtualworld- virtualWorld-ul în care se află playerul testLOS - reprezintă 2 valori aici 0/1 şi corespund văzului, adică dacă să se vadă prin pereţi sau nu Mergem la OnGameModeInit şi punem aşa: Create3DTextLabel("Apasă F sau scrie /entern pentru a intră!", -1,1554.6113, -1675.6897, 16.1953, 10.0, 0, 0);// textul din faţă poliţiei Create3DTextLabel("Apasă F sau scrie /exitn pentru a intră!", -1,246.783996,63.900199,1003.640625, 10.0, 1, 0);// textul din interiorul poliţiei AddStaticPickup(1314, 23, 1554.6113, -1675.6897, 16.1953);// pickup-ul din faţă secţiei de poliţie, observăm că faţă de al 2-lea nu are pus 1, deoarece suntem în Virtual World 0, şi nu mai are rost să punem ",0" la urmă AddStaticPickup(1314, 23, 246.783996,63.900199,1003.640625,1);// pickup-ul din interiorul secţiei, are virtualWorld 0 Observăm aici că nu au condiţie de interior, deci e un avantaj. Acum mergem , testăm, totul ok şi mai avem nevoie de culoare la facţiune. Mergem AICI şi definim culorile în GM Atenţie în text punem culoarea între paranteze, dar nu oricum ci în felul următor: 0xAFAFAFAA -> {AFAFAF} deci din culoarea definită "0xAFAFAFAA" am scos "0x AFAFAF AA" AA şi 0x de la început , iar înăutru parantezei sunt celelalte 6 caractere. Avem mai întâi nevoie de ProxDetector, pentru a vedea de la o limita de distanţă în chat, avem nevoie şi de forech, care îl găsiţi aici şi îl definim: #define COLOR_FADE1 0xE6E6E6E6 #define COLOR_FADE2 0xC8C8C8C8 #define COLOR_FADE3 0xAAAAAAAA #define COLOR_FADE4 0x8C8C8C8C #define COLOR_FADE5 0x6E6E6E6E forward ProxDetector(Float:radi, playerid, string[], col1, col2, col3, col4, col5); public ProxDetector(Float:radi, playerid, string[], col1, col2, col3, col4, col5) { if(IsPlayerConnected(playerid)) { new Float:posx, Float:posy, Float:posz; new Float:oldposx, Float:oldposy, Float:oldposz; new Float:tempposx, Float:tempposy, Float:tempposz; GetPlayerPos(playerid, oldposx, oldposy, oldposz); foreach(Player, i) { if(GetPlayerVirtualWorld(i) == GetPlayerVirtualWorld(playerid)) { GetPlayerPos(i, posx, posy, posz); tempposx = (oldposx -posx); tempposy = (oldposy -posy); tempposz = (oldposz -posz); if (((tempposx < radi/16) && (tempposx > -radi/16)) && ((tempposy < radi/16) && (tempposy > -radi/16)) && ((tempposz < radi/16) && (tempposz > -radi/16))) { SendClientMessage(i, col1, string); } else if (((tempposx < radi/8) && (tempposx > -radi/8)) && ((tempposy < radi/8) && (tempposy > -radi/8)) && ((tempposz < radi/8) && (tempposz > -radi/8))) { SendClientMessage(i, col2, string); } else if (((tempposx < radi/4) && (tempposx > -radi/4)) && ((tempposy < radi/4) && (tempposy > -radi/4)) && ((tempposz < radi/4) && (tempposz > -radi/4))) { SendClientMessage(i, col3, string); } else if (((tempposx < radi/2) && (tempposx > -radi/2)) && ((tempposy < radi/2) && (tempposy > -radi/2)) && ((tempposz < radi/2) && (tempposz > -radi/2))) { SendClientMessage(i, col4, string); } else if (((tempposx < radi) && (tempposx > -radi)) && ((tempposy < radi) && (tempposy > -radi)) && ((tempposz < radi) && (tempposz > -radi))) { SendClientMessage(i, col5, string); } } else { SendClientMessage(i, col1, string); } } } return 0; } Acesta îl găsiţi şi pe internet, etc, noi îl vom folosi. Mergem mai întâi să modificăm scrisul în chat, adică la public-ul OnPlayerText şi punem aşa: public OnPlayerText(playerid, text[]) { new strîng[1000];// facem strîng-ul şi text-ul de 1000 de caractere, adică să scrie până la 1000 de caractere(SPACE se ia că caracterd) if(P_Data[playerid][pMember] == 1 || P_Data[playerid][pLeader] == 1)// dacă e lider/member 1 {//scrie în chat(cu T) format(strîng, sizeof(strîng), "{2641FE}%s {FFFFFF}: %s", GetName(playerid), text);//observaţi că va fi de genu {2641FE}Widualk: mesaj // {2641FE} este culoarea albastră, adică va fi scris Widualk cu albastru dacă sunt poliţist // {FFFFFF} - este culoarea alb, şi mesajum meu este cu alb, deci mesaj>alb nume>albastru SetPlayerChatBubble(playerid, text, -1, 30.0, 10000);// SetPlayerChatBubble face că mesajul să fie scris deasupra capului, -1 reprezintă culoarea albă //-1 reprezintă culoarea albă, 30.0 reprezintă distanţă la care vede celălalt jucător mesajul, în cazul nostru se vede deasupra capului până la distanţă de 30 m // 10000> reprezintă timpul adică 10 secunde, 1000 însemnând 1 secundă ProxDetector(20.0, playerid, strîng, COLOR_FADE1, COLOR_FADE2, COLOR_FADE3, COLOR_FADE4, COLOR_FADE5); // Aici ProxDetector face că textul în chat să fie văzut de la distanţă de 20metri //Adică trebuie să ai fi la cel mult 30metri să îi vezi textul deasupra capului şi la max 20 metri să vezi textul în chat } //la facţiunea 2(Police BlueBerry) else if(P_Data[playerid][pMember] == 2 || P_Data[playerid][pLeader] == 2)//dacă e în facţiunea nr 2 că membru/lider/amândouă {//şi scrie în chat, o să se întâmple că mai sus. format(strîng, sizeof(strîng), "{1E519D}%s {FFFFFF}: %s", GetName(playerid), text); SetPlayerChatBubble(playerid, text, -1, 30.0, 10000); ProxDetector(20.0, playerid, strîng, COLOR_FADE1, COLOR_FADE2, COLOR_FADE3, COLOR_FADE4, COLOR_FADE5); } //acum, dacă nu are lider/member la cele de mai sus, adică este civil else { // este civil şi scrie în chat format(strîng, sizeof(strîng), "{FFFFFF}%s {FFFFFF}: %s", GetName(playerid), text); //la fel că mai sus, dar numele îi apare cu alb("{FFFFFF}") SetPlayerChatBubble(playerid, text, -1, 30.0, 10000); ProxDetector(20.0, playerid, strîng, COLOR_FADE1, COLOR_FADE2, COLOR_FADE3, COLOR_FADE4, COLOR_FADE5); } return 1; } Acum, mergem , verificăm, şi mai ramande de făcut un singur lucru, când apăsăm TAB să apară numele cu o culoare. Când te apropi de el, are culoarea albă, noi o modificăm tot cu aceast callback Mergem şi definim un nou callback, şi un public al callback-ului forward FactionColor(playerid);// definim Callback-ul public FactionColor(playerid)// facem callback-ul { if(IsPlayerConnected(playerid))// verificăm dacă este conectat { SetPlayerColor(playerid, COLOR_WHITE);// dacă nu are lider/member într-o facţiune să scrie cu alb if(P_Data[playerid][pMember] == 1 || P_Data[playerid][pLeader] == 1)// dacă are lider/member 1 SetPlayerColor(playerid,COLOR_BLUE);// culoarea playerului este albastră if (P_Data[playerid][pMember] == 2 || P_Data[playerid][pLeader] == 2)// dacă are lider/member 2 SetPlayerColor(playerid,COLOR_BLUE);// culoarea playerului este albastră } return 1; } Acum mergem la OnPlayerSpawn şi adăugăm la urmă: //liniile care le avem else// aici vom verifică dacă nu are lider să îl spawneze la locul dorit { SetPlayerPos(playerid, 1479.6548, -1725.2207, 13.5469); SetPlayerInterior(playerid,0);// nu este într-o clădire sau altcv , deci îi vom seta 0 când se spawneaza SetPlayerVirtualWorld(playerid, 0); } // asta e ultimul else, şi după el adăugăm: FactionColor(playerid);// când se spawneaza să îi dea culoare Atenţie, dacă sunteţi singur pe server, nu puteţi vedea, deoarece numele vostru e selectat, şi va apărea mereu cu alb, folosiţi tutorialul pentru a testa cu prietenii fără HOST. Mă scuzaţi de întârziere, dar am avut mult de scris... am făcut şi poze, am stat sa pun diacritice, am făcut mai mult decât mi-am propus... DIN FERICIRE PENTRU VOI. Sper că am fost de folos cu acest tutorial, am să vin cu ultima parte cât de repede am să pot. Până dată viitoare PACE!
  12. 9 points
    Informaţii Acest gamemode (GM) este făcut de mine de la 0. Am reuşit să-l fac după ce Pain123 a lansat versiunea MySQL R33 BlueG. Am lucrat la el încă de la versiunea MySQL R31 BlueG. Când a apărut versiunea MySQL R33 BlueG am făcut mici modificări. L-am făcut deoarece am început să-mi creez propriul gamemode, nu are toate comenziile pentru un server RPG, este o versiune (stabilă) pentru a începe un server RPG de la 0. Dacă faceţi un server cu acest gamemode respectaţi această licenţă. Caracteristic - Un sistem de incarcare mai rapida a datelor. (Cache) - Un sistem de Înregistrare / Logare bazat pe MySQL. Comenzi - Comandă /makeadmin, poţi să îi dai unui jucător admin sau chiar ţie. Trebuie să ai admin level 6 sau să fi logat că RCON. - Comandă /makehelper, poţi să îi dai unui jucător helper sau chiar ţie. Trebuie să ai admin level 6 sau să fi logat că RCON. - Comandă /ah sau /adminhelp, îţi arată comenziile pentru admini , pe level-ul pe care îl deţine admin-ul. Dacă ai admin level 1, îţi arată comenziile pentru admin level 1, s.a.m.d. - Comandă /hh sau /helperhelp, îţi arată comenziile pentru helper, pe level-ul pe care îl deţine helper-ul. Dacă ai helper level 1, îţi arată comenziile pentru helper level 1, s.a.m.d. - Comandă /a sau /adminchat, poţi să scri un mesaj, vizibil tuturor adminilor online. - Comandă /he sau /helperchat, poţi să scri un mesaj, vizibil tuturor helperilor online. - Comandă /report, trimite un mesaj adminilor online, în caz că ai nevoie de ajutor. O poţi folosi odată la 10 secunde. - Comandă /helpme, trimite un mesaj helperilor online, în caz că ai nevoie de ajutor. O poţi folosi odată la 10 secunde. - Comandă /stats, îţi arată status-ul tău. - Comandă /check, verifică status-ul unui jucător (ales de către admin ). Se poate folosi de admini şi helper. - Comandă /makeleader, face un jucător lider (ales de către admin ). Se poate folosi de admini level 6. V0.2 - Comandă /ban, poţi să-i dai ban unui jucător. Se poate folosi de admini level 1, minim. - Comandă (/bano)ffline, poţi să-i dai ban unui jucător offline. Se poate folosi de admini level 2, minim. - Comandă /kick, poţi să scoţi afară un jucător după server. Se poate folosi de admini level 1, minim. - Comandă /respawn, poţi să respawnezi un jucător după server, fie că este în facţiune sau nu. Se poate folosi de admini level 1, minim. - Comandă (/checkw)eapons, poţi să vezi armele unui jucător după server. Se poate folosi de admini level 1, minim. - Comandă /auninvite, poţi să scoţi un jucător din facţiune. Se poate folosi de admini level 6. - Comandă /spec || /rcon, poţi să asişti un jucător după server. Poţi vedea orice face el. Se poate folosi de admini level 1, minim. - Comandă /gethere, poţi să aduci la ţine o maşină sau un jucător, în funcţie de caz. Se poate folosi de admini level 1, minim. - Comandă /goto, poţi să te duci la un jucător, o maşină sau o locaţie, în funcţie de caz. Se poate folosi de admini level 1, minim. - Comandă /uninvite, poţi să scoţi / concediezi un jucător din facţiune, doar dacă eşti leaderul facţiunii respective. Se poate folosi de leaderi. - Comandă (/f)action, poţi să scrii orice pe acest chat şi toţi ceilalţi membrii din facitune o pot vedea, oriunde se află. Se poate folosi de membrii factiuniilor. - Comandă (/r)adio, este la fel că (/f)action, dar doar câteva facţiuni o pot folosi. Se poate folosi de membrii factiuniilor (LSPD / LVPD / SFPD / NG / Paramedics). Instrucţiuni / Instalare - Dacă vreţi să rulaţi server-ul, descărcaţi SA-MP Server for Windows or Linux, după această descărcaţi şi MySQL BlueG R33 şi puneţi gamemodes, pawno şi server.cfg în fişierul unde aţi descărcat SA-MP Server for Windows or Linux. - Dacă vreţi să editaţi datele pentru baza de date, va duceţi în pawno\include şi dechideti cu Notepad / Visual Studio / Wordpad etc. şi dechideti connection.inc. Modificaţi următoarele linii: #define mysql_host "ip-ul host-ului" #define mysql_user "numele de utilizator pentru baza de date (MySQL)" #define mysql_password "parolă pentru baza de date (MySQL)" #define mysql_database "numele bazei de date"- Baza de date o găsiţi în folder-ul pe care îl descărcaţi sub numele de w3op.sql - Dacă vreţi să modificaţi level-ul, banii, banii în banca etc. va duceţi în gamemode (GM) şi căutaţi linia pLevel, pCash, pAccount etc., în funcţie de caz, după această va duceţi şi în baza de date MySQL şi modificaţi valoarea iniţială. Informaţii suplimentare - Dacă aveţi întrebări sau nelamuri postaţi în acest topic. - Acesta este primul meu gamemode (GM), va rog, nu fiţi răi. V0.2 div.pawn { background-color: #fafafa !important; -moz-border-radius: 4px; -webkit-border-radius: 4px; -o-border-radius: 4px; -ms-border-radius: 4px; -khtml-border-radius: 4px; border-radius: 4px; color: #000000; padding: 5px; border: 1px solid #c9c9c9; overflow: auto; margin-left: 10px; font-size: 13px; line-height: 140%; font-family: monospace !important; max-height: 300px; } div.pawn { width: 95%; margin: 1em auto; padding: 1em; /* white-space: pre-wrap; */ } - Parola a fost mascată în MD5, pentru a nu o vedea şi alţii.- Comenziile următoare adăugate: /ban, /banoffline sau /bano, /kick, /auninvite, /respawn, /checkweapons sau /checkw, /spec sau /rcon, /gethere, /goto, /uninvite, /faction sau /f, /radio sau /r. - Adăugate 6 facţiuni: Los Santos Police Depratment, Las Venturas Police Depratment, San Fierro Police Depratment, Federal Bureau of Investigation, Naţional Guard and Paramedic. (nu au maşini la spawn!) - Conexiunea MySQL a fost adăugată în folderul "connection". - Redenumit folderul "myacc" în "accounts". - Atunci când MySQL nu se poate conecta la baza de date o să se închidă consola, iar în log va apărea mesajul specific ("[MYSQL]: Connection to database (db) failed!"). - Logurile o să apară în HTML datorită lui InfiniTy. - Rescrise querty pentru update, pLevelx => pLevelu, pAdminx => pAdminu etc. pentru că se asemăna foarte mult cu gamemode-ul de la redzmax. "u" = update! - Adăugat statutul de Premium Account (momentan nu are avantaje & se poate obţine doar din MySQL). V0.1 div.pawn { background-color: #fafafa !important; -moz-border-radius: 4px; -webkit-border-radius: 4px; -o-border-radius: 4px; -ms-border-radius: 4px; -khtml-border-radius: 4px; border-radius: 4px; color: #000000; padding: 5px; border: 1px solid #c9c9c9; overflow: auto; margin-left: 10px; font-size: 13px; line-height: 140%; font-family: monospace !important; max-height: 300px; } div.pawn { width: 95%; margin: 1em auto; padding: 1em; /* white-space: pre-wrap; */ } - Întregul gamemode (GM) Buguri - N-am gasit nici un bug încă. Descărcări - San Andreas Multiplayer Romania- Descarca (V0.2) - San Andreas Multiplayer Romania- Descarca (V0.1) - SolidFiles- Descarca (V0.2) - SolidFiles- Descarca (V0.1) Credite BlueG & maddinat0r - Pentru plugin-ul MySQL. * Aceasta este o versiune veche si neoptimizata a acestui gamemode!
  13. 9 points
    Salutare, astazi vreau sa vorbim despre hack-uri. Multi jucatori vor sa abuzeze de niste chaturi cum ar fi sobeit sau money hack sau barbut hack sau multe altele.... In primul rand, nu exista hack-urile astea nu vor merge , si de ce va spun ca nu vor merge? Inafara de sobeit, money-hack, si barbut sau coins hack sau ce mai cautati voi nu va vor da nici odata bani, sau noroc la barbut pentru ca ele sunt simple programe. Q:Si de ce nu vor merge daca sunt simple programe? A: Sunt niste facaturi, si ele merg doar in GTA-San Andreas, pe serverele de sa-mp nu vor merge ca trebuie sa apeleze la server(GM), adica trebuie sa foloseasca functia GivePlayerMoney, si sunt rare hack-urile care o folosesc, la fel si la barbut hack. Barbut-ul foloseste random(alegere), adica alege numerele la intamplare, si barbut hack nu poate apela la aceste functii, la fel si coins hack sau alte prosti. Pentru cateva hack-uri care merg, de exemplu sobeit care are integrata funcia jetpack si merge, sau teleport se pot crea callback-uri pentru a contracara acestea. De exemplu la jetpack putem apela la urmatoarea: public OnPlayerUpdate(playerid) { if(GetPlayerSpecialAction(playerid) == SPECIAL_ACTION_USEJETPACK) { if(PlayerInfo[playerid][pAdmin] < 1) { Kick(playerid); } } return 1; } sau la moneyHack putem apela la urmatorul stock: http://forum.sa-mp.com/showthread.php?t=71136 Daca vrem sa ii returnam kick player-ului care se teleporteaza fara admin putem face urmatoarea: new pTeleported[MAX_PLAYERS]; forward PlayerTeleported(playerid); public PlayerTeleported(playerid) { pTeleported[playerid] = 0; } public OnPlayerConnect(playerid) { pTeleported[playerid] = 0; } CMD:gotols( playerid ) { if(P_DATA[playerid][pAdmin] >= 1 || P_DATA[playerid][pHelper] >= 2) { } else return SendError( playerid, "/gotols" ); gszString[ 0 ] = EOS; InHouse [ playerid ] = 0; if (GetPlayerState(playerid) == 2) { new tmpcar = GetPlayerVehicleID(playerid); SetVehiclePos(tmpcar, 1529.6,-1691.2,13.3); } else { SetPlayerPos(playerid, 1529.6,-1691.2,13.3); } SendClientMessage(playerid, COLOR_WHITE, "Ai fost teleportat cu succes!"); SetPlayerVirtualWorld(playerid, 0); SetPlayerInterior(playerid,0); P_DATA[playerid][pInt] = 0; pTeleported[playerid] = 1; SetTimerEx("PlayerTeleported", 1500, false, "i", playerid); format(gszString, 144, "{2D82D6}AW{FFFFFF}:{FFFFFF} Admin %s s-a teleportat. (/gotols)", GetPName( playerid ) ); SendAdminMessage( -1, gszString ); return 1; } Si inafara de asta trebuie a luam in calcul si viteza cu care playerul strabate drumul de unde e pana in fata PD-ului , de obicei ajunge la 7000 m/s. si putem pune conditia: if(PvitezaTeleported[playerid > 1000) { if(pTeleported[playerid] == 0) { Kick(playerid); SendClientMessage(playerid,culoare,"Ai folosit un hack de teleportare!"); } } Acum eu v-am aratat o metoda de gandire, voi trebuie sa creati conditiile si functiile complete. La fel trebuie gandit si anti gun hack-ul. V-am aratat doar cum trebuie sa ganditi aceste functii. Cam atat v-am putut zice, daca mai aveti metode de antichat postatile cu un reply.
  14. 8 points
    Stiu ca multi o sa ma injurati ca am pus acest gamemode pe internet,dar na asta e... Factiuni Los Santos Police Department Federal Bureau of Investigation National Guard Hitman Agency Taxi Cab Company News Reporters Paramedic Department School Instructors Grove Street Los Vagos Los Astecaz The Rifa The Russian Mafia Ballas # Poze: Nu am facut. # Versiune: 0.3.7 # Link de descarcare: Link 1: Girlshare.ro Link 2: Fileshare.ro Link 3: Zippyshare.com # Parola arhiva: mr.yonutz_zm # Link virustotal: ViruslTotal.Com # Descriere Gamemode: Am facut noi UPDATE, nu le voi posta. Si sper ca acum sa mearga ok, inainte aveai cateodata drop flame ori aveai setat 1 fps automat de la server (si aveai lag). Rezolvat! * Rezolvat sistemul de masini personale, acum nu mai permite urcarea intr-o masina a cuiva, de altcineva. * Comanda /createhouse ar trebui sa functioneze corect acum. * Rezolvate comenzile /areaheal /areafreeze /areadisarm /areagun /areaunfreeze * Am sters anumite fisiere din folderul cu serverul, care erau inutile * Acuma aveti si o versiune de UCP pentru acest server. * Alte actualizari gasiti in el. * Pentru porni serverul aveti nevoie sa descarcati XAMPP. Macar un +1 daca se poate =)))))))))))))))))))))))))))))))))))))))))))))))))
  15. 8 points
    Salut SA-MP.RO. Vreau sa va arat cum puteti folosi Notepad ++ ca si compilator. Pe langa design-ul atractiv pe care il are, usurinta prin care poti selecta proiectele si varietatea de optiuni pe care le poti folosi(ex: combinatia de taste pentru compilare sau pentru orice actiune), auto-completarea mai este si multithreading. Ce este multithreading? Este abilitatea unui program/sistem de operare imparte actiunile la fiecare thread, acestea executandu-se mai repede. Daca ati observat, folosind PAWNO ca si compilator, daca aveti un numar mare de linii, compilatorul va da Non Responding, blocandu-se pentru o perioada mai mica sau mai mare de timp. Motivul pentru care se blocheaza este anume ca foloseste 1 singur thread, deci este single-thread. Notepad ++ nu va avea aceasta problema. Deci sa incepem In primul rand aveti nevoie de Notepad ++ https://notepad-plus-plus.org/download/v6.8.8.html Veti avea nevoie de 2 fisiere: userDefineLanguage.xml - pentru a evidentia limbajul si PAWN.xml - pentru design-ul limbajului. Am facut un winrar cu cele 2 fisiere. http://www.solidfiles.com/d/06d48873e9/ Pentru a nu exista discutii, am pus si virustotal: https://www.virustotal.com/ro/file/2a0688d8ef14a4804060c2433d3f2fad42b3fc7cc4595e415ad2488ccf850cf4/analysis/1452888736/ Acum ca avem tot ce e necesar, instalati Notepad ++ , intalarea este simpla Next>Next>Next> bifati sa se creeze pe desktop si finalizati instalarea. Acum intrati in My Computer si scrieti %appdata%\Notepad++: Introducem fisierul userDefineLanguage.xml Acum mergem in folderul instalarii Notepad ++ In folderul APIs Introducem PAWN.xml Acum mergem la Setari > Preference Asociem filele .pwn Executam auto-completarea , ATENTIE!!! bifati From 3 th character, pentru a executa auto-completarea la 3 caractere scrise Acum vom cauta plugin-ul care ne va ajuta la compilare: Bifam si instalam NppExec: Dupa ce instalati va necesita sa inchideti si sa redeschideti programul. Acum v-a trebui sa mergem la plugin-ul NppExec pentru a bifa No internal message. De ce? Pentru ca vor aparea mesaje inutile, si noi nu dorim acest lucru. Vom merge si vom face un folder cu Pawno. In acest folder vom adauga include-urile cu care vom compila orice fisier .pwn. De obicei eu il pun in Local Disk D. Pe urma v-a trebui sa ii luam adresa din Local Disk-ul in care se afla folderul Pawno. Mergem la plugin NppExec>Executare: Apoi introducem codul acesta: Apoi dati save si dati un nume, de preferat Pawn Compilator: Pentru a activa codul precedent mergem la Advanced Options: Bifati ca in imagine si dati OK: Setarile sunt realizate, acum va trebui sa bifam 2 chestii: 1) Mie personal imi place sa ma folosesc de F3 si F4 in cautarea unei denumiri. F3 e definit, dar F4 nu este setat pe back search. Asa ca il vom seta. 2) Vom seta tastele de pe care vom compila. Mie mi se pare confortabil sa compilez de pe CTRL + ALT + F5. Pentru ambele setari vom face in felul urmator: Mergem la Setari> Shoutcut Mapper: Vom modifica in felul urmator: Apoi mergem la Plugin Comands , iar la linia 35 vom gasi PAWNO Compilator: Si vom configura combinatia de taste pe care o vom face la compilare: Odata ce ne-am configurat Notepad ++ , recomandat ar fi sa folosim Zeex's Compilator. Este acelasi compilator folosit din totdeauna DAR este configurat de Zeek's care a rezolvat niste probleme, deci l-a imbunatatit. Link: http://forum.sa-mp.com/showthread.php?p=2768123 Mergem la Download> Executables Only iar dupa ce descarcam dezarhivam in folderul cu PAWNO pe care l-am facut anterior. Dezarhivati acolo si dati Copy and Replace. Nota: Dupa ce a-ti executat toti pasii compilati un fisier .pwn. Dupa ce compilati, adaugati niste caractere aiurea prin GM gen: apoi compilati. IN CAZ CA NU PRIMITI ERORI MERGETI LA Plugins > NppExec > BIFATI: Save all files on execute. Atentie: Inainte de a modifica combinatia de taste inchideti si deschideti programul pentru a-si face load la setarile facute. In caz ca nu se incarca plugin-urile dati inchideti si deschideti programul apoi cautati din nou. IN CAZ CA NU PUTETI INSTALA SAU GASI NPPEXEC LASATI REPLY SI IAR EU VOI RASPUNDE. Cam atat cu acest tutorial, multumesc pentru atentie!
  16. 8 points
    Tutorial Afk cu TextLabel Buna ziua, am vazut mai multe tutoriale de genul "afk" si majoritatea erau cu o comanda, dupa ce scriai comanda spunea ca playerul respectiv este afk. Acelea pareau destul de simple. Sper ca tutorialul meu este mult mai bun si sper sa va fie de ajuor. Sa incepem: Pentru inceput va trebui sa puneti acest fisier include in /pawno/includes OnPlayerPause.inc Adaugati la inceputul GM-ului asta #include <OnPlayerPause> //incarcam pluginul care ne va ajuta mai tarziuDupa asta punem la OnPlayerPause urmatorul cod. Puneti acest public undeva in gm, este functia includeului. public OnPlayerPause(playerid) // forwardul este in include deci nu mai trebuie sa il punem noi { afklabel[playerid] = Create3DTextLabel("afk",COLOR_WHITE,0,0,0,50,-1,1);// cream labelul pentru a putea sa il actualizam Attach3DTextLabelToPlayer(afklabel[playerid], playerid, 0,0,0);// atasam labelul de player pentru a vedea cine este afk SetTimerEx("PauseTime", 1000, false, "i", playerid);// apelam la functia de contorizare pentru a avea timpul corect de cand jucatorul este afk return 1; } Acum sa cream funcita care contorizeaza timpul afk forward PauseTime(playerid); public PauseTime(playerid) { if(IsPlayerPaused(playerid))// verificam daca playerul este AFK { new strings[40];// adaugam functia strings pentru a putea crea textul afktime[playerid] ++;// crestem secundele decand este afk format(strings, sizeof(strings), "Afk De %d:%d minute",afktime[playerid]/60,afktime[playerid]-afktime[playerid]/60*60);// cream stringul, impartim timpul la 60 pentru a vedea cate minute sunt, apoi din timp scadem minutele pentru a obtine restul de secunde Update3DTextLabelText(afklabel[playerid], COLOR_WHITE, strings); // actualizam textlabelul pentru a afisa corect timpul decand playerul este afk SetTimerEx("PauseTime", 1000, false, "i", playerid);// apelam iar la aceasta functie pentru a contoriza secundele in continuare } return 1; // oprim functia } Cam atat, labelul se sterge atunci cand playerul revine in joc este in include, nu trebuie sa mai adaugati, este facuta deja Cateva poze pentru a vedea cum arata: http://i.imgur.com/Wsl7CMt.png http://i.imgur.com/hyNG3Ul.png
  17. 7 points
    Hard RolePlay by EquiNoxAdv Sper sa luati in considerare: * GameMode-ul original este South Central RolePlay , eu am lucrat la accest GameMode, sper sa pastrati creditele si macar sa-mi multumiti pentru generozitatea mea. * Emmet_ care m-a sustinut la dezvoltarea acestui GameMode , care mi-a spus de existenta bugurilor si vulnerabilitatilor SQL. Acum GameMode-ul a ajuns la o versiune care este superioara celui de pe net.(South Central RolePlay Original) Sper sa nu va bateti joc de accest GameMode. Am lucrat foarte mult. Aveti comanda /credits. Sper sa o pastrati. Salut , la multi ani 2016 Pentru ca am primit multe PM-uri referitoare la UCP. Si pentru ca l-am dat la vreo 2 persoane si acum se lauda ca l-au facut ei , m-am decis sa va dau si User Control Panel-ul. Va las mai jos si un scurt tutorial ca sa puteti sa-l porniti , sunt sigur ca ii destul de greu Copyright© 2012-2015 EquiNox (All rights reserved / Script Developer). Copyright© 2012-2015 Emmet_ (All rights reserved / Script Developer / Creator GameMode). Caracteristici. Sistemul de armament Unic Inventarul Sistemul Unic Sistemul Unic de droguri Unic Faction Sistem dinamic Sistemul de afaceri dinamic Sistem dinamic de case Sistem Clip Dinamic (GUNS) Sistemul Unic LSPD Cruiser. Unic Metal System Detector Sistemul penitenciar Sistem Foame si Sete . (O pizza si o bere) Cu un singur Nick aveti dreptul la 3 caractere. Sistem Pick-up / Release (Mancare , Arme , Beutura) DealerShip Dialog . Preturi RolePlay (Niciun bug gasit) Rescrise comenzi de Admin / Tester Comenzile (/tduty) si (/adminduty) au fost rescrise. GameMode tradus 70%. Rezolvate vulnerabilitatile SQL. Rezolvat bugul la DealerShip. Rezolvat bugul la Bizz / House. Modificat sistemul de Masini Personale. Adaugat sistem de trunk. Adaugat Radio. Acum jobul Mechanic are un HQ. Unele tabele din DataBase au fost rescrise. Sistemul de /report a fost reparat. Optimizat GameMode pe Linux (Doar Versiunea Linux care este si ea in Arhiva) Cateva culori schimbate. Spawn mutat + Mapping adaugat. Rezolvat bug la Weapon License. Rezolvat care facea ca unii playeri sa primeasca ban. Player-ul nu beneficieaza de RP & Level. Se va adauga 1+ Score la fiecare ora jucata. Sistem Report. Cu Accept / Respinge Report. Joburile sunt unice si functioneaza perfect. GameMode-ul este foarte cautat in Romania. Tutorial pentru pornirea UCP-ului Intrati in folder-ul "inc" si deschide-ti fisierul config.inc.php Modificati urmatoarea linie public static $_PAGE_URL = 'localhost/'; <<< Pui frumos link-ul unde ai pus panel-ul. Daca ii pe xammp lasi localhost/folder/unde/aibagat/panel, iar daca ai host , pui link-ul catre site , ai inteles? Nu este greu , crede-ma. private function __construct() { $db['mysql'] = array( 'host' => 'localhost', <<< Aci , un minim de inteligenta sa il conectati la MySQL , nu? 'username' => 'root', <<< 'password' => 'equinox', <<< 'dbname' => 'rp' <<< ); Apoi , tot in folder-ul "inc" , deschide-ti fisierul settings.inc.php Conectati la MySQL prin urmatoarele linii , de restu nu va atingeti. define('_DB_SERVER_', 'localhost'); define('_DB_NAME_', 'rp'); define('_DB_USER_', 'root'); define('_DB_PASSWD_', 'equinox'); Video : #Download UCP + SERVER: https://mega.nz/#!u7gTkaQR!aoMzJcMcXbaFvecEa6YfQ3sZwnfsuetv-sggNwHKQG0 #VirusScan : https://www.virustotal.com/ro/file/6e50273fff2183993d4ad5a30a2b09a40178eabb465c44990df981dbd1b5eaf5/analysis/1430129408/ Am rezolvat cu link-urile, spor.
  18. 7 points
    PawnPlus - 0.5.2 Beta Informatii PawnPlus este IDE pentru limbajul Pawn, cu mai multe facilitati decat PAWNO. Facilitati Cateva facilitati ale lui PawnPlus sunt: Auto completarea. Verificare de update-uri O interfata placuta. Poti deschide mai multe documente. Imagini Auto completare - Imaginea 1, Imaginea 2. Stilul PawnPlus - Imaginea 1, Imaginea 2, Imaginea 3. Verificare de update-uri - Imaginea 1, Imaginea 2. Descarcari - GitHub - Project Home - GitHub - Versiuni noi Bug-uri - GitHub - Bug-uri
  19. 7 points
    Salut , am revenit sa împărtășească acest sistem cu voi. El cuprinde : Un mini-bar un paznic [ Actori ] doua dansatoare erotice [ Actori ] Pentru inceput ne trebuie INCLUDE "Actor streamer" Click 1. La inceputul gamemodului punem : 2. La OnGameModeInit punem : 3. Adaugam la sfarsit. 4 . Sa facem si comanda O sa revin si cu cateva poze.
  20. 7 points
    Dupa cum stiti acum cateva luni am zis ca m-am apucat sa fac un procesor de comenzi pentru SA:MP. Dar m-am lasat pentru ca nu mai aveam timp de el. Uitati aici codul sursa. Codul este incomplet pentru ca nu am mai continuat. https://github.com/WopsS/wCMD
  21. 7 points
    Hard-Roleplay Version 0.11b Salut SA-MP.Ro . Am revenit si eu in putere. Cred ca multi cunoasteti server-ul Hard-Roleplay. Ei bine astazi din cauza unora care spuneau ca GameMode-ul de pe Hard-RP este unic si toate prostiile , m-am hotarat sa va fac o surpriza. Ca doar ne cunoastem noi , nu? GameMode-ul este la fel ca cel de pe H-RP doar ca nu este tradus . Nu ii mare lucru de tradus la el si gata aveti GM pentru server RolePlay. Imi pare rau ca nu am putut posta si panelul dar inca lucrez la el. O sa vina si el Caracteristici. Sistemul de armament Unic Inventarul Sistemul Unic Sistemul Unic de droguri Unic Faction Sistem dinamic Sistemul de afaceri dinamic Sistem dinamic de case Sistem Clip Dinamic (GUNS) Sistemul Unic LSPD Cruiser. Unic Metal System Detector Sistemul penitenciar Sistem Foame si Sete . (O pizza si o bere) Cu un singur Nick aveti dreptul la 3 caractere. Sistem Pick-up / Release (Mancare , Arme , Beutura) DealerShip Dialog . Preturi RolePlay (Niciun bug gasit) Player-ul nu beneficieaza de RP & Level. Se va adauga 1+ Score la fiecare ora jucata. Sistem Report. Cu Accept / Respinge Report. Joburile sunt unice si functioneaza perfect. GameMode-ul este foarte cautat in Romania. Gata cu descrierea , sa trecem la poze :->~~ :->~~ Poze : http://imgur.com/a/2ekMH (Album 21 Poze) ?@_@? Poze 2xNew Jobs: http://imgur.com/rUUOL5b,mc3KA6t Download Link :http://www.girlshare.ro/34176538| Original GameMode | With Include & Plugins | Download Link #2 : http://www.filehost.ro/31069580/H_RP_rar/| Original GameMode | With Include & Plugins | <<<<>>>>>> Download Link #3 : http://www.girlshare.ro/34190610.3| Update [06.12.2014] Download Link #4 : http://www.filehost.ro/31082373/roleplay_pwn/|Update [06.12.2014] VirusTotal : https://www.virustotal.com/ro/file/4299caa5f8c79ec323372ce9a6d2a5a59b3f83681f238e72f43e9dc792535cd5/analysis/1417558214/ Sper sa va placa. Daca nu va place nu-mi pasa. Multi cred ca isi doreau accest GameMode. Daca va placut nu uitati sa lasati un comentariu si 1+ la profilul meu :X Baza de Date : http://www.girlshare.ro/34176543.5| http://www.filehost.ro/31069585/db_sql/ << Default >> Baza de Date Update : http://www.filehost.ro/31082385/DB_Upate_sql/| Update! Baza de Date Update #2: http://www.girlshare.ro/34190623.5| Update! /-------------------------------------------------------------------------- [uPDATE] 06.12.2014 Adaugate masini Joburi. Adaugate Factiuni Adaugate Masini Factiuni Adaugate Rank-uri Factiuni Adaugate Porti Factiuni Mutate intrarile in Los Santos Create Arrest-Point Tradus Tutorial/Cateva comenzi! Adaugat Job Taxi Driver Adaugat Job Mechanic Puse porti la Pay-N-Spray / Transfender /------------------------------------------------------------------------
  22. 7 points
    Buna ziua stimati membri ai comunitatii SA-MP.RO Astazi, spre atentia dumneavoastra voi prezenta un tutorial al jobului de Programator, pe care recent l-am elaborat. Nu este un job complicat , sper sa fie pe placul dumneavoastra. → Va puteti angaja in calitate de programator in incinta Primariei din Los Santos. → Odata angajat, va veti indrepta spre cabinetul de alaturi , la dulapul (marcat cu un checkpoint) din care veti lua valiza cu accesoriile necesare pentru serviciu. → Dupa ce veti primi toate cele necesare pentru lucru, veti urca la al 2-lea ataj al Primariei, unde se vor afla numeroase calculatoare (random) ce necesita sa fie reparate. → Sarcina dumneavoastra, e sa va apropiati de calculatorul defect (marcat cu un checkpoint), sa introduceti parola Bazei de Date (un cod din cifre random afisat in dialog), pentru a intra in sistemul de operare a acestuia si apoi sa il reparati. → Salariul il veti primi in functie de numarul de calculatoare reparate, la primul etaj, de unde ati primit valiza cu accesorii (in tutorial e 50$ pentru un calculator reparat).
  23. 7 points
    SA-MP 0.3.7 R2 Această actualizare este doar pentru administratorii de servere SA-MP. Adăugată protecţie împotriva hackerilor care spamau mesajele pentru OnPlayerConnect. Verificarea pentru ID-ul armei după OnPlayerWeaponShot în cazul în care serverul n-o făcea. Actorii devin invulnerabili implici (acest lucru ar putea fi necesar mai târziu pentru un fix de rotaţie pentru bandaid în client). Adăugată pentru consolă variabila 'conncookies' (întreg) pentru a dezactiva sistemul de cookie în din versiunea 0.3.7. Adăugată pentru consolă variabila 'cookielogging' pentru a dezactiva log-ul de cookie-uri de conectare solicitate de jucătorii noi care se conectează. Adăugată funcţia SHA256_PassHash() pentru a masca parolele jucatoriilor. Lucruri pentru SQLite: Funcţiile sqlite db_open şi db_query o să returneze acum indicii (începând de la 1) în loc de 'memory handles'. Asta înseamnă că serverul urmăreşte 'memory handles' intern şi nu va mai cauza închiderea acestuia dacă sefoloseşte un 'memory handle' invalid. Câteva funcţii sqlite noi db_* au fost adăugate. Vedeţi a_sampdb.inc pentru o lista a acestora. Adăugat formatorul %q la format(). %q este la fel că %s numai că textul va fi mai întâi trecut prin funcţia de prevenire a SQL injections (strîng escaping function). Adăugată pentru consolă variabila 'db_logging'. Va afişa toate erorile funcţiilor sqlite în server_log. Adăugată pentru consolă variabila 'db_log_queries'. Va afişa toate apelurile functiti db_query() incluzând textul interogării. Sistemul variabilelor serverului (SVars): Sistemul Svars este la fel că PVars, doar că variabilele sunt create pe server, nu sunt ataşate de nici un playerid şi persistă după ce gamemode-ul se schimbă. Funcţiile PAWN destinate citirii variabilelor consolei / config (server.cfg) au fost marcate că învechite datorită conflictului de nume cu sistemul SVar. Aceste funcţii o să mai fie funcţionale ceva timp. Trecând peste este recomandat să redenumiti aceste funcţii cu cele de mai jos: native GetConsoleVarAsString(const varname[], buffer[], len); native GetConsoleVarAsInt(const varname[]); native GetConsoleVarAsBool(const varname[]); SA-MP 0.3.7 R2-1 Adăugate verificări pentru funcţiile de SQLite db_get* în cazul în care valoare este null. Aceste funcţii provocau serverul să dea crash dacă erau specificate rânduri sau nume de coloane invalide. Actualizată funcţia SHA256_PassHash() implementarea sha256 pentru a fixa o problema (padding problem). Rezolvată o problema de indicii cu PVars şi SVars unde *GetUpperIndex trebuia să returneze 1 când toate vars au fost şterse. Descărcări: SA-MP 0.3.7 R2 Linux Server: http://files.sa-mp.com/samp037svr_R2-1.tar.gz SA-MP 0.3.7 R2 Windows Server: http://files.sa-mp.com/samp037_svr_R2-1-1_win32.zip
  24. 7 points
    Problema cu nr 1 nu prea, dar celelalte da. Tot din cauza cretinilor care apar pe zi ce trece, m-am lasat si eu de SAMP. Oricum, degeaba ii facut topicul. Cei cretini nu o sa inteleaga nimic. Romanul e specia care vrea sa aibe el tot.
  25. 6 points
    Salutare, astăzi am decis să incep o serie de tutoriale cu ajutorul cărora sper să învățați puțin PHP, moduri de securizare ale unui site PHP și de ce lucruri esențiale are nevoie un User Control Panel ca să fie folositor pentru jucători cât și pentru staff. Țin să precizez că nu o să pun mare accent pe aspectul site-ului până când nu terminăm crearea întregului panel. După ce terminăm UCP-ul este posibil să mai fac și vreo două tutoriale în care să vă explic și câteva lucruri de bază despre cum ar trebui aranjat un UCP. În acest tutorial o să creăm un User Panel Control care poate fi utilizat la aproape orice server care are o bază de date MySQL. Fișiere și programe necesare: Un program sau un webserver pe care să încărcați fișierele necesare UCP-ului și o bază de date MySQL. (Exemple de programe: wamp, xampp) Un program cu ajutorul căruia puteți edita fișiere PHP, HTML și CSS cu care să fiți obișnuiți și să vă placă să lucrați în el. Partea I a tutorialului: Partea a II-a a tutorialului: Aceasta ar fi prima parte a ghidului, nu o să intru în mai multe detalii în acest tutorial ca să nu vă încurc cu prea multe coduri din prima, o să fie puțin greu să urmați acest tutorial dacă nu aveți cunoștințe în nicio limbă de programare web, dar o să încerc să explic cât mai bine. Download panel: http://www.mediafire.com/download/3ou19n07p5ddu4p/Panel.rar Despre ce o să fie partea a 3-a?: Crearea unui admin panel cu funcții RCON pentru panel-ul nostru.
This leaderboard is set to Bucharest/GMT+03:00
×

Important Information

This site uses cookies. By continuing browsing, you agree to the use of this information. For more details, see Terms of Use and Privacy Policy.