Beiträge von Kaliber
-
-
Für Anregungen oder Lösungen wäre ich sehr dankbar
Es wäre cool, wenn du 2 SQL Files hochladen könntest, die die jeweiligen Tabellen mit ihren Spalten erstellen + 2 Testdatensätze und dann genau erklären, wie du dir das Ergebnis vorstellst 😅
Dann muss man sich das nicht aus dem Text theoretisch alles herleiten, dafür bin ich gerade zu faul

-
Und Ihr so?
Externer Inhalt www.youtube.comInhalte von externen Seiten werden ohne Ihre Zustimmung nicht automatisch geladen und angezeigt.Durch die Aktivierung der externen Inhalte erklären Sie sich damit einverstanden, dass personenbezogene Daten an Drittplattformen übermittelt werden. Mehr Informationen dazu haben wir in unserer Datenschutzerklärung zur Verfügung gestellt. -
-
Was muss ich jetzt hier verändern?
Steht doch in der Warnung, kein SHA256 verwenden.
Hatte mal bisschen hier darüber mehr erklärt: Hash Verfahren genauer erklärt
Als Fazit, nutze BCrypt: https://github.com/Sreyas-Sreelal/samp-bcrypt
PS: Verwende in MySQL Querys, niemals %s. Wurde dafür extra %q eingeführt, oder du nutzt mysql_format mit %e

-
ja aber dazu muss doch die 0 eine 1 sein das der timer darin auch immer wieder läuft 0 sprich false ist doch nur einmal laufen ?
Lies meinen ersten Satz, der Timer ruft sich immer wieder auf, weil er in der Funktion selbst ist 😅
Er wird einmalig aufgerufen -> Ruft sich einmalig selbst auf -> rufst sich einmalig selbst auf -> ruft sich einmalig selbst auf
Ist eine Endlosschleife

-
Nein, in der Funktion ruft sich der Timer immer wieder auf xD
Am Anfang wird die Funktion direkt aufgerufen, damit sich das Wetter sofort setzt

Kannst natürlich auch das auf 1 setzen und die Timer Funktion aus der Funktion löschen.
-
Ja, wobei du das dann noch einmal aktualisieren musst, damit die Änderung sofort gültig wird.
C++
Alles anzeigenstock UpdateWeatherForAll() { for(new i; i<MAX_PLAYERS; i++) { if(!IsPlayerConnected(i)) continue; if(IsPlayerInDynamicArea(i, sZoneLS)) SetPlayerWeather(i, sWeatherLS); else if(IsPlayerInDynamicArea(i, sZoneSF)) SetPlayerWeather(i, sWeatherSF); else if(IsPlayerInDynamicArea(i, sZoneLV)) SetPlayerWeather(i, sWeatherLV); } return 1; } -
Habe hier das zu gefunden
Ja, was ich meinte war sowas:
C++
Alles anzeigen//Ganz oben definieren static sWeatherLS, sWeatherSF, sWeatherLV; static sZoneLS, sZoneSF, sZoneLV; //Unter OnGameModeInit oder OnFilterscriptInit sZoneLS = CreateDynamicRectangle(2919.469, -782.4177, 93.423, -2837.724); sZoneLV = CreateDynamicRectangle(2942.825, 2884.435, 794.0955, 618.9274); sZoneSF = CreateDynamicRectangle(-1377.989, 1599.869, -2989.536, -1004.297); ChangeWeather(); //Dann irgendwo public OnPlayerEnterDynamicArea(playerid, STREAMER_TAG_AREA:areaid) { if(areaid == sZoneLS) SetPlayerWeather(playerid, sWeatherLS); else if(areaid == sZoneSF) SetPlayerWeather(playerid, sWeatherSF); else if(areaid == sZoneLV) SetPlayerWeather(playerid, sWeatherLV); return 1; } forward ChangeWeather(); public ChangeWeather() { sWeatherLS = random(20); sWeatherSF = random(20); sWeatherLV = random(20); SetTimer("ChangeWeather", 1000*60*10, 0); //Ändert sich alle 10min return 1; }Dann macht das das Streamer Plugin alles für dich automatisch

