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.
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.
stock 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;
}
Alles anzeigen
Habe hier das zu gefunden
Ja, was ich meinte war sowas:
//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;
}
Alles anzeigen
Dann macht das das Streamer Plugin alles für dich automatisch ![]()
So hier:
//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);
}
Alles anzeigen
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 ![]()
Zu Punkt 3, wie man das realisieren kann:
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:
//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]);
Alles anzeigen
Dadurch würdest du dir allein dort 100 Zeilen sparen.
Dann genau das Selbe weiter unten:
switch(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);
}
Alles anzeigen
Da machst du es dir viel zu kompliziert 😅
Kannst dir die 300 Zeilen sparen und einfach:
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! ![]()
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:
#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;
}
Alles anzeigen
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 ![]()
Dann hast beim Laden der Farben einen Fehler...
Wie sieht die db aus?
Wie sieht das Laden aus?
...
Der zurückgegebene Wert ist in diesem Fall 0
Dann stimmt einfach etwas mit deiner Logik nicht.
Was ist denn GfInfo[i][old_fraktion]?
Und du bekommst da keine Fehlermeldung? Du gibst einen String zurück, wo ein Integer erwartet wird...
Wie wäre es denn mit:
GetFrakColor(id)
{
for(new i; i < sizeof(FrakInfo); i++)
{
if(id == FrakInfo[i][frak_id])
{
return FrakInfo[i][frak_color];
}
}
return 0xFFFFFFFF;
}
Alles anzeigen
Interessant wäre auch, welchen Wert frak_colors hat. Evtl fehlen da Alpha Werte, diese könntest du hier auch einfach hinzufügen.
Es ist zum Fehler finden sehr hilfreich, öfter ein System.out.println einzubauen, so kannst du genau nachvollziehen, was an den gewissen geschieht und ob diese überhaupt aufgerufen werden ![]()
while(c.next()) { if(c.wasAdded()) { Lernkarte[] ak = lk.gibAlleKarten(); for(int i = 0; i < ak.length; i++) { liste.add(ak[i].toString()); } } }
Das sieht mir etwas komisch aus.
Müsste es nicht sowas irgendwie sein? 😅
Habe mit JavaFX noch nie etwas gemacht, aber die Logik wäre ja, dass es nur hinzugefügt wird, wenn es noch nicht hinzugefügt wurde. Keine Ahnung, wieso du alles noch einmal hinzufügst :o
Läuft der MySQL-Server auf dem selben Server wie der SA:MP Server?
Dann solltest du 127.0.0.1 einfach verwenden ![]()
-bash: ./samp03svr: No such file or directory
Daaa stimmt vermutlich die Berechtigung nicht. Musst evtl chmod mal nutzen ![]()
Das ist zwar der server_log und nicht der mysql.log, aber abgesehen davon läuft denn mysql überhaupt? ![]()