SA-MP 0.3.7 este lansat şi ca de obicei poate fi găsit pe pagina de descărcare.
Noutăţi:
- Peste 500 de obiecte noi adăugate, incluzând obiecte pentru stunt şi obiecte pentru teren.
- Posibilitatea de a schimbă mărimea fontului interfeţei.
- O varietate de caractere noi pentru poliţişti.
- Posibilitatea de a controla uşile şi ferestrele maşinilor.
- Posibilitatea de a adaugă sirene de poliţie pentru maşinile normale.
- Adăugat un sistem static de actori pentru a face mai uşoară creerea NPC-urilor pentru magazine.
- Multe probleme rezolvate şi noi facilităţi de scripting.
Mulţumiri speciale lui Matite şi GamerX pentru contribuţia cu noile obiecte. Mulţumim tuturor celor care au ajutat la testarea versiunii 0.3.7 când a fost în teste!
Sperăm să va bucuraţi de noua versiune.
- 0 comments
- 227.482 views
Începând de astăzi, nu mai acceptăm autentificarea și înregistrarea prin Google și Facebook. Această decizie a fost luată deoarece aceste servicii ne impun cerințe tot mai stricte, inclusiv obligația de a furniza explicații detaliate despre utilizarea aplicației și de a face cereri repetate pentru a continua să folosim aceste metode de autentificare, dintre care multe sunt respinse. Din acest motiv, menținerea acestor servicii active a devenit prea dificilă.
Dacă v-ați autentificat sau înregistrat anterior folosind Google sau Facebook, vă puteți accesa contul utilizând opțiunea "Ați uitat parola?" / "Forgot your password?" pentru a seta o parolă nouă și a continua conectarea prin email.
Dacă aveți nelămuriri sau întâmpinați probleme, ne puteți trimite un mesaj privat pe site mie sau lui @-=[Vyorel]=-.
- 0 comments
- 2.393 views
După cum am spus și vineri am actualizat platforma pe care rulează forumul nostru la o versiune mai modernă. Odată cu actualizarea a trebuit să refacem complet tema site-ului deoarece nu mai erau compatibile. Am decis să păstram aceleași elemente cu câteva modificări.
Tot odată cu acestă actualizare am refăcut și tema întunecată (Dark), puteți să o selectați de la sfârșitul paginii ca în poza următoare.