-
So hier:
C++
Alles anzeigen//Ganz oben definieren #define IsPlayerInLosSantos(%0) IsPlayerInArea(%0, 2919.469, 93.423, -782.4177, -2837.724) #define IsPlayerInLasVenturas(%0) IsPlayerInArea(%0, 2942.825,794.0955,2884.435,618.9274) #define IsPlayerInSanFierro(%0) IsPlayerInArea(%0, -1377.989,-2989.536,1599.869,-1004.297) static sWeatherLS, sWeatherSF, sWeatherLV; //Unter OnGameModeInit oder OnFilterscriptInit ChangeWeather(); SetTimer("ChangeWeatherForPlayers", 1000*5, 1); // Alle 5sek //Dann irgendwo forward ChangeWeatherForPlayers(); public ChangeWeatherForPlayers() { for(new i; i<MAX_PLAYERS; i++) { if(!IsPlayerConnected(i)) continue; if(IsPlayerInLosSantos(i)) SetPlayerWeather(i, sWeatherLS); else if(IsPlayerInSanFierro(i)) SetPlayerWeather(i, sWeatherSF); else if(IsPlayerInLasVenturas(i)) SetPlayerWeather(i, sWeatherLV); } return 1; } forward ChangeWeather(); public ChangeWeather() { sWeatherLS = random(20); sWeatherSF = random(20); sWeatherLV = random(20); SetTimer("ChangeWeather", 1000*60*10, 0); //Ändert sich alle 10min return 1; } //Unten im Skript (oder in einer utils.inc oder sowas) stock IsPlayerInArea(playerid, Float:minx, Float:maxx, Float:miny, Float:maxy) { new Float:x, Float:y, Float:z; GetPlayerPos(playerid, x, y, z); return (x > minx && x < maxx && y > miny && y < maxy); }Das Wetter muss natürlich perma gesetzt werden, falls Spieler die Zone verlassen xD
Theoretisch kannst hier auch mit dem StreamerPlugin und dynamischen Areas arbeiten, dann gibt es den Callback OnPlayerEnterDynamicArea. Dann benötigst du keine Loop die perma läuft.
Aber dafür müsst ich nochmal ins Include vom Streamer schauen, da war ich grad zu faul für xD
-
-
dass erklärt warum ich kaum noch was finde dazu.
Was suchst du denn? 😅
Eigentlich würde das doch bedeuten, dass man extrem viel zu etwas findet, je älter es ist 😄 Das Problem ist halt, dass das englische Forum gelöscht wurde...
-
Ich merke, Deutsche Spieler sind ein besonderes Volk.
Streich das Spieler 😂
-
Hey cooles Ding,
ich dachte ich bin mal so frei und geb dir ein kleines Code Review (auch wenn keiner danach gefragt hat)

Ich gehe jetzt auf nichts Pawn-Spezifisches ein, sondern ganz generell quasi ein kleines Clean Code Feedback.
Ich pack es mal in den Spoiler, damit ich hier nicht so viel Platz klaue

