-
Posts
667 -
Joined
-
Last visited
-
Days Won
55
khain.dev last won the day on June 14
khain.dev had the most liked content!
About khain.dev
- Birthday 19.01.2000
Profile Information
-
Sex
Masculin
-
Interests
Programming
-
In-game Name
khain.dev
-
Level of knowledge
Experimentat
Contact Methods
-
Discord
Mo_Garcia#3221
- Website URL
khain.dev's Achievements
-
// Definim variabilele global pentru a le putea accesa peste tot new QuestVehicle[3]; new QuestIcon[3]; public OnGameModeInit() { // Creăm cele 3 mașini de quest QuestVehicle[0] = CreateVehicle(411, 1000.0, -1000.0, 10.0, 0.0, -1, -1, 60000); // Exemplu Infernus QuestVehicle[1] = CreateVehicle(411, 1020.0, -1000.0, 10.0, 0.0, -1, -1, 60000); QuestVehicle[2] = CreateVehicle(411, 1040.0, -1000.0, 10.0, 0.0, -1, -1, 60000); // Creăm iconițele pe poziția inițială a mașinilor // Parametri: X, Y, Z, tip_iconiță (ex: 55 pentru mașină/quest), culoare, worldid, interiorid, playerid, streamdistance QuestIcon[0] = CreateDynamicMapIcon(1000.0, -1000.0, 10.0, 55, 0, -1, -1, -1, 6000.0); QuestIcon[1] = CreateDynamicMapIcon(1020.0, -1000.0, 10.0, 55, 0, -1, -1, -1, 6000.0); QuestIcon[2] = CreateDynamicMapIcon(1040.0, -1000.0, 10.0, 55, 0, -1, -1, -1, 6000.0); // Pornim un timer care să updateze poziția iconițelor după mașini (la fiecare secundă) SetTimer("UpdateQuestIcons", 1000, true); return 1; } // Forward pentru timer forward UpdateQuestIcons(); public UpdateQuestIcons() { new Float:x, Float:y, Float:z; for(new i = 0; i < 3; i++) { // Luăm poziția curentă a mașinii (în caz că se mișcă) GetVehiclePos(QuestVehicle[i], x, y, z); // Update la poziția iconiței dinamice Streamer_SetFloatData(STREAMER_TYPE_MAP_ICON, QuestIcon[i], E_STREAMER_X, x); Streamer_SetFloatData(STREAMER_TYPE_MAP_ICON, QuestIcon[i], E_STREAMER_Y, y); Streamer_SetFloatData(STREAMER_TYPE_MAP_ICON, QuestIcon[i], E_STREAMER_Z, z); } return 1; } Daca vrei cu ID de player new QuestVehicle[2]; public OnGameModeInit() { QuestVehicle[0] = CreateVehicle(411, 1000.0, -1000.0, 10.0, 0.0, -1, -1, 60000); QuestVehicle[1] = CreateVehicle(411, 1020.0, -1000.0, 10.0, 0.0, -1, -1, 60000); SetTimer("UpdateNativeIcons", 1000, true); return 1; } forward UpdateNativeIcons(); public UpdateNativeIcons() { new Float:x, Float:y, Float:z; // Trecem prin toți jucătorii online for(new i = 0; i < MAX_PLAYERS; i++) { if(IsPlayerConnected(i)) { // Pentru mașina 1 (folosim slotul de iconiță 10) GetVehiclePos(QuestVehicle[0], x, y, z); SetPlayerMapIcon(i, 10, x, y, z, 55, 0, MAPICON_GLOBAL); // Pentru mașina 2 (folosim slotul de iconiță 11) GetVehiclePos(QuestVehicle[1], x, y, z); SetPlayerMapIcon(i, 11, x, y, z, 55, 0, MAPICON_GLOBAL); } } return 1; }
-
sa:mp LAUNCHER & custom register/login showcase
khain.dev replied to Waller.'s topic in Imagini şi Videoclipuri
Nu cred ca ai scris tu launcherul de la 0, cu Cursor/Claude toti sunt buni la toate, nu e nimic gresit, important sa stii sa il folosesti corect, in rest bravo. -
sa:mp LAUNCHER & custom register/login showcase
khain.dev replied to Waller.'s topic in Imagini şi Videoclipuri
Noroc de AI, in rest bravo -
Referitor la sidenote: ma bucur ca te informezi cu AI-ul despre Rusia, totusi, tin sa te anunt ca serverele rusesti cu launcherele pe care le dezvolta solicita resurse bune la PC-ul tau, in esenta SAMP-ul va exista mult timp, bine SAMP e mult spus, serverele de SAMP, sunt jucatori amatori si sunt jucatori cu statut social mai scazut, dar chiar si cei cu statutul social mai scazut au PC-uri care usor se pot juca in GTA 5, ei continuu joaca SAMP mai degraba din placere. Ce tine de GTA 5, o sa mosteneasca istoria SAMP-ului, o sa treaca ani buni pana ce GTA 5 nu va mai fi la moda, multi din GTA SA aka SAMP vor tranzitiona in GTA 5, multi bani se fac cu GTA 5 si se va face in continuare, asta spun cifrele la detinatorii de servere GTA 5, milioane de dolari, miliarde de ruble (Majestic RP). Cat despre GTA 6, cu siguranta Rockstar o sa ofere multiplayer prin abonament, alternative cum spui cracked vor fi blochate prin judecata, cum intalnim in povestea lui Rage MP. Iarasi sa joci SAMP e una, si sa deschizi server SAMP visand la stele verzi e alta situatie. Sa investesti in GTA 5 chiar si acum este de perspectiva minim de 20 ani sigur. Sa astepti GTA 6 + timp pentru a dezvolta un server e de perspectiva majora dar si complicat in acelasi timp.
-
SAMP-ul e mort. Serverele mari românești mai rezistă cu un scârțâit profund, iar să începi să creezi ceva în 2026 pe SAMP este extrem de ridicol – o pierdere de timp, bani și nervi. Vorbind la nivel global, încă există servere populare, dar rușii mențin cel mai mult acest online datorită launcherelor dezvoltate de fiecare proiect în parte, care practic modifică jocul așa cum vor ei. Mulți încearcă open.mp, dar nici acolo nu e un online strălucit; respectiv, proiectul plutește cum poate. GTA 5 este de perspectivă dacă vrei să creezi ceva sau, dacă vrei să fii băiat deștept, aștepți GTA 6 Multiplayer. Faci un server acolo și perspectiva crește substanțial. SAMP rămâne o istorie memorată și susținută de amatori. La nivel economic, este o pierdere de bani dacă vrei să deschizi ceva acum.
-
Ce a vrut sa zică autorul
-
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
-
-
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
-
-
khain.dev changed their profile photo
-
Caut scripter in pwn/vision contra cost
khain.dev replied to IoNuT OaNa's topic in Caut servicii / partener / etc.
daca mai este valabil, adauga-ma def_19- 1 reply
-
- 1
-
-
enum e_RadarData { bool:rOn, rLimit, rAreaId } new RadarData[MAX_PLAYERS][e_RadarData]; new Iterator:RadarsOn<MAX_PLAYERS>; #define RADAR_STREAMER_IDENTIFIER 999 public OnGameModeExit() { foreach(new i : RadarsOn) { ResetPlayerRadar(i); } Iter_Clear(RadarsOn); return 1; } public OnPlayerDisconnect(playerid, reason) { if(RadarData[playerid][rOn]) { ResetPlayerRadar(playerid); } return 1; } public OnPlayerDeath(playerid, killerid, reason) { if(RadarData[playerid][rOn]) { ResetPlayerRadar(playerid); SendClientMessage(playerid, COLOR_GREY, "Radarul a fost oprit deoarece ai murit."); } return 1; } stock ResetPlayerRadar(playerid) { if(IsValidDynamicArea(RadarData[playerid][rAreaId])) { DestroyDynamicArea(RadarData[playerid][rAreaId]); } RadarData[playerid][rOn] = false; RadarData[playerid][rLimit] = 0; RadarData[playerid][rAreaId] = INVALID_STREAMER_ID; Iter_Remove(RadarsOn, playerid); TogglePlayerControllable(playerid, 1); return 1; } CMD:startradar(playerid, params[]) { if(!IsACop(playerid)) return SendClientMessage(playerid, COLOR_GREY, "Nu faci parte din departament."); if(OnDuty[playerid] != 1) return SendClientMessage(playerid, COLOR_LGREEN, "Eroare: Nu esti la datorie!"); new vehicleid = GetPlayerVehicleID(playerid); if(!Copcar2(vehicleid)) return SendClientMessage(playerid, COLOR_GREY, "Nu esti intr-o masina a factiunii."); if(RadarData[playerid][rOn]) return SendClientMessage(playerid, -1, "Ai deja activat radaru."); new viteza; if(sscanf(params, "d", viteza)) return SendClientMessage(playerid, COLOR_GREY, "USAGE: {FFFFFF}/startradar <Speed Limit>"); if(viteza > 200 || viteza < 40) return SendClientMessage(playerid, -1, "Viteza invalida (40-200)."); new Float:cX, Float:cY, Float:cZ, Float:cAngle; GetVehiclePos(vehicleid, cX, cY, cZ); GetVehicleZAngle(vehicleid, cAngle); new Float:rad = (90.0 - cAngle) * 0.0174532925; new Float:points[8]; points[0] = cX; points[1] = cY; points[2] = cX + (45.0 * floatcos(rad + 0.15)); points[3] = cY + (45.0 * floatsin(rad + 0.15)); points[4] = cX + (45.0 * floatcos(rad - 0.15)); points[5] = cY + (45.0 * floatsin(rad - 0.15)); points[6] = cX; points[7] = cY; new areaid = CreateDynamicPolygon(points, cZ - 3.0, cZ + 6.0, 4); Streamer_SetIntData(STREAMER_TYPE_AREA, areaid, E_STREAMER_EXTRA_ID, playerid + RADAR_STREAMER_IDENTIFIER); RadarData[playerid][rOn] = true; RadarData[playerid][rLimit] = viteza; RadarData[playerid][rAreaId] = areaid; Iter_Add(RadarsOn, playerid); TogglePlayerControllable(playerid, 0); new string[64]; format(string, sizeof(string), "Ai activat radarul. Viteza maxima: %d KM/H.", viteza); SendClientMessage(playerid, COLOR_YELLOW, string); return 1; } CMD:stopradar(playerid, params[]) { if(!IsACop(playerid)) return SendClientMessage(playerid, COLOR_GREY, "Nu faci parte din politie."); if(!RadarData[playerid][rOn]) return SendClientMessage(playerid, COLOR_GREY, "Nu ai radarul activ."); ResetPlayerRadar(playerid); SendClientMessage(playerid, COLOR_YELLOW, "Ai dezactivat radarul!"); return 1; } public OnPlayerEnterDynamicArea(playerid, areaid) { new extraid = Streamer_GetIntData(STREAMER_TYPE_AREA, areaid, E_STREAMER_EXTRA_ID); if(extraid >= RADAR_STREAMER_IDENTIFIER) { new copid = extraid - RADAR_STREAMER_IDENTIFIER; if(IsPlayerConnected(copid) && RadarData[copid][rOn] && RadarData[copid][rAreaId] == areaid) { if(playerid != copid && GetPlayerState(playerid) == PLAYER_STATE_DRIVER && OnDuty[playerid] != 1) { new viteza = Carspeed1(playerid); if(viteza > RadarData[copid][rLimit]) { new targetName[MAX_PLAYER_NAME], copName[MAX_PLAYER_NAME], msg[144]; GetPlayerName(playerid, targetName, sizeof(targetName)); GetPlayerName(copid, copName, sizeof(copName)); format(msg, sizeof(msg), "{FF0000}[RADAR] %s[ID:%d] conduce cu {FFFFFF}%d km/h{FF0000}, Locatie: %s, Limita: %d km/h!", targetName, playerid, viteza, GetPlayerZone(playerid), RadarData[copid][rLimit]); SendClientMessage(copid, COLOR_LIGHTBLUE, msg); format(msg, sizeof(msg), "{FF0000}[RADAR] Ai fost surprins de %s conducand cu {FFFFFF}%d km/h{FF0000}. Limita: %d km/h.", copName, viteza, RadarData[copid][rLimit]); SendClientMessage(playerid, COLOR_YELLOW, msg); } } } } return 1; } Am imbunatatit codul tau, ai avut un bug floatcos/floatsin, eroare de cash
-
enum e_RadarData { bool:rOn, rLimit } new RadarData[MAX_PLAYERS][e_RadarData]; new Iterator:RadarsOn<MAX_PLAYERS>; new pickuptimer; public OnGameModeInit() { pickuptimer = SetTimer("CustomPickups", 1000, true); return 1; } public OnGameModeExit() { KillTimer(pickuptimer); return 1; } CMD:startradar(playerid, params[]) { if(!IsACop(playerid)) return SendClientMessage(playerid, COLOR_GREY, "Nu faci parte din departament."); if(OnDuty[playerid] != 1) return SendClientMessage(playerid, COLOR_LGREEN, "Eroare: Nu esti la datorie!"); if(!Copcar2(GetPlayerVehicleID(playerid))) return SendClientMessage(playerid, COLOR_GREY, "Nu esti intr-o masina a factiunii."); if(RadarData[playerid][rOn]) return SendClientMessage(playerid, -1, "Ai deja activat radaru."); new viteza; if(sscanf(params, "d", viteza)) return SendClientMessage(playerid, COLOR_GREY, "USAGE: {FFFFFF}/startradar <Speed Limit>"); if(viteza > 200 || viteza < 40) return SendClientMessage(playerid, -1, "Viteza invalida (40-200)."); RadarData[playerid][rOn] = true; RadarData[playerid][rLimit] = viteza; Iter_Add(RadarsOn, playerid); TogglePlayerControllable(playerid, 0); new string[64]; format(string, sizeof(string), "Ai activat radarul. Viteza maxima: %d KM/H.", viteza); SendClientMessage(playerid, COLOR_YELLOW, string); return 1; } CMD:stopradar(playerid, params[]) { if(!IsACop(playerid)) return SendClientMessage(playerid, COLOR_GREY, "Nu faci parte din 専用 politiei."); if(!RadarData[playerid][rOn]) return SendClientMessage(playerid, COLOR_GREY, "Nu ai radarul activ."); RadarData[playerid][rOn] = false; RadarData[playerid][rLimit] = 0; Iter_Remove(RadarsOn, playerid); TogglePlayerControllable(playerid, 1); SendClientMessage(playerid, COLOR_YELLOW, "Ai dezactivat radarul!"); return 1; } forward CustomPickups(); public CustomPickups() { if(Iter_Count(RadarsOn) == 0) return 1; new Float:pX, Float:pY, Float:pZ; new targetName[MAX_PLAYER_NAME], copName[MAX_PLAYER_NAME], msg[144]; foreach(new o : Player) { if(GetPlayerState(o) != PLAYER_STATE_DRIVER || OnDuty[o] == 1) continue; new viteza = Carspeed1(o); GetPlayerPos(o, pX, pY, pZ); foreach(new i : RadarsOn) { if(viteza <= RadarData[i][rLimit]) continue; if(IsPlayerInRangeOfPoint(i, 30.0, pX, pY, pZ)) { GetPlayerName(o, targetName, sizeof(targetName)); GetPlayerName(i, copName, sizeof(copName)); format(msg, sizeof(msg), "{FF0000}[RADAR] %s[ID:%d] conduce cu {FF0000}%d km/h, Locatie: %s, Limita: %d km/h!", targetName, o, viteza, GetPlayerZone(o), RadarData[i][rLimit]); SendClientMessage(i, COLOR_LIGHTBLUE, msg); format(msg, sizeof(msg), "{FF0000}[RADAR] Ai fost surprins de %s conducand cu {FF0000}%d km/h. Limita: %d km/h.", copName, viteza, RadarData[i][rLimit]); SendClientMessage(o, COLOR_YELLOW, msg); break; } } } return 1; }
-
#include <a_samp> // Intervalul de timp în milisecunde (Ex: 30 de minute = 30 * 60 * 1000) #define WEATHER_TIMER_DELAY (30 * 60 * 1000) // Lista cu ID-urile de vreme alese de tine new const ValidWeathers[] = {1, 2, 3, 5, 9, 12, 15}; public OnGameModeInit() { // Pornim timerul care va apela funcția "ChangeRandomWeather" periodic SetTimer("ChangeRandomWeather", WEATHER_TIMER_DELAY, true); // Opțional: Setăm o vreme random chiar și când se deschide serverul ChangeRandomWeather(); return 1; } forward ChangeRandomWeather(); public ChangeRandomWeather() { // random(sizeof(ValidWeathers)) alege un index la întâmplare din vector new randomIndex = random(sizeof(ValidWeathers)); new newWeather = ValidWeathers[randomIndex]; // Setăm vremea globală pe server SetWeather(newWeather); // Trimitem un mesaj informativ tuturor jucătorilor (opțional) new string[64]; format(string, sizeof(string), "{FF9900}[Server]{FFFFFF} Vremea a fost schimbată (ID: %d).", newWeather); SendClientMessageToAll(-1, string); return 1; } /* sizeof(ValidWeathers): Află automat câte ID-uri ai pus în listă (în cazul tău, 7 ID-uri). Dacă pe viitor vrei să adaugi și ID-ul 7, doar îl treci în array {1, 2, 3, 5, 9, 12, 15, 7} și codul se va adapta singur. random(...): Extrage o poziție din listă (de la 0 la 6). SetWeather(newWeather): Schimbă vremea pentru toți jucătorii care se conectează sau sunt deja pe server.*/
-
function ScadeTimpBillboard() { new query[248]; for(new i = 0; i < MAX_BILLBOARDS; i++) { if(Billboard[i][blOwned] > 0) { if(Billboard[i][blExpire] > 0) { Billboard[i][blExpire] -= 60; UpdateLabelBillboard(i); mysql_format(SQL, query, sizeof(query), "UPDATE `billboards` SET `expire`='%d' WHERE `ID`='%d'", Billboard[i][blExpire], i); mysql_tquery(SQL, query, "", ""); if(Billboard[i][blExpire] <= 0) { mysql_format(SQL, query, sizeof(query), "UPDATE `users` SET `Billboard` = '0' WHERE `Username` = '%s'", Billboard[i][blOwner]); mysql_tquery(SQL, query, "", "" ); Billboard[i][blOwned] = 0; Billboard[i][blPhone] = 0; Billboard[i][blExpire] = 0; format(Billboard[i][blOwner],25,"AdmBot"); format(Billboard[i][blFont],25,"Arial"); format(Billboard[i][blMessage],32,"Your advertisement here!"); mysql_format(SQL,query,248,"UPDATE `billboards` SET `blFont`='Arial',`blOwned`='0',`blOwner`='AdmBot',`blPhone`='0',`blMessage`='Your advertisement here!',`expire`='0' WHERE `ID` = '%d' LIMIT 1",Billboard[i][blID]); mysql_tquery(SQL,query,"",""); SetDynamicObjectMaterialText(Billboard[i][blObjectID],0,Billboard[i][blMessage], OBJECT_MATERIAL_SIZE_256x128,Billboard[i][blFont], 18, 0, 0xFF000000, 0xFFFFFFFF, OBJECT_MATERIAL_TEXT_ALIGN_CENTER); UpdateLabelBillboard(i); } } } } return 1; } Poftim
-
cea mai proasta investitie in 2026 este deschiderea unui server samp, nu mai credeti in stele fratilor
-
Spor la vanzare, nustiu daca mai deschide cineva servere in 2026