Dacă aveți sugestii sau întampinați probleme cu una dintre teme (culorile nu se potrivesc, etc.) puteți să îmi dați un mesaj privat sau să lăsați un comentariu mai jos.
Și cu această ocazie am decis să recrutăm noi moderatori, vedeți următorul topic pentru delatii.
În continuare dacă aveți sugestii puteți să îmi dați un mesaj privat sau să lăsați un comentariu mai jos.
- 0 comments
- 8.312 views
-
Activitate
-
0
Crown Pheonyx.ro - crown.pheonyx.ro
Pe data de 11.06.2026, la ora 20:00, deschidem oficial serverul SA:MP Crown Pheonyx! Vă invităm să fiți alături de noi încă de la start și să faceți parte dintr-o comunitate serioasă, stabilă și de lungă durată. Adăugați serverul la Favorite și nu ratați lansarea! Server stabil și administrat cu seriozitate Fără wipe-uri și fără pierderea progresului Bunurile, nivelul, orele jucate și toate datele contului vor fi păstrate permanent Economie și gameplay bazate pe fair-play și legitimitate Proiect de lungă durată, susținut până la închiderea oficială a platformei SA:MP Ne dorim să construim împreună o comunitate frumoasă, unde fiecare jucător să se poată bucura de experiență fără grija că își va pierde progresul acumulat. Mai multe informații, noutăți și detalii despre server găsiți pe Discord. Vă așteptăm la deschidere! Echipa Crown Datele de conectare: IP Server: crown.pheonyx.ro Panel: https://crownpanel.pheonyx.ro/ Discord: https://pheonyx.ro/discord 11.06.2026 | Ora 20:00 -
0
Nex-AC - Anticheat profesional (Instalare + Setare direct din joc)
Nex-AC (Anticheat) este unul dintre cele mai populare anticheat-uri din lumea SAMP-ului. Spre deosebire de alte soluții care necesită pluginuri complexe, Nex-AC rulează direct din script, fiind tradus în peste 20 de limbi (inclusiv română) și având protecții pentru mai bine de 40 de tipuri de hack-uri (FlyHack, SpeedHack, AirBreak, GodMode, MoneyHack etc.). Pasul 1: descărcarea fișierelor Pentru început, ai nevoie de fișierele oficiale Nex-AC. Descarcă pe GitHub "Nex-AC" (by NexiusTailer) și descarcă ultima versiune. Vei avea nevoie de: Fișierul nex-ac.inc (îl pui în folderul scriptului tău: pawno/include/). Folderul nex-ac (care conține fișierele de limbă, inclusiv romanian.lang). Acesta trebuie pus în folderul principal al serverului tău, în scriptfiles/. Structura în scriptfiles ar trebui să arate așa: scriptfiles/nex-ac/romanian.lang Pasul 2: integrarea în Gamemode (GM) Nex-AC folosește o metodă numită "hooking". Ca să funcționeze corect și să nu dea erori de compilare, el trebuie adăugat la începutul scriptului, dar DUPĂ include-ul principal din SA-MP și după cele de MySQL/Streamer dacă le folosești. Deschide gamemode-ul tău și adaugă: #include <a_samp> #include <a_mysql> #include <streamer> // ADĂUGĂ NEX-AC AICI (După include-urile de bază, dar înaintea scriptului tău) #define AC_USE_BUILD_IN_BAN 1 // 1 = folosește sistemul de ban integrat în anticheat, 0 = folosești sistemul tău #include <nex-ac> Pasul 3: configurarea setărilor (OnCheatDetected) Când Nex-AC prinde un codat, el nu îi dă direct kick/ban de la sine fără să te întrebe. El apelează un callback public numit OnCheatDetected. Aici decizi tu ce se întâmplă cu jucătorul (dacă primește Kick, Ban, sau doar alertă pe chat-ul adminilor). Adaugă acest cod undeva în gamemode-ul tău (în afara altor funcții): public OnCheatDetected(playerid, ip_address[], type, code, version, value) { // Verificăm dacă jucătorul este admin. Adminii pot fi imuni la teste/false-uri. // Înlocuiește IsPlayerAdminEx cu funcția ta de admin creată în pașii anteriori! if(IsPlayerAdminEx(playerid)) return 1; new string[256], pName[MAX_PLAYER_NAME]; GetPlayerName(playerid, pName, sizeof(pName)); // 'code' reprezintă ID-ul hack-ului detectat. // Poți face acțiuni personalizate în funcție de gravitate. switch(code) { case 0, 1, 2, 3: // Exemple de coduri pentru FlyHack, AirBreak, SpeedHack { format(string, sizeof(string), "{FF0000}[Anticheat] {FFFFFF}Jucătorul %s[%d] a primit Ban pentru Hack (Cod: %d).", pName, playerid, code); SendClientMessageToAll(0xFF0000FF, string); // Îi dăm ban folosind funcția nativă din Nex-AC BanPlayer(playerid, "Nex-AC: Folosire de Cheat-uri"); } default: // Pentru restul hack-urilor mai puțin grave sau potențiale erori (false-positives) { format(string, sizeof(string), "{FF0000}[Anticheat] {FFFFFF}Jucătorul %s[%d] a primit Kick pentru acțiuni suspecte (Cod: %d).", pName, playerid, code); SendClientMessageToAll(0xFF0000FF, string); KickPlayer(playerid); // Funcție nativă Nex-AC care rezolvă bug-ul de kick din SA-MP } } return 1; } Pasul 4: regula de Aur (Înlocuirea funcțiilor native) Aceasta este cea mai importantă parte a tutorialului. Dacă serverul tău oferă bani, arme sau teleportează jucătorii prin comenzi/sisteme normale, Nex-AC va crede că jucătorul trișează (pentru că vede că jucătorul a primit bani "din senin") și îi va da kick. Pentru a preveni acest lucru, Nex-AC înlocuiește funcțiile native din SA-MP cu versiuni modificate (anticheat-safe). Tu nu trebuie să schimbi nimic în codul tău, Nex-AC face asta automat prin macro-uri, DAR trebuie să fii atent la un detaliu: Dacă în gamemode-ul tău folosești scripturi secundare (Filterscripts), funcțiile de resetare bani sau teleportare executate din filterscript-uri vor fi detectate ca hack de către gamemode-ul principal. Recomandare: evită complet folosirea filterscript-urilor pentru acțiuni ce țin de bani, arme și poziție dacă folosești Nex-AC, sau adaugă #include <nex-ac> și în acele filterscript-uri. Funcțiile pe care Nex-AC le monitorizează automat: GivePlayerMoney / ResetPlayerMoney / GetPlayerMoney GivePlayerWeapon / ResetPlayerWeapons SetPlayerPos / SetVehiclePos SetPlayerHealth / SetPlayerArmour Atâta timp cât modifici banii sau poziția jucătorilor doar prin funcțiile standard de mai sus în GM-ul tău, Nex-AC va ști că este o acțiune legitimă și nu va pedepsi jucătorul. Pasul 5: funcții utile din Nex-AC pe care le poți folosi Nex-AC îți oferă câteva funcții noi (native) foarte utile pe care le poți apela în comenzile tale de admini: EnableAntiCheat(code, bool:enable) Dezactivează sau activează un anumit modul de anticheat în timp real. Exemplu: Dacă vrei să dezactivezi protecția de SpeedHack (cod 2) pe server: EnableAntiCheat(2, false); EnableAntiCheatForPlayer(playerid, code, bool:enable) Oferă imunitate unui anumit jucător la un anumit cod. Util pentru teste de către admini. GetPlayerWeaponID(playerid, slot) Returnează ID-ul armei dintr-un anumit slot, dar securizat prin baza de date Nex-AC, prevenind hack-urile care păcălesc GetPlayerWeapon. Probleme frecvente Jucătorii primesc kick când intră în Tuning Shop sau la Spawn, sistemele vechi de tuning sau spawn teleportează jucătorul rapid de câteva ori. Dacă pățești asta, caută ID-ul codului trimis pe chat și folosește EnableAntiCheat(cod, false); în OnGameModeInit pentru a opri acea protecție specifică care dă erori pe stilul tău de script. Erori la compilare (Symbol already defined): Apare dacă ai pus #include <nex-ac> de două ori sau l-ai pus la sfârșitul scriptului în loc de început. Mută-l imediat sub #include <a_samp>. GESTIONARE DIRECT DIN JOC Structura Tabelului MySQL (SQL) Rulează această comandă SQL în baza ta de date pentru a crea tabelul dedicat stărilor anticheat-ului: CREATE TABLE IF NOT EXISTS `server_anticheat` ( `module_id` int(11) NOT NULL, `module_name` varchar(32) NOT NULL, `is_enabled` tinyint(1) NOT NULL DEFAULT 1, PRIMARY KEY (`module_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; Codul sursă Pawn actualizat cu MySQL R41 Adaugă acest cod în Gamemode-ul tău. Acesta va citi setările din baza de date la pornire și le va actualiza în timp real când le modifici din meniul /acpanel. #include <a_samp> #include <pawncmd> #include <sscanf2> #include <a_mysql> // ---- Configurații Dialoguri ---- #define DIALOG_AC_MAIN (8871) #define DIALOG_AC_MODULES (8872) #define DIALOG_AC_IMMUNITY (8873) // Folosește handler-ul tău global de MySQL dacă ai deja unul (ex: SQL, handle, etc.) extern MySQL:SQL_Handle; enum E_AC_MODULE_INFO { acCode, acName[32] } new const AC_Modules[][E_AC_MODULE_INFO] = { {0, "AirBreak (Pe jos)"}, {1, "AirBreak (În vehicul)"}, {2, "FlyHack (Pe jos)"}, {3, "FlyHack (În vehicul)"}, {4, "SpeedHack (Pe jos)"}, {5, "SpeedHack (În vehicul)"}, {11, "Teleport (Pe jos)"}, {12, "Teleport (În vehicul)"}, {16, "Weapon Hack (Arme)"}, {17, "Infinite Ammo (Muniție)"}, {18, "Money Hack (Bani)"}, {22, "Health Hack (HP)"}, {23, "Armour Hack (Armură)"}, {24, "GodMode (Pe jos)"}, {28, "CarJack Hack"}, {32, "Rapid Fire (Trb. Rapid)"}, {40, "Car Health Hack (Tuning)"} }; // Forward-uri noi pentru MySQL forward OnAnticheatSettingsLoad(); public OnGameModeInit() { // Trimitem o interogare pentru a încărca starea modulelor salvate print("[MySQL] Se încarcă setările personalizate pentru Nex-AC..."); mysql_tquery(SQL_Handle, "SELECT * FROM `server_anticheat`", "OnAnticheatSettingsLoad"); return 1; } // ---- Încărcarea Setărilor din Baza de Date ---- public OnAnticheatSettingsLoad() { new rows = cache_num_rows(); // Dacă baza de date este goală (prima pornire a serverului), o populăm cu valorile implicite (toate pornite) if(rows == 0) { print("[MySQL] Tabelul anticheat este gol. Se populează cu modulele implicite..."); new query[256]; for(new i = 0; i < sizeof(AC_Modules); i++) { mysql_format(SQL_Handle, query, sizeof(query), "INSERT INTO `server_anticheat` (`module_id`, `module_name`, `is_enabled`) VALUES ('%d', '%e', '1') ON DUPLICATE KEY UPDATE `is_enabled`='1'", AC_Modules[i][acCode], AC_Modules[i][acName] ); mysql_tquery(SQL_Handle, query); // Le lăsăm pornite nativ în Nex-AC EnableAntiCheat(AC_Modules[i][acCode], true); } return 1; } // Dacă există deja salvări în baza de date, le aplicăm pe server new m_id, is_enabled; for(new i = 0; i < rows; i++) { cache_get_value_name_int(i, "module_id", m_id); cache_get_value_name_int(i, "is_enabled", is_enabled); // Aplicăm starea încărcată (0 = oprit, 1 = pornit) în Nex-AC EnableAntiCheat(m_id, (is_enabled == 1) ? true : false); } printf("[MySQL] S-au aplicat cu succes %d setări de module pentru Nex-AC.", rows); return 1; } // ---- Funcție ajutătoare pentru salvare rapidă ---- stock SaveAnticheatModuleStatus(module_id, bool:status) { new query[128]; mysql_format(SQL_Handle, query, sizeof(query), "UPDATE `server_anticheat` SET `is_enabled` = '%d' WHERE `module_id` = '%d'", (status == true) ? 1 : 0, module_id ); mysql_tquery(SQL_Handle, query); } // ---- Comanda de Admin ---- cmd:acpanel(playerid, params[]) { if(!IsPlayerAdminEx(playerid)) return SendClientMessage(playerid, 0xFF0000FF, "Nu ai permisiunea de a folosi această comandă."); ShowPlayerDialog(playerid, DIALOG_AC_MAIN, DIALOG_STYLE_LIST, "{FF0000}Nex-AC {FFFFFF}- Panou MySQL Profesional", "1. Gestionare Module Anticheat (Salvare Persistentă)\n2. Oferă Imunitate unui Jucător (Până la relog)\n3. Stare Anticheat (Sumar)", "Selectează", "Închide" ); return 1; } alias:acpanel("ac"); // ---- Răspunsurile Dialogurilor ---- public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[]) { if(dialogid == DIALOG_AC_MAIN) { if(!response) return 1; switch(listitem) { case 0: // Afișare module { new dialogStr[1024], lineStr[128]; format(dialogStr, sizeof(dialogStr), "Modul Anticheat\tStare Curentă (MySQL)\n"); for(new i = 0; i < sizeof(AC_Modules); i++) { new bool:status = bool:GetAntiCheatStatus(AC_Modules[i][acCode]); format(lineStr, sizeof(lineStr), "%s\t%s\n", AC_Modules[i][acName], status ? "{00FF00}ACTIVAT" : "{FF0000}DEZACTIVAT" ); strcat(dialogStr, lineStr); } ShowPlayerDialog(playerid, DIALOG_AC_MODULES, DIALOG_STYLE_TABLIST_HEADERS, "{FF0000}Nex-AC {FFFFFF}- Configurare Persistentă", dialogStr, "Comută", "Înapoi" ); } case 1: // Imunitate temporară jucător { ShowPlayerDialog(playerid, DIALOG_AC_IMMUNITY, DIALOG_STYLE_INPUT, "{FF0000}Nex-AC {FFFFFF}- Imunitate Jucător", "Introdu ID-ul sau numele jucătorului:", "Oferă", "Înapoi" ); } case 2: // Status { new statsStr[256]; format(statsStr, sizeof(statsStr), "{FFFFFF}Versiune Nex-AC: {FFFF00}%s\n{FFFFFF}Stocare: {00FF00}Bază de date MySQL{FFFFFF}\n{FFFFFF}Module înregistrate: {FFFF00}%d", AC_VERSION, sizeof(AC_Modules) ); ShowPlayerDialog(playerid, 9999, DIALOG_STYLE_MSGBOX, "{FF0000}Nex-AC {FFFFFF}- Status", statsStr, "Ok", ""); } } return 1; } if(dialogid == DIALOG_AC_MODULES) { if(!response) return PC_ExecuteCommand(playerid, "/acpanel"); new code = AC_Modules[listitem][acCode]; new bool:newStatus = !bool:GetAntiCheatStatus(code); // Inversăm starea actuală // 1. Schimbăm starea în mod activ în memoria serverului EnableAntiCheat(code, newStatus); // 2. Trimitem modificarea direct în baza de date MySQL (Salvare persistentă) SaveAnticheatModuleStatus(code, newStatus); // Notificare admini new logStr[128], adminName[MAX_PLAYER_NAME]; GetPlayerName(playerid, adminName, sizeof(adminName)); format(logStr, sizeof(logStr), "{FF0000}[Anticheat] %s a %s modulul '%s' (Salvat în DB).", adminName, newStatus ? "{00FF00}ACTIVAT" : "{FF0000}DEZACTIVAT", AC_Modules[listitem][acName] ); for(new i = 0; i < MAX_PLAYERS; i++) { if(IsPlayerConnected(i) && IsPlayerAdminEx(i)) SendClientMessage(i, 0x33CCFFFF, logStr); } // Redeschidem meniul actualizat PC_ExecuteCommand(playerid, "/acpanel"); return 1; } if(dialogid == DIALOG_AC_IMMUNITY) { if(!response) return PC_ExecuteCommand(playerid, "/acpanel"); new targetid; if(sscanf(inputtext, "u", targetid) || !IsPlayerConnected(targetid)) { SendClientMessage(playerid, 0xFF0000FF, "Eroare: Jucător offline sau invalid."); return PC_ExecuteCommand(playerid, "/acpanel"); } for(new i = 0; i < sizeof(AC_Modules); i++) { EnableAntiCheatForPlayer(targetid, AC_Modules[i][acCode], false); } new tName[MAX_PLAYER_NAME], msg[128]; GetPlayerName(targetid, tName, sizeof(tName)); format(msg, sizeof(msg), "{00FF00}[Anticheat] I-ai oferit imunitate temporară lui %s[%d].", tName, targetid); SendClientMessage(playerid, 0x00FF00FF, msg); return 1; } return 0; }- 1
-
-
0
Sistem de report avansat
Dependențe necesare: Pawn.CMD MySQL R-41 sscanf2 Structura tabelului MySQL (SQL) CREATE TABLE IF NOT EXISTS `server_reports` ( `id` int(11) NOT NULL AUTO_INCREMENT, `sender_name` varchar(24) NOT NULL, `reason` varchar(128) NOT NULL, `date_added` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; Codul sursă pawn #include <a_samp> #include <pawncmd> #include <sscanf2> #include <a_mysql> // Include pluginul MySQL R41+ // ---- Configurații ---- #define MAX_REPORTS (50) #define DIALOG_REPORT_MAIN (9981) #define DIALOG_REPORT_TEXT (9982) #define DIALOG_REP_LIST (9983) #define REASON_LENGTH (128) #define COLOR_RED 0xFF0000FF #define COLOR_GREEN 0x00FF00FF #define COLOR_YELLOW 0xFFFF00FF #define COLOR_WHITE 0xFFFFFFFF #define COLOR_LIGHTBLUE 0x33CCFFFF // Înlocuiește "MySQL_Handle" cu variabila ta de conexiune MySQL dacă ai una existentă în GM new MySQL:SQL_Handle; // ---- Structuri de date ---- enum E_REPORT_DATA { repDatabaseID, // ID-ul unic din baza de date (MySQL Auto_Increment) repSenderID, // ID-ul jucătorului pe server (-1 dacă e offline dar raportul e încă în coadă) repSenderName[MAX_PLAYER_NAME], // Numele jucătorului (salvat pentru când e offline) repReason[REASON_LENGTH], bool:repActive } new ReportQueue[MAX_REPORTS][E_REPORT_DATA]; new TotalReports = 0; new bool:HasActiveReport[MAX_PLAYERS]; new PlayerUnderReport[MAX_PLAYERS]; // ---- Verificare Admin ---- stock IsPlayerAdminEx(playerid) { if(IsPlayerAdmin(playerid)) return 1; // Înlocuiește linia de mai jos cu variabila ta de admin (ex: if(PlayerInfo[playerid][pAdmin] >= 1) return 1;) return 0; } // ---- Forward-uri pentru MySQL ---- forward OnUnansweredReportsLoad(); forward OnReportInserted(queue_index, playerid); public OnGameModeInit() { // Inițializare coadă golită pe server for(new i = 0; i < MAX_REPORTS; i++) { ResetReportSlot(i); } // ATENȚIE: Dacă ai deja logica de conectare MySQL în GM, șterge liniile mysql_connect de mai jos! SQL_Handle = mysql_connect("127.0.0.1", "root", "", "server_db"); if(mysql_errno(SQL_Handle) != 0) { printf("[MySQL] Conexiunea a eșuat în sistemul de reporturi."); } else { printf("[MySQL] Conexiune reușită. Încărcăm rapoartele nerezolvate..."); // Încărcăm rapoartele nerezolvate salvate în baza de date mysql_tquery(SQL_Handle, "SELECT * FROM `server_reports` ORDER BY `id` ASC LIMIT 50", "OnUnansweredReportsLoad"); } return 1; } public OnPlayerConnect(playerid) { HasActiveReport[playerid] = false; PlayerUnderReport[playerid] = INVALID_PLAYER_ID; // Verificăm dacă jucătorul care s-a conectat are un raport rămas în coadă din sesiunea trecută new pName[MAX_PLAYER_NAME]; GetPlayerName(playerid, pName, sizeof(pName)); for(new i = 0; i < MAX_REPORTS; i++) { if(ReportQueue[i][repActive] && !strcmp(ReportQueue[i][repSenderName], pName, true)) { ReportQueue[i][repSenderID] = playerid; // Îi reasociem ID-ul curent de server HasActiveReport[playerid] = true; new str[128]; format(str, sizeof(str), "{FFFFFF}[REPORT] Raportul tău din sesiunea anterioară este încă în coadă pe poziția {FFFF00}%d{FFFFFF}.", i + 1); SendClientMessage(playerid, COLOR_GREEN, str); break; } } return 1; } public OnPlayerDisconnect(playerid, reason) { // Când un jucător iese, NU mai ștergem raportul din baza de date și nici din coadă! // Doar marcăm ID-ul ca invalid pe server, dar adminii îl vor vedea în continuare în listă după nume. if(HasActiveReport[playerid]) { for(new i = 0; i < MAX_REPORTS; i++) { if(ReportQueue[i][repActive] && ReportQueue[i][repSenderID] == playerid) { ReportQueue[i][repSenderID] = INVALID_PLAYER_ID; break; } } } if(PlayerUnderReport[playerid] != INVALID_PLAYER_ID) { new target = PlayerUnderReport[playerid]; if(IsPlayerConnected(target)) { SendClientMessage(target, COLOR_RED, "Adminul care iți procesa raportul s-a deconectat."); } PlayerUnderReport[playerid] = INVALID_PLAYER_ID; } return 1; } // ---- Funcții Ajutătoare (Helperi) ---- stock ResetReportSlot(i) { ReportQueue[i][repDatabaseID] = 0; ReportQueue[i][repSenderID] = INVALID_PLAYER_ID; ReportQueue[i][repSenderName][0] = '\0'; ReportQueue[i][repReason][0] = '\0'; ReportQueue[i][repActive] = false; } stock MessageToAdmins(color, const message[]) { for(new i = 0; i < MAX_PLAYERS; i++) { if(IsPlayerConnected(i) && IsPlayerAdminEx(i)) { SendClientMessage(i, color, message); } } } // ---- Logica MySQL R41 ---- public OnUnansweredReportsLoad() { new rows = cache_num_rows(); if(rows == 0) return printf("[MySQL] Nu s-au găsit rapoarte nerezolvate în baza de date."); TotalReports = 0; for(new i = 0; i < rows && i < MAX_REPORTS; i++) { ReportQueue[i][repActive] = true; cache_get_value_name_int(i, "id", ReportQueue[i][repDatabaseID]); cache_get_value_name(i, "sender_name", ReportQueue[i][repSenderName], MAX_PLAYER_NAME); cache_get_value_name(i, "reason", ReportQueue[i][repReason], REASON_LENGTH); ReportQueue[i][repSenderID] = INVALID_PLAYER_ID; // Va deveni valid dacă jucătorul se conectează TotalReports++; } printf("[MySQL] S-au încărcat cu succes %d rapoarte nerezolvate în coadă.", TotalReports); return 1; } stock SendReportToQueue(playerid, const reason[]) { if(TotalReports >= MAX_REPORTS) { return SendClientMessage(playerid, COLOR_RED, "Coada de rapoarte este plină! Încearcă din nou mai târziu."); } // Găsim primul slot liber local pe server for(new i = 0; i < MAX_REPORTS; i++) { if(!ReportQueue[i][repActive]) { ReportQueue[i][repActive] = true; ReportQueue[i][repSenderID] = playerid; GetPlayerName(playerid, ReportQueue[i][repSenderName], MAX_PLAYER_NAME); format(ReportQueue[i][repReason], REASON_LENGTH, "%s", reason); TotalReports++; HasActiveReport[playerid] = true; // Salvare threaded în MySQL R41 new query[256]; mysql_format(SQL_Handle, query, sizeof(query), "INSERT INTO `server_reports` (`sender_name`, `reason`) VALUES ('%e', '%e')", ReportQueue[i][repSenderName], reason); mysql_tquery(SQL_Handle, query, "OnReportInserted", "dd", i, playerid); return 1; } } return 0; } public OnReportInserted(queue_index, playerid) { // Salvăm ID-ul generat de baza de date (Primary Key) direct în slotul aferent din coadă ReportQueue[queue_index][repDatabaseID] = mysql_insert_id(SQL_Handle); if(IsPlayerConnected(playerid)) { new str[128]; format(str, sizeof(str), "{FFFFFF}[REPORT] Raportul tău a fost salvat! Poziția în coadă: {FFFF00}%d{FFFFFF}.", TotalReports); SendClientMessage(playerid, COLOR_GREEN, str); new name[MAX_PLAYER_NAME]; GetPlayerName(playerid, name, sizeof(name)); format(str, sizeof(str), "{33CCFF}[Report nou] (%d) %s[%d]: %s", TotalReports, name, playerid, ReportQueue[queue_index][repReason]); MessageToAdmins(COLOR_LIGHTBLUE, str); } return 1; } stock DeleteReportFromDatabase(db_id) { if(db_id == 0) return 0; new query[128]; mysql_format(SQL_Handle, query, sizeof(query), "DELETE FROM `server_reports` WHERE `id` = '%d'", db_id); mysql_tquery(SQL_Handle, query); return 1; } stock RemoveReportFromQueue(queue_index) { if(!ReportQueue[queue_index][repActive]) return 0; // Ștergem din baza de date DeleteReportFromDatabase(ReportQueue[queue_index][repDatabaseID]); // Resetăm variabila per jucător dacă este online new target = ReportQueue[queue_index][repSenderID]; if(target != INVALID_PLAYER_ID && IsPlayerConnected(target)) { HasActiveReport[target] = false; } // Resetăm slotul și rearanjăm coada (FIFO) ResetReportSlot(queue_index); TotalReports--; ReorderQueue(); return 1; } stock ReorderQueue() { new tempQueue[MAX_REPORTS][E_REPORT_DATA]; new count = 0; for(new i = 0; i < MAX_REPORTS; i++) { if(ReportQueue[i][repActive]) { tempQueue[count] = ReportQueue[i]; count++; } } for(new i = 0; i < MAX_REPORTS; i++) { if(i < count) { ReportQueue[i] = tempQueue[i]; } else { ResetReportSlot(i); } } TotalReports = count; } // ---- Comenzi Jucători (Pawn.CMD) ---- cmd:report(playerid, params[]) { if(HasActiveReport[playerid]) { return SendClientMessage(playerid, COLOR_RED, "Eroare: Ai deja un raport activ în coadă. Te rugăm să aștepți."); } ShowPlayerDialog(playerid, DIALOG_REPORT_MAIN, DIALOG_STYLE_LIST, "{FFFFFF}Sistem de Raportare", "1. Raportează un Codat / Hacker\n2. Raportează limbaj / jigniri\n3. Am blocat / Am nevoie de ajutor (Unstuck)\n4. Altă problemă (Scrie text manual)", "Selectează", "Închide" ); return 1; } alias:report("rep"); // ---- Comenzi Administratori (Pawn.CMD) ---- cmd:ar(playerid, params[]) { if(!IsPlayerAdminEx(playerid)) return SendClientMessage(playerid, COLOR_RED, "Nu ai permisiunea de a folosi această comandă."); if(PlayerUnderReport[playerid] != INVALID_PLAYER_ID) return SendClientMessage(playerid, COLOR_RED, "Eroare: Procesezi deja un raport! Folosește /cr pentru a-l închide."); if(TotalReports == 0) return SendClientMessage(playerid, COLOR_RED, "Nu există rapoarte active în coadă în acest moment."); new queueIndex = 0; new inputIndex; if(!sscanf(params, "d", inputIndex)) { inputIndex = inputIndex - 1; if(inputIndex >= 0 && inputIndex < TotalReports && ReportQueue[inputIndex][repActive]) { queueIndex = inputIndex; } else { return SendClientMessage(playerid, COLOR_RED, "Poziție invalidă în coadă. Folosește /reports pentru listă."); } } new targetid = ReportQueue[queueIndex][repSenderID]; new reason[REASON_LENGTH]; format(reason, sizeof(reason), "%s", ReportQueue[queueIndex][repReason]); new adminName[MAX_PLAYER_NAME], str[256]; GetPlayerName(playerid, adminName, sizeof(adminName)); // Verificăm dacă jucătorul mai este pe server if(targetid == INVALID_PLAYER_ID || !IsPlayerConnected(targetid)) { format(str, sizeof(str), "{FFFFFF}Ai preluat raportul lui {FFFF00}%s{FFFFFF} (offline). Motiv: %s.", ReportQueue[queueIndex][repSenderName], reason); SendClientMessage(playerid, COLOR_GREEN, str); format(str, sizeof(str), "{33CCFF}[Admin] %s a eliminat raportul de la offline al lui %s. Motiv: %s", adminName, ReportQueue[queueIndex][repSenderName], reason); MessageToAdmins(COLOR_LIGHTBLUE, str); // Din moment ce este offline, doar curățăm raportul din listă/bază de date direct RemoveReportFromQueue(queueIndex); return 1; } // Jucătorul este online, începem conversația asistată PlayerUnderReport[playerid] = targetid; format(str, sizeof(str), "{FFFFFF}[REPORT] Adminul {FFFF00}%s{FFFFFF} ți-a acceptat raportul. Acesta va discuta cu tine acum.", adminName); SendClientMessage(targetid, COLOR_GREEN, str); format(str, sizeof(str), "{33CCFF}[Admin] %s a preluat raportul lui %s[%d]. Motiv: %s", adminName, ReportQueue[queueIndex][repSenderName], targetid, reason); MessageToAdmins(COLOR_LIGHTBLUE, str); format(str, sizeof(str), "{FFFFFF}Ai preluat raportul lui %s. Motiv: %s. Folosește /cr când ai terminat.", ReportQueue[queueIndex][repSenderName], reason); SendClientMessage(playerid, COLOR_GREEN, str); // Îl eliminăm din MySQL și din coada de așteptare deoarece un admin se ocupă acum de el RemoveReportFromQueue(queueIndex); return 1; } cmd:cr(playerid, params[]) { if(!IsPlayerAdminEx(playerid)) return SendClientMessage(playerid, COLOR_RED, "Nu ai permisiunea de a folosi această comandă."); if(PlayerUnderReport[playerid] == INVALID_PLAYER_ID) return SendClientMessage(playerid, COLOR_RED, "Nu ai niciun raport activ în desfășurare."); new targetid = PlayerUnderReport[playerid]; new adminName[MAX_PLAYER_NAME], userName[MAX_PLAYER_NAME], str[128]; GetPlayerName(playerid, adminName, sizeof(adminName)); if(IsPlayerConnected(targetid)) { GetPlayerName(targetid, userName, sizeof(userName)); format(str, sizeof(str), "{FFFFFF}[REPORT] Adminul {FFFF00}%s{FFFFFF} ți-a închis raportul. Sperăm că te-am ajutat!", adminName); SendClientMessage(targetid, COLOR_YELLOW, str); format(str, sizeof(str), "{FFFFFF}Ai închis cu succes raportul lui %s.", userName); SendClientMessage(playerid, COLOR_GREEN, str); } else { SendClientMessage(playerid, COLOR_GREEN, "Ai închis raportul curent (jucătorul era deconectat)."); } PlayerUnderReport[playerid] = INVALID_PLAYER_ID; return 1; } cmd:reports(playerid, params[]) { if(!IsPlayerAdminEx(playerid)) return SendClientMessage(playerid, COLOR_RED, "Nu ai permisiunea de a folosi această comandă."); if(TotalReports == 0) return SendClientMessage(playerid, COLOR_RED, "Nu există rapoarte active în coadă."); new dialogStr[1024], lineStr[150]; format(dialogStr, sizeof(dialogStr), "Poziție\tJucător\tStare\tMotiv\n"); for(new i = 0; i < MAX_REPORTS; i++) { if(ReportQueue[i][repActive]) { if(ReportQueue[i][repSenderID] != INVALID_PLAYER_ID && IsPlayerConnected(ReportQueue[i][repSenderID])) { format(lineStr, sizeof(lineStr), "#%d\t%s (%d)\t{00FF00}Online{FFFFFF}\t%s\n", i+1, ReportQueue[i][repSenderName], ReportQueue[i][repSenderID], ReportQueue[i][repReason]); } else { format(lineStr, sizeof(lineStr), "#%d\t%s\t{FF0000}Offline{FFFFFF}\t%s\n", i+1, ReportQueue[i][repSenderName], ReportQueue[i][repReason]); } strcat(dialogStr, lineStr); } } ShowPlayerDialog(playerid, DIALOG_REP_LIST, DIALOG_STYLE_TABLIST_HEADERS, "{FFFFFF}Listă Coadă Rapoarte (MySQL)", dialogStr, "Acceptă primul", "Închide"); return 1; } // ---- Dialoguri ---- public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[]) { if(dialogid == DIALOG_REPORT_MAIN) { if(!response) return 1; switch(listitem) { case 0: SendReportToQueue(playerid, "Posibil codat / hacker (necesită spectate)"); case 1: SendReportToQueue(playerid, "Limbaj vulgar / Jigniri / Spam"); case 2: SendReportToQueue(playerid, "Am rămas blocat (solicit unstuck / flip)"); case 3: { ShowPlayerDialog(playerid, DIALOG_REPORT_TEXT, DIALOG_STYLE_INPUT, "{FFFFFF}Raport - Detalii manuale", "Te rugăm să descrii problema ta cât mai detaliat posibil în căsuța de mai jos:", "Trimite", "Înapoi" ); } } return 1; } if(dialogid == DIALOG_REPORT_TEXT) { if(!response) return PC_ExecuteCommand(playerid, "/report"); if(strlen(inputtext) < 5 || strlen(inputtext) > 120) { SendClientMessage(playerid, COLOR_RED, "Eroare: Textul raportului trebuie să aibă între 5 și 120 de caractere."); return PC_ExecuteCommand(playerid, "/report"); } SendReportToQueue(playerid, inputtext); return 1; } if(dialogid == DIALOG_REP_LIST) { if(response) { PC_ExecuteCommand(playerid, "/ar"); } return 1; } return 0; }- 1
-
-
1
Caut scripter in pwn/vision contra cost
daca mai este valabil, adauga-ma def_19 -
1
Caut scripter in pwn/vision contra cost
atentie vreau sa imi pune ti cateva proiecte de ale voastre doar poze nu ma intereseaza scriptul in sine , plus daca aveti ceva recenzi bune de la alti clienti ar fi mai bine platim pe ora/sistem depinde cum lucrezi si de experienta ta in acest domeniu, ma puteti contacta pe mine sau pe Jaker pe urmatoarele discorduri baton9580 sau pe discord pandarazvan
-
-
-
Sponsor