- Statt den defines für die Dialoge, wäre ein enum besser, da kannst du nämlich oben die erste Zahl ändern, und dann zählt der Compiler automatisch immer eins hoch, das ist dann leichter anzupassen
- dini sollte man nicht nutzen, das ist wirklich Schmutz. Verstehe, dass du kein MySQL nutzen wolltest, da das wieder Konfigurationsaufwand wäre. Dann aber zumindest SQLite wäre eine deuutlich bessere Alternative gewesen.
- Das größte Manko was mir aufgefallen ist, aber da geht es nicht nur die so, sondern sehr sehr vielen Leuten. Man wiederholt Code ohne Ende. Das möchte man als Entwickler eigentlich komplett vermeiden. Beispiel: Zeile 142 und 156 da geht es schon los. Einfach Funktionen machen, die tun nicht weh xD Aber ich sage mal so 80% Code ist redundant. Zeile 435 - 546 und dann von 546-778 kannst du dir komplett schenken
Das sind einfach mal 300 Zeilen Code, die unnötig sind. Und in deinen Befehlen wiederholst du auch sehr oft Routinen, die einfach in eine Funktion auslagern
Das würde den Code deutlich deutlich übersichtlicher machen.
Zu Punkt 3, wie man das realisieren kann:
C++switch(listitem){ case 0:{//Kick Player permissionChange[playerid] = 1; return ShowCurrentAccessLevelDialog(playerid,"KICKPLAYER_USABLE"); }Da hast du ein ewig langes switch-case.
Wie wäre es aber so, du machst ein konstantes großes Array mit den ganzen Namen, also sowas wie:
C++
Alles anzeigen//Ganz oben ins Skript static stock const gUserUsables[][] = { "KICKPLAYER_USABLE", "BANPLAYER_USABLE", "TIMEBANPLAYER_USABLE", "UNBANPLAYER_USABLE", //usw.. }; //Und dann anstatt dem switch-case, einfach: permissionChange[playerid] = listitem+1; return ShowCurrentAccessLevelDialog(playerid, gUserUsables[listitem]);Dadurch würdest du dir allein dort 100 Zeilen sparen.
Dann genau das Selbe weiter unten:
C++
Alles anzeigenswitch(permissionChange[playerid]){ case 1:{// Kick Player if(strval(inputtext) <= 0 || strval(inputtext) > MAX_ADMINLEVEL){ return ShowCurrentAccesLevelDialogE(playerid, "KICKPLAYER_USABLE"); } permissionChange[playerid] = -1; UpdateAccessLevel("KICKPLAYER_USABLE", strval(inputtext)); return ShowPermissionDialog(playerid); } case 2:{// Ban Player if(strval(inputtext) <= 0 || strval(inputtext) > MAX_ADMINLEVEL){ return ShowCurrentAccesLevelDialogE(playerid, "BANPLAYER_USABLE"); } permissionChange[playerid] = -1; UpdateAccessLevel("BANPLAYER_USABLE", strval(inputtext)); return ShowPermissionDialog(playerid); }Da machst du es dir viel zu kompliziert 😅
Kannst dir die 300 Zeilen sparen und einfach:
C++new tValue = strval(inputtext); if(tValue <= 0 || tValue > MAX_ADMINLEVEL) return ShowCurrentAccesLevelDialogE(playerid, gUserUsables[permissionChange[playerid]]); UpdateAccessLevel(gUserUsables[permissionChange[playerid]], tValue); permissionChange[playerid] = -1; return ShowPermissionDialog(playerid);4. Du machst es dir mit deinem Sprachensystem viel zu schwierig. Hier würde sich auch anbieten einfach ein konstantes Array anbieten und dort schreibst du alle Texte rein und greifst dann nur noch darauf zu. Da sparst du dir maaaassig Zeilen xD Zumal du oft gleich den ganzen Befehl in 2 Sprachen gemacht hast, statt nur den Code, auf den es ankommt

5. Durch die ganzen Wiederholungen ist dein Code sehr anfällig für Fehler. Also es ist fast unmöglich keine zu machen, da ständig alle Variablen manuell zurückgesetzt werden müssen etc pp. Sowas einfach in Funktionen auslagern.
6. Du nutzt sehr viele globale Variablen. Ruhig, gerade wenn es nur temporär ist paar PVars nutzen.
Für Weitere Infos, kann den YouTube Channel für CleanCode empfehlen: https://www.youtube.com/@10minuteswithcoachjoe55
Gibt da gewisse Regeln generell wie KISS und DRY (https://de.wikipedia.org/wiki/Don%E2%80%99t_repeat_yourself).
Bei deinem nächsten Projekt kannst du versuchen diese mehr zu berücksichtigen!

- Statt den defines für die Dialoge, wäre ein enum besser, da kannst du nämlich oben die erste Zahl ändern, und dann zählt der Compiler automatisch immer eins hoch, das ist dann leichter anzupassen
-
Es gibt einen mysql.log
Entweder direkt im server Verzeichnis oder es gibt ein log Verzeichnis wo er drinnen liegt.Falls nicht, diesen mit mysql_log(ALL); unter OnGameModeInit aktivieren.
Dort steht genau drinnen, was passiert und ob etwas fehlschlägt oder nicht

-
Ich finde es gut, wie du dir im Text die Titelfrage schon selbst beantwortest

Wenn die Frage ist, ob es besser geht: Es geht immer besser.

-
Wie kann ich denn nun allerdings die Farben erstellen mit Transparenz ?
Der Farbwert ist so aufgebaut: 0xAABBCCDD
AA = Rot Anteil
BB = Grün Anteil
CC = Blau Anteil
DD = Alpha, sprich Transparenz
0xAABBCC00 = unsichtbar, 0xAABBCCFF = maximal sichtbar, Farbe ist nicht durchlässig
Du musst quasi nur hinten die beiden Zahlen zwischen 00-FF etwas setzen, um die Transparenz zu ändern

-
Zusätzlich sollte das UPDATE Query vom Gamemode geprüft werden. Vermutlich wird nur ein INSERT gemacht, aber das Update Query schlägt fehl, deshalb werden keine Werte dort eingetragen

-
Ich würde dir empfehlen den Code etwas zu refactoren.
Dadurch wird er weniger Fehleranfällig, da alles separiert und getrennt von der eigentlichen Logik ist.
Hier mal als kleine Inspiration:
C++
Alles anzeigen#include <tutorial> //Unterhalb new PlayerInfo iwo setzen ;) public OnPlayerSpawn(playerid) { if(!PlayerInfo[playerid][pTutorial]) return StartPlayerTutorial(playerid);//pTutorial sollte ein Bool sein SetCameraBehindPlayer(playerid); //Kannst du generell immer hier reinpacken, wenn du das magst :D return 1; //Immer 1 zurückgeben, sonst werden Filterscripts ignoriert (brauchst hier kein SetPlayerSpawn, nutz einfach hier die Funktion) } // In tutorial.inc static stock const CAMERA_TIME = 10_000; //in ms (_ kann als Trenner gesetzt wird, wird vom Compiler ignoriert) stock StartPlayerTutorial(playerid) { SetTimerEx(!"Player_Tutorial", CAMERA_TIME, false, !"ii", playerid, 1); SendClientMessage(playerid, COLOR_ORANGE, !"Das Tutorial startet in 10 Sekunden."); //Das ! vor Strings packt diese, macht diese kleiner und schneller. (nicht bei format anwenden) return 1; } stock EndPlayerTutorial(playerid) { PlayerInfo[playerid][pNeuling] = 1; PlayerInfo[playerid][pTutorial] = 1; Player_Save(playerid); SendClientMessage(playerid, COLOR_GREEN, !"Du hast das Tutorial erfolgreich abgeschlossen."); TogglePlayerSpectating(playerid,0); //Spawnt den Spieler automatisch return 1; } static forward Player_Tutorial(playerid, step); public Player_Tutorial(playerid, step) { switch(step) { case 1: { InterpolateCameraPos(playerid, -2264.149169, -79.553237, 54.108608, -2258.836914, -133.797988, 38.133533, CAMERA_TIME); InterpolateCameraLookAt(playerid, -2269.145263, -79.574234, 53.913345, -2263.404052, -131.805282, 37.719944, CAMERA_TIME); SendClientMessage(playerid, COLOR_YELLOW, !"Der Neulingsspawn"); } case 2: { InterpolateCameraPos(playerid, -2559.761230, 657.360534, 54.506183, -2606.139892, 570.644104, 27.216636, CAMERA_TIME); InterpolateCameraLookAt(playerid, -2564.715087, 657.393859, 55.183780, -2609.537841, 574.257385, 26.585512, CAMERA_TIME); SendClientMessage(playerid, COLOR_YELLOW, !"Das Krankenhaus"); } case 3: { InterpolateCameraPos(playerid, -2731.381347, 52.292167, 44.589134, -2696.582275, -60.425365, 6.027071, CAMERA_TIME); InterpolateCameraLookAt(playerid, -2727.718750, 49.573192, 42.541774, -2693.474609, -56.652973, 7.081593, CAMERA_TIME); SendClientMessage(playerid, COLOR_YELLOW, !"Das Rathaus"); } case 4: return EndPlayerTutorial(playerid); } SetTimerEx(!"Player_Tutorial", CAMERA_TIME, false, !"ii", playerid, step+1); return 1; }Dann lenkt das nicht so im eigentlichen Gamemode ab

-
Eventuell hat Kaliber sonst sobald er Zeit hat noch eine Idee ?
Wie ich gerade sehe, speicherst du Farben als varchar ab.
Das ist natürlich Quatsch, da Hexadezimale Zahlen, ja auch nur Zahlen sind und somit einfach nur Integer.
Ob du 0xF, 0b1111 oder 15 schreibst, ist komplett äquivalent.
Wie ist denn frak_color im enum definiert?
strval struggelt mit Hexzahlen, deshalb geht das so nicht.
Ich empfehle dir, änder den Typ in der MySQL Tabelle auf Integer und nutze natürlich cache_get_value_name_int.
Und im enum lass es eine Zahl sein.
Dann nimm meine erste Funktion und es sollte gehen
