OnPlayerConnect
Mach das bei OnPlayerSpawn hin.
OnPlayerConnect
Mach das bei OnPlayerSpawn hin.
Dein Array heißt supermarkt und du loopst über ticketATM. Da passt was nicht.
printf("Tankstelle: Diese Tankstelle hat %d Bentin erhalten.", floatround(floatsub(gebraucht, Tanke[i][tLiterBenzin])));
zu:
printf("Tankstelle: Diese Tankstelle hat %d Benzin erhalten.", gebraucht - floatround(Tanke[i][tMaxLiterBenzin] - Tanke[i][tLiterBenzin]));
return i;
zu:
return idx;
Dann frag das doch
Will die nähsten Koordinaten herausfinden und dort soll ein Checkpoint erstellt werden.
Es reicht dort ein Textdraw, du brauchst keine drei Textdraws.
Der Fehler tritt dann auf, weil du mit TextDrawSetString ein Integer nutzt.
TextDrawSetString(TextDraw_EventZeit[0], Event[EventMinuten] /*<-- Integer*/);
Nutze stattdessen:
format(string, sizeof(string), "%02d:%02d", Event[EventMinuten], Event[EventSekunden]);
TextDrawSetString(TextDraw_EventZeit, string);
Außerdem kannst du dir das Hide&Show sparen, wenn du nur TextDrawSetString nutzt.
Zusätzlich verweise ich auf: Tipps: Scripting-Probleme richtig erklären
Das ist so ja nicht ganz richtig.
Doch, völlig.
dann kann man auch nicht mehr so einfach checken, wann die Route zu Ende ist oder nicht...
Natürlich kann man das, man muss nur abfragen ob alle Koordinaten des nächsten Punktes 0 sind.
Das ist deutlich besser, als für jede Route einen separaten Code zu schreiben, mit Route1, Route2, Route3, etc.
Ich bitte dich, das empfiehlt niemand.
Variante 1 ist dynamisch nutzbar und damit die einzig sinnvolle Methode.
Das Array ist zwar größer und verbraucht etwas mehr Speicher (völlig irrelevant, ein paar kBs), dafür ist dein Code deutlich sauberer und mit sehr viel weniger Aufwand verbunden, da dynamisch aufgebaut, somit musst du den Code nicht jedes mal anpassen, wenn eine neue Route dazu kommt.
Die korrekte Syntax ist übrigens:
new Float:Route[][][Routeinfo] =
{
{
{1.0,1.0,1.0},
{1.0,1.0,1.0},
{1.0,1.0,1.0},
{0.0,0.0,0.0},//Leerer Cp
{0.0,0.0,0.0}//Leerer Cp
},
{
{1.0,1.0,1.0},
{1.0,1.0,1.0},
{1.0,1.0,1.0},
{1.0,1.0,1.0},
{1.0,1.0,1.0}
}
};
Versuche die erste Variante, bei denen alle Objekte hinter dem Blitzer sind, mit - distance anstatt + distance.
Dann sollte genau der gegenteilige Effekt passieren, somit wären alle Objekte vor dem Blitzer.
Nein, das macht ja keinen Sinn.
Ich meine das Minus direkt hinter der Klammer auf.
floatsin(-
^
Nutze den Code von Versuch 1.
Es könnte sein, dass die Drehung des Blitzers anders ist, als von den meisten Objekten, es gibt da Ausnahmen.
Hast du einfach mal folgendes versucht?
new Float:x = Blitzi[i][blitz_x] + distance * floatcos(-Blitzi[i][blitz_r], degrees);new Float:y = Blitzi[i][blitz_y] + distance * floatsin(-Blitzi[i][blitz_r], degrees);
Es könnte sein, dass die Drehung gegenläufig ist.
Zusätzlich, falls das nicht klappt, kannst du versuchen, alle Varianten durchzuspielen, sprich:
cos und sin mit - hinter der Klammer
cos und sin jeweils nur eins mit -
cos und sin beide ohne -
und dann jeweils noch sin und cos vertauscht, für jeden der obigen Fälle. Sind 8 Fälle insgesamt.
Am einfachsten ist es, wenn du dir 4 Blitzer irgendwo hin stellst, die alle 90° versetzt sind, mit genügend Abstand dazwischen natürlich.
Lasse dann zusätzlich beim Erstellen des Blitzer-Objekts mit der obigen Formel ein weiteres Objekt an der Position "vor" dem Blitzer erstellen, das wäre dann der Punkt, an dem der Blitzer ausgelöst wird.
Wenn bei allen Blitzern das Objekt an der richtigen Position vor dem Blitzer steht, hast du die richtige Formel.
Anschließend nimmst du diese Formel in deine Prüf-Routine und fragst nach IsPlayerInRangeOfPoint zusätzlich noch ab, ob der Spieler den Blitzer anschaut, sprich mit IsPlayerFacingPos auf die Blitzer-Position.
Diese zusätzliche Abfrage ist wichtig, sonst würde der Blitzer auch blitzen, wenn vom Blitzer weg fährt, sprich auf der Gegenfahrbahn.
Dann sollte es passen.
Von 59,99 auf 49,99 runtergesetzt und ich hatte noch einen 15€ Gutschein.
Nach mysql_format muss das Query noch versendet werden:
mysql_pquery(handle, string);
Anstatt
Geschenke[i][ID]
in beiden Funktionen
i
in mysql_format.
Du füllst die ID vom enum beim AddGeschenk nicht. Dem Code nach benötigst du die ID gar nicht, sondern kannst einfach "i" nutzen, in beiden Queries bei der "id" der Datenbank.
Zum einen übertreibe ich angeblich, und zum anderen sollen meine Punkte die gleichen sein, wie die deinen? Außerdem beschreibe ich angeblich was du sagst und zum anderen ist meine Meinung Käse? Da stimmt doch was nicht.
Als Beispiel nennst du ein Haussystem. Ich hatte selbst jahrelang einen Server, mit einem solchen System. Es lässt sich auf gar keinen Fall komplett vom Rest trennen, und gehört damit auch nicht in eine Include.
Außerdem sagst du explizit, dass die Logik (also die Integration in den Gamemode) in die Include soll. Genau das soll sie eben nicht. Das ist der springende Punkt. In Includes gehört nur das, was sich ohne integrative Probleme in jeden beliebigen anderen Gamemode hinzufügen lässt. Dein "Tutorial" stellt dies völlig falsch dar.
Ich stehe zu dem, was ich geschrieben habe und betone nochmal, dass hoffentlich niemand seinen Code durch die falsche Darlegung der modularen Programmierung in diesem "Tutorial", um die es dem Titel nach ja gehen sollte, aber gar nicht geht, verunstaltet.
Ich kann diese Methode nicht für gut heißen und auch nicht empfehlen.
Was hier beschrieben wird, hat nichts mit echtem modularen Code-Aufbau zu tun, sondern verteilt den eigentlichen Code nur in unzählige Includes, was den Code nur verteilt und sonst keinen Mehrwert bringt, der die Nachteile davon überwiegen würde. Es wird ein falscher Eindruck von Modularem Coding vermittelt.
Unter Modularem Coding versteht man nämlich im weitesten Sinne:
Weitere Informationen zu echter modularer Programmierung: https://de.wikipedia.org/wiki/Modulare_Programmierung bzw. https://en.wikipedia.org/wiki/Modular_programming
Keiner der oben genannten Aspekte trifft auf die hier beschriebene Logik zu.
Es erzeugt deutlich mehr Verkomplizierungen, wenn man seine Systeme in Includes auslagert.
Beispielsweise kann man in den Includes dann keine systemübergreifenden Funktionen einbauen, ohne dass diese im falschen Include stehen.
Stellen wir uns mal vor, man hat ein Banksystem und ein Autohaussystem. Die Include des Banksystems steht vor der Include des Autohaussystems im Code. Dinge wie z.B. #define GetCarValue(%0) carInfo[%0][cValue] können dann nicht im Banksystem verwendet werden. Auf den ersten Blick mag dies auch nicht notwendig sein. Denkt man aber nur einen Schritt weiter, dann kann dies durchaus notwendig sein. Man muss sich nur vorstellen, man kann ein Fahrzeug Leasen und will die Bankrate entsprechend es Fahrzeug-Werts berechnen. In welches System (und damit in welche Include) gehört der Leasing-Vertrag dann, der mit der Bank aber im Autohaus abgeschlossen wird? Oder ein entsprechender Kreditvertrag, bei dem die Fahrzeug-Papiere bei der Bank hinterlegt werden? Natürlich kommt man über stock-Funktionen etc. an die Werte auch im Banksystem hin, darum geht es nicht. Man verkompliziert sich den Aufbau und wird niemals eine 100%'ige Trennung hinbekommen. In zig Threads zur Code-Optimierung wird gepredigt, keine unnötigen Funktionen aufzubauen, was man mit dieser Variante aber sehr wohl machen müsste.
Zusätzlich, und das ist der springende Punkt an diesem Beispiel, vermischen sich die beiden Beispiele hier. Man wird daher nicht zwingend alle Punkte, die ein Autohaus betreffen, auch in der Autohaus-Include haben. Ich werde jetzt nicht dutzende Beispiele bringen, die durch diese Methode schlechter werden, das Beispiel genügt.
Zusätzlich, stellen wir uns doch mal vor, wir haben ein Flughafen-System und ein Bahnhof-System. Hat man nun zum Beispiel in einem Timer eine Prüfung drin, die überprüft, ob der Spieler an einem Flughafen oder einem Bahnhof ist, und dann irgendetwas ausführt, dann geht dies hier nicht ohne weiteres. Normales Verhalten wäre ein 1-Sekunden-Timer (oder was auch immer), der prüft, ob der Spieler entweder am Bahnhof oder am Flughafen ist. Das klappt hier nicht, da man beides nicht in eine Include packen kann. Somit hat man zwei Timer und somit hat man auch erneut das Gegenteil von der hier als nicht vorhanden genannten Performanceverschlechterung erreicht.
Es gibt natürlich noch deutlich mehr und deutlich komplexere Logiken, bei denen Systeme ineinandergreifen müssen, um korrekt zu funktionieren. Das ist immer vom jeweiligen Gamemode abhängig.
Um nochmal auf die Ressourcen zurück zu kommen. Bisher hat man ein Callback im Code, dort steht alles drin. Hookt man das Callback jetzt in 10 Includes, dann muss in jedem Callback beispielsweise eine Variable "string[145]" zur Ausgabe von Nachrichten deklariert werden. Auch hier wird in unzähligen Threads geschrieben, dass man die mehrfache Deklaration von Variablen nach Möglichkeit vermeiden soll. Hier würde man dies explizit machen und sich daher den x-fachen Speicher anhäufen. Dies nur als einzelnes Beispiel.
Wie man an den Beispielen aber sieht, ist diese hier sogenannte "modulare Programmierung" (was es nicht ist!) hier nur in der Theorie gegeben, sieht auf dem Papier schön aus, macht es in der Praxis aber nur unnötig kompliziert.
Wofür sind Includes eigentlich gedacht? Includes sind dafür gemacht, wie oben in den Punkten genannt, fertige Funktionen, die unabhängig voneinander funktionieren, in den Code einzubinden, zum Beispiel einen Checkpoint-Streamer. Im Prinzip nichts anderes als Libraries in Java zum Beispiel. Niemand würde in Java auf die Idee kommen, seinen gesamten Code in Libraries auszulagern. So sollte auch in PAWN niemand auf die Idee kommen, seinen Code in Includes auszulagern.
Der Ansatz, wie er hier als schlecht beschrieben wird, Funktionen in Includes zu trennen, bringt technisch gesehen zwar nichts, wird aber sehr häufig in der Praxis verwendet, um gigantische Code-Dateien zu vermeiden. Ein Beispiel aus meinem Alltag sind zum Beispiel SAP Reports, diese sind , bei deutlicher Komplexität, öfters auch so aufgebaut, dass es eine Include gibt (TOP-Include), welche alle Deklarationen beinhaltet, eine Include, welche die Selektions-GUI beinhaltet und diverse Includes, welche die jeweilig getrennten Funktionen beinhalten. Dies kann man machen, muss man aber nicht. Ich persönlich (meine Meinung) finde diesen Ansatz in der Regel trotzdem nicht sinnvoll, da im Falle von SAP z.B. eine Möglichkeit besteht, Code direkt in der Ausführung zu debuggen. Springt man ständig durch die Includes, fehlt oftmals die Verbindung zwischen den Funktionen und auch für Anpassungen muss man oftmals durch diverse Includes springen, um alle Anpassungen machen zu können.
Fazit:
Eine Trennung der Logik kann und sollte nicht über Includes realisiert werden, aus oben genannten Gründen, welche im Wesentlichen aus der unnötigen Verkomplizierung vom Aufbau des Codes bestehen und der nicht sauber vorhandenen Trennbarkeit von Systemen.
Zudem hat der beschriebene Ansatz im Tutorial nichts mit der tatsächlichen Idee der Modularen Programmierung zu tun und vermittelt ein falsches Bild dessen.
Includes sollten dafür genutzt werden, wofür sie auch gemacht sind. Um Funktionen unabhängig und in mehreren Codes einbinden zu können.
Ich kann nur hoffen, niemand verbiegt sich hierdurch unnötigerweise seinen Code.
1. Ja.
2. Die spalte natürlich. Warum willst du dort die 3 stehen haben, welchen Zweck hätte das?
Du musst die Spalte genau gleich im Funktionskopf mitgeben, wie die playerid auch, das hast du doch auch hinbekommen, warum verkomplizierst du es jetzt so?
Wenn ich schreibe "wie die playerid auch", warum schreibst du dann GVRN(playerid)[4]? playerid = innerhalb der runden Klammern --> Folge: slot ebenfalls innerhalb der Runden Klammern und nicht außerhalb der runden Klammern in eckigen Klammern.
Außerdem ist 4 zu groß, es geht nur 0 bis 3. Und warum schreibst du das fest rein? Der Spieler gibt das doch ein.
GVRN(playerid, spalte)
switch(SpielerDaten[playerid][pVerwalter][3])
Warum schreibst du dort die 3 hart rein? Willst du immer nur die 4. Spalte (pVerwalter4) zurückgegeben bekommen? Nein, also:
stock GetVerwalterRangName(playerid, spalte)
{
new string[50];
switch(SpielerDaten[playerid][pVerwalter][spalte])
{
case 0: string = "Spieler";
case 1: string = "Helferverwalter";
case 2: string = "Firmenverwalter";
case 3: string = "Bizverwalter";
case 4: string = "Fraktionsverwalter";
case 5: string = "Parteiverwalt";
case 6: string = "Hausverwalter";
case 7: string = "Charakterbeauftragter";
case 8: string = "Eventmanager";
}
return string;
}
Du sollst es nicht so machen, wie du denkst, sondern wie es dir gesagt wird, wenn du danach fragst.
Sonst brauchst du nicht danach fragen.
Also gehe bitte die Punkte aus obigem Post von mir an. Das sind 4 "auf die Sprünge Helfer".
Arbeite dich in den Code und die Punkte die man dir sagt ein. Wenn du alle 10 Minuten sagst, du kommst nicht weiter, nachdem du nicht einmal die Hälfte dessen gemacht hast, was dir gesagt wurde, dann ist das für mich einfach nur Desinteresse, dann sehe ich es auch nicht ein, dir zu helfen. Es soll ja am Ende dein Code sein, wenn du nichts dafür tust, dann wird das nichts.
Was soll den diese Schleife, so wie sie da steht, bewirken? Das macht doch gar keinen Sinn und entspricht auch nicht dem, was ich dir gesagt habe.
Außerdem sind alle diese Zeilen nicht korrekt:
SD[pID][pVerwalter] = verwid;
Wenn du keine Spalte angibst, was soll der Code da machen? Gebe die Spalte entsprechend an.
GVRN hast du auch nicht angepasst.
Wenn du die Dinge, die man dir sagt, ignorierst, wird es schwer dir nachhaltig zu helfen.
Bitte arbeite etwas gewissenhafter, was du aktuell machst ist einfach nur ohne Nachdenken mit völligem Desinteresse hingeklatscht.