Beiträge von Goldkiller

    Hier nochmal eine Testversion,Changelog:


    Wer MYSQL nutzen möchte für das Usersystem ->[REL]SAMP-MySQL v0.14 - Memory Leak FIXED !!!
    Download zur Testversion gibt es hier : > Klick <

    Sag mir die benötigten Floatberechnungen und ich release so einen "Kilometerzähler".


    Bei manchen mag die Eigeninitiative tot sein, bei anderen, wie mir z.B., lebt sie noch.


    Wohl eher nicht,die Suchfunktion zu benutzten ist dann wohl doch zu viel Arbeit ... :whistling:

    Hab mir das Tutorial jetzt nicht durchgelesen,kann aber versicher das es bei mehreren Pickups nicht so funktionieren wird wie du möchtest.
    tutpickup = AddStaticPickup(pickupid,type,x,y,z);

    tutpickup wird immer 1 sein,wenn das Pickup erfolgreich erstellt wurde.
    Man sollte anstatt AddStaticPickup(),CreatePickup() nehmen bei solchen Sachen.

    Dann ließ das Tutorial noch einmal,irgendwo wirst du wohl etwas falsch gemacht haben.
    Grob sieht das immer so aus:
    #define dcmd(%1,%2,%3) if ((strcmp((%3)[1], #%1, true, (%2)) == 0) && ((((%3)[(%2) + 1] == 0) && (dcmd_%1(playerid, "")))||(((%3)[(%2) + 1] == 32) && (dcmd_%1(playerid, (%3)[(%2) + 2]))))) return 1


    public OnPlayerCommandText(playerid,cmdtext[])
    {
    dcmd(test,4,cmdtext);
    return 0;
    }


    dcmd_test(playerid,params[]) {
    // hier code
    return 1;
    }

    Und welcher Teil ist nicht auf Deutsch X__x?
    Erklär doch einfach mal mal wozu der Eintrag Passwort[255!!!] gut ist in enum PlayerInfo.

    Zitat

    BrighT ihc habe nichts bei onplayerdisconnect drin muss ihc noch machen wo kann man den pFile deklariren?


    Muss man dir jetzt bei deinem eigenen Tutorial etwas erklären :0 ?

    Zitat

    Warum es enum heißt kann ich euch leider nicht sagen.


    Weiss nicht ob es stimmt,hab es aber immer damit verbunden.
    to enumerate


    Pass[255], // Das Passwort, es kann bis zu 255 Zeichen lang sein

    Kannst mal erklären wofür man das Passwort in einer Variablen speichern sollte :\ ?
    Ich brauch das Passwort nur beim einloggen (/login) oder Passwört ändern (/changepw).Da reicht es auch wenn ich es temporär speicher oder direkt als return nur benutzte.


    - - - - - - - - - - - - - - -
    Ansonsten nettes Tutorial.Wollen wir mal hoffen,dass es auch welche gebrauchen ;).

    Ich würde OnPlayerUpdate() erst gar nicht anrühren.Für sowas würde ich eher einen Timer nehmen,wenn überhaupt der alle 5Minuten etwas speichert.Ansonsten reicht es bei OnPlayerDisconnect()

    Was hat das für einen Sinn das Passwort in einem 255 / 128 Zellen- Großem Array zu speichern?
    Das Script im Anhang zeigt auch ganz deutlich wofür man OnPlayerUpdate() niemals benutzten sollte.

    >= 0
    Das ist sicherlich falsch,denn samp_mysql_fetch_row()


    num_line=samp_mysql_num_rows(); //Korrekte Anzahl
    while ((num_line = samp_mysql_fetch_row(line)) > 0) //Bricht nach einem Schleifendurchgang ab

    Verstehe hier den Zusammenhang nicht ganz.Wozu speicherst du erst in num_line die Anzahl an rows,wenn du sie danach in der while()-schleife überschreibst mit dem Eregnis von samp_mysql_fetch_row was sowieso nur 1 / true oder 0 /false ist.


    Bin jetzt nicht gut im Ungang mit MYSQL,glaube aber du müsstest es so machen:
    if(samp_mysql_query(statement) && samp_mysql_store_result())
    {
    new
    num_line=samp_mysql_num_rows(); //Korrekte Anzahl
    printf("pre num_line = %d",num_line);
    while ((num_line) && (samp_mysql_fetch_row(line))) {
    {
    printf("num_line = %d", num_line);
    if (!line[0]) {
    continue;
    }
    print(line); // würde crashen wenn nicht vorher abfrage wäre ob der string leer ist
    samp_mysql_strtok(col1, "|", line);
    samp_mysql_strtok(col2, "|", "");
    samp_mysql_strtok(col3, "|", "");
    print("..."); //Wird noch ausgegeben
    num_line--;
    }
    }

    "u" ist ein spezieller Typ mit dem man Automatisch die Spieler ID bekommt.Bei dem Typ ist es egal ob man den Namen oder die ID direkt angibt,der Typ u würde bei der Eingabe von einem Namen diesen automatisch in die ID der Spielers umwandeln.
    Ich sehe jetzt auf den ersten blick keinen Fehler bei deinem Code,habs deshalb mal selber fix runtergeschrieben.
    public OnPlayerCommandText(playerid, cmdtext[]) {
    dcmd(heal,4,cmdtext);
    return 0;
    }
    dcmd_heal(playerid,params[]) {
    new
    giveid;
    if(sscanf(params,"u",giveid)) {
    return SendClientMessage(playerid,COLOR_RED,"Benutzung: /heal [Name / ID]");
    }
    if(!IsPlayerConnected(giveid)) {
    return SendClientMessage(playerid,COLOR_RED,"Spieler nicht gefunden!");
    }
    SetPlayerHealth(giveid,100.0);
    SendClientMessage(giveid,COLOR_YELLOW,"Du wurdest von einem Admin geheilt!");
    return 1;
    }

    Guten Morgen,


    Wie ich immer wieder merke gibt es noch sehr viele Leute die nicht wissen wie man ein Script erstellt bei denen Checkpoints
    abgefahren werden (Die roten Kreise falls jemand nicht genau weiss was das ist ;] ), sei es nun für Jobs oder Rennen.
    Für alle anderen die meinen sie wissen wie man so etwas erstellt,schaut euch das Tutorial trotzdem an.Denn am Beispiel von diesem Post hier des Müllabfuhrscript ist wieder mal deutlich gezeigt wie man es eigentlich nicht machen sollte.
    Es ist unglaublich unübersichtlich mit dem extrem langen Code unter OnPlayerCheckpoint,außerdem sehr schlecht zu
    bearbeiten falls man irgendwo in der Mitte einen neuen Checkpoint hinzufügen möchte oder sonst wo.


    Wer soll sich denn bitte bei diesem Code zurecht finden:



    public OnPlayerEnterCheckpoint(playerid) {
    new trinkgeld = random(85); // Betrag für das Trinkgeld, lässt sich beliebig ändern! ( Zufalls Betrag )
    new string[256];
    if(Checkpoint[playerid] == 1)
    {
    SendClientMessage(playerid, COLOR_RED, "Muell aufgeladen, weiter!");
    GivePlayerMoney(playerid, trinkgeld);
    format(string, sizeof(string), "** Du hast %d$ Trinkgeld bekommen!",trinkgeld);
    SendClientMessage(playerid, COLOR_GREEN, string);
    DisablePlayerCheckpoint(playerid);
    SetPlayerCheckpoint(playerid, -89.2432,-1189.7782,2.3241, 5.0);
    Checkpoint[playerid] = 2;
    }
    else if(Checkpoint[playerid] == 2)
    {
    SendClientMessage(playerid, COLOR_RED, "Muell aufgeladen, weiter!");
    GivePlayerMoney(playerid, trinkgeld);
    format(string, sizeof(string), "** Du hast %d$ Trinkgeld bekommen!",trinkgeld);
    SendClientMessage(playerid, COLOR_GREEN, string);
    DisablePlayerCheckpoint(playerid);
    SetPlayerCheckpoint(playerid, -63.3734,-1588.5732,3.1782, 5.0);
    Checkpoint[playerid] = 3;
    }
    else if(Checkpoint[playerid] == 3)
    {
    SendClientMessage(playerid, COLOR_RED, "Muell aufgeladen, weiter!");
    GivePlayerMoney(playerid, trinkgeld);
    format(string, sizeof(string), "** Du hast %d$ Trinkgeld bekommen!",trinkgeld);
    SendClientMessage(playerid, COLOR_GREEN, string);
    DisablePlayerCheckpoint(playerid);
    SetPlayerCheckpoint(playerid, 220.8943,-1393.5308,52.1264, 5.0);
    Checkpoint[playerid] = 4;
    }
    else if(Checkpoint[playerid] == 4)
    {
    ...
    }



    Ich zeig euch mal wie Ich es besser machen würde.Gibt wahrscheinlich noch andere Varianten,aber so hab ich
    es für mich persöhnlich eingepräkt.
    Als erstes einmal hab ich mir alle Checkpoint Koordinaten aus dem Script rausgeschrieben:


    Wunderbar oder nicht?
    Für sowas erstelle ich immer ein enum,ist mit dem Array vergleichbar nur besser :].
    Man kann verschiedene Typen haben und direkt über einen Namen auf den Index zugreifen (Hoffe ich hab das jetzt nicht völlig falsch erklärt.DMA kann ja sein Wissen hier zur schau stellen :P)
    Nun gut,das enum brauch X,Y,Z und die Größe des Checkpoints als Float Daten,deshalb sieht es bei mir so aus:

    enum e_Muell {
    Float:M_fX,
    Float:M_fY,
    Float:M_fZ,
    Float:M_fRad
    }

    Ich kennzeichnen ein enum immer mit e_ vor dem eigentlichen Namen.
    Float:M_fX,
    M_ = steht bei mir für e_Müll,um zu wissen von welchem enum und um verwechselungen auzuschließen falls ein Variablenname doppelt vergeben wird.
    f = steht bei mir für Float,um zu wissen welcher Typ es ist
    Jetzt müssen wir das enum noch mit Daten füllen,wieso also nicht mit den Checkpoints die wir aufgeschrieben haben.
    Das ganze sieht dann also so aus:

    enum e_Muell {
    Float:M_fX,
    Float:M_fY,
    Float:M_fZ,
    Float:M_fRad
    }


    new
    Muellabfuhr_Stationen[][e_Muell] = {
    {-74.2252, -1128.7936, 1.6359, 5.0},
    {-89.2432, -1189.7782, 2.3241, 5.0},
    {-63.3734, -1588.5732, 3.1782, 5.0},
    {220.8943, -1393.5308, 52.1264, 5.0},
    {169.0361, -1356.8065, 69.8208, 5.0},
    {263.5524, -1341.0842, 53.7643, 5.0},
    {871.9646, -864.5255, 77.2742, 5.0},
    {935.7687, -835.7352, 94.4455, 5.0},
    {1496.5879, -698.0237, 94.5207, 5.0},
    {1001.1724, -935.0218, 41.9509, 5.0},
    {-546.9002, -488.6077, 25.2961, 5.0}
    };

    Jetzt brauchen wir noch Variablen die Speichern, ob der Spieler gerade der Muellfahrer ist und
    bei welchem Checkpoint er sich zur Zeit befindet.



    enum e_PlayerMuellInfo {
    bool:pmi_bAktiv,
    pmi_Checkpoint
    }
    new Muellmann[MAX_PLAYERS][e_PlayerMuellInfo];


    Gut,den Grundstein haben wir jetzt gelegt.Jetzt folgt der eigentliche Code.
    Zuerst brauchen wir einen Start,ich nehme einen Command.



    public OnPlayerCommandText(playerid, cmdtext[]) {
    if (strcmp("/starten", cmdtext, true, 8) == 0) {
    if(!Muellmann[playerid][pmi_bAktiv]) {
    new
    vehicleid = GetPlayerVehicleID(playerid),
    model = GetVehicleModel(vehicleid);
    if(model == 408) { // Text ab hier!
    Muellmann[playerid][pmi_Checkpoint]=0;
    Muellmann[playerid][pmi_bAktiv]=true;
    SendClientMessage(playerid, COLOR_LIGHTGREEN, "Muellabfuhr gestartet, fahre nun zu den einzelnen Haeusern!");
    SetPlayerCheckpoint(playerid,Muellabfuhr_Stationen[0][M_fX],Muellabfuhr_Stationen[0][M_fY],Muellabfuhr_Stationen[0][M_fZ],Muellabfuhr_Stationen[0][M_fRad]);
    }
    else {
    SendClientMessage(playerid, COLOR_RED, "Du bist nicht im Muellwagen!");
    }
    }
    else {
    SendClientMessage(playerid, COLOR_RED, "Es laeuft schon eine Mission!");
    }
    return 1;
    }
    return 0;
    }

    Zuerst müssen wir den aktuellen Checkpoint des Spielers auf 0 setzten,denn man startet ja ganz von vorne und nicht irgendwo
    Anders (pmi_Checkpoint).Danach wird die Variable auf true / 1 gesetzt,die sagt ob ein Spieler gerade Muellmann ist (pmi_bAktiv) .
    Die Nachricht danach ist eher unwichtig.Doch danach wird es wieder interessant.
    Wir setzten den Checkpoint des Spielers.
    Der Checkpoint wird für den Spieler auf die Koordinaten gesetzt des ersten Eintrages (Ist allerdings der Index 0,deshalb [0] im Muellabfuhr_Stationen Enum )
    Muellabfuhr_Stationen[0][M_fX],Muellabfuhr_Stationen[0][M_fY],Muellabfuhr_Stationen[0][M_fZ],Muellabfuhr_Stationen[0][M_fRad]


    Jetzt haben wir den ersten Checkpoint.Doch wie geht es weiter?Bewegen wir uns nun zum OnPlayerEnterCheckpoint() Callback.
    Der bisherige Code sieht übrigens so aus:

    #include <a_samp>


    #define COLOR_LIGHTGREEN 0x86FF59FF
    #define COLOR_RED 0xFF0000FF
    #define COLOR_GREEN 0x00CA00FF


    enum e_PlayerMuellInfo {
    bool:pmi_bAktiv,
    pmi_Checkpoint
    }
    new Muellmann[MAX_PLAYERS][e_PlayerMuellInfo];


    enum e_Muell {
    Float:M_fX,
    Float:M_fY,
    Float:M_fZ,
    Float:M_fRad
    }


    new
    Muellabfuhr_Stationen[][e_Muell] = {
    {-74.2252, -1128.7936, 1.6359, 6.0},
    {-89.2432, -1189.7782, 2.3241, 6.0},
    {-63.3734, -1588.5732, 3.1782, 6.0},
    {220.8943, -1393.5308, 52.1264, 6.0},
    {169.0361, -1356.8065, 69.8208, 6.0},
    {263.5524, -1341.0842, 53.7643, 6.0},
    {871.9646, -864.5255, 77.2742, 6.0},
    {935.7687, -835.7352, 94.4455, 6.0},
    {1496.5879, -698.0237, 94.5207, 6.0},
    {1001.1724, -935.0218, 41.9509, 6.0},
    {-546.9002, -488.6077, 25.2961, 6.0}
    };



    public OnFilterScriptInit()
    {
    print("-] Tutorial - Checkpoints abfahren [-");
    CreateVehicle(408,-535.8450,-502.6665,26.0667,358.0911,1,1,-1);
    return 1;
    }


    public OnPlayerCommandText(playerid, cmdtext[]) {
    if (strcmp("/starten", cmdtext, true, 8) == 0) {
    if(!Muellmann[playerid][pmi_bAktiv]) {
    new
    vehicleid = GetPlayerVehicleID(playerid),
    model = GetVehicleModel(vehicleid);
    if(model == 408) {
    Muellmann[playerid][pmi_Checkpoint]=0;
    Muellmann[playerid][pmi_bAktiv]=true;
    SendClientMessage(playerid, COLOR_LIGHTGREEN, "Muellabfuhr gestartet, fahre nun zu den einzelnen Haeusern!");
    SetPlayerCheckpoint(playerid,Muellabfuhr_Stationen[0][M_fX],Muellabfuhr_Stationen[0][M_fY],Muellabfuhr_Stationen[0][M_fZ],Muellabfuhr_Stationen[0][M_fRad]);
    }
    else {
    SendClientMessage(playerid, COLOR_RED, "Du bist nicht im Muellwagen!");
    }
    }
    else {
    SendClientMessage(playerid, COLOR_RED, "Es laeuft schon eine Mission!");
    }
    return 1;
    }
    return 0;
    }
    public OnPlayerEnterCheckpoint(playerid) {
    // Hier haben wir noch nix eingefügt vom Tutorial,das kommt erst ;)
    return 1;
    }


    Jetzt sollten wir als erstes einen Check einfügen in OnPlayerEnterCheckpoint,der überprüft ob wir einen Muellmann haben
    der durch den Checkpoint gelaufen/gefahren ist.Dafür haben wir ja unsere Variable pmi_bAktiv.

    public OnPlayerEnterCheckpoint(playerid) {
    if(Muellmann[playerid][pmi_bAktiv]) {
    }
    return 1;
    }

    Wunderbar!
    Jetzt kann es direkt weiter gehen.Wir wissen jetzt,dass der Spieler durch einen Checkpoint gelaufen ist und Müllmann ist.
    Er hat also einen Checkpoint betreten,von daher müssen wir seine Variable erhöhen die weiss bei welchem Checkpoint er sich befindet,dafür nehmen wir :
    Muellmann[playerid][pmi_Checkpoint]++;
    Außerdem müssen wir den aktuellen Checkpoint verschwinden lassen,das machen wir mit Hilfe der Funktion DisablePlayerCheckpoint().



    public OnPlayerEnterCheckpoint(playerid) {
    if(Muellmann[playerid][pmi_bAktiv]) {
    Muellmann[playerid][pmi_Checkpoint]++; // ++ ist das gleiche wie +1
    DisablePlayerCheckpoint(playerid);
    }
    return 1;
    }


    Doch jetzt passiert nix beim durchfahren einen Checkpoints außer,dass der Checkpoint verschwindet durch den man gefahren ist.Aber noch wird kein neuer herbei gezaubert.Jetzt brauchen wir den Wert der sich hinter Muellmann[playerid][pmi_Checkpoint] verbirgt und den Vorteil ausmacht hinter dieser Variante des Scripts.
    Um das ganze jetzt leichter für die meisten darzustellen,benutzte ich eine Hilfsvariable,die den Wert enthält des Checkpoints den der Spieler erreicht hat.

    new playercp = Muellmann[playerid][pmi_Checkpoint];

    Jetzt brauchen wir nur noch bei SetPlayerCheckpoint();anstatt wie vorher bei /starten als Index nicht 0 nehmen ,sondern playercp.
    Denn wir brauchen ja den nächsten Eintrag aus den Muellabfuhr_Stationen.



    public OnPlayerEnterCheckpoint(playerid) {
    if(Muellmann[playerid][pmi_bAktiv]) {
    Muellmann[playerid][pmi_Checkpoint]++;
    DisablePlayerCheckpoint(playerid);
    new
    playercp = Muellmann[playerid][pmi_Checkpoint];
    SetPlayerCheckpoint(playerid,Muellabfuhr_Stationen[playercp][M_fX],Muellabfuhr_Stationen[playercp][M_fY],Muellabfuhr_Stationen[playercp][M_fZ],Muellabfuhr_Stationen[playercp][M_fRad]);
    return 1;
    }
    return 1;
    }


    Dieser kleine Code macht schon die meiste Arbeit,die wie im Beispiel oben durch 100 von Zeilen gemacht wird.
    Das einzige was noch fehlt,ist zu prüfen ob der Spieler den letzten Checkpoint erreicht hat.
    Das sollte aber kein Problem sein für jemand den die Grundlagen beherrscht.


    public OnPlayerEnterCheckpoint(playerid) {
    if(Muellmann[playerid][pmi_bAktiv]) {
    Muellmann[playerid][pmi_Checkpoint]++;
    DisablePlayerCheckpoint(playerid);
    new
    playercp = Muellmann[playerid][pmi_Checkpoint];
    if(playercp == sizeof(Muellabfuhr_Stationen)) {
    Muellmann[playerid][pmi_bAktiv]=false;
    }
    else {
    SetPlayerCheckpoint(playerid,Muellabfuhr_Stationen[playercp][M_fX],Muellabfuhr_Stationen[playercp][M_fY],Muellabfuhr_Stationen[playercp][M_fZ],Muellabfuhr_Stationen[playercp][M_fRad]);
    }
    return 1;
    }
    return 1;
    }
    Wenn also der Spieler den Checkpoint erreicht,der gleich dem Wert der Größe bzw der Anzahl von Checkpoints von Muellabfuhr_Stationen ist,wissen wir,dass der
    letzte Checkpoint erreicht ist.Ist der letzte Checkpoint erreicht,können / sollten und brauchen wir keinen neuen Checkpoint setzten.
    Wir müssen nur noch die Variable auf false / 0 setzten,die darüber Info gibt ob der Spieler Muellmann ist.


    Jetzt fehlt nur noch ein feinschliff mit Fahrzeug-Check,Sound,Geld,usw. ,denn die ganze Arbeit ist mit dem winzigem Code bereits getan.
    Natürlich sollte man noch einen Check einfügen der prüft,ob der Spieler sich immernoch in einem Müllwagen befindet.Doch soviel Eigeninziative sollte wohl noch vorhanden sein.
    public OnPlayerEnterCheckpoint(playerid) {
    if(Muellmann[playerid][pmi_bAktiv]) {
    Muellmann[playerid][pmi_Checkpoint]++;
    DisablePlayerCheckpoint(playerid);
    new
    playercp = Muellmann[playerid][pmi_Checkpoint];
    if(playercp == sizeof(Muellabfuhr_Stationen)) {
    Muellmann[playerid][pmi_bAktiv]=false;
    // Extra code
    SendClientMessage(playerid, COLOR_GREEN, "Super Arbeit,du hast die Stadt hervorragend gesäubert");
    GivePlayerMoney(playerid, 2000);
    }
    else {
    new
    String[128];
    PlayerPlaySound(playerid,1056,0.0,0.0,0.0);
    format(String,sizeof(String),"Weiter so,du hast es fasst geschafft ! (%d / %d)",playercp,sizeof(Muellabfuhr_Stationen));
    SendClientMessage(playerid,COLOR_LIGHTGREEN,String);
    SetPlayerCheckpoint(playerid,Muellabfuhr_Stationen[playercp][M_fX],Muellabfuhr_Stationen[playercp][M_fY],Muellabfuhr_Stationen[playercp][M_fZ],Muellabfuhr_Stationen[playercp][M_fRad]);
    }
    return 1;
    }
    return 1;
    }
    Wer trotzdem bei der Anderen Methode bleiben möchte,nur zu.


    Abschließen lässt sich nicht viel sagen,
    Hab das Tutorial jetzt fix herrunter geschrieben ohne großartig auf Wortwahl usw. zu achten.Sollte etwas unverständlich sein oder Fehler enthalten (Was natürlich möglich ist) könnt ihr das gerne posten.


    //Edit 27-03-2015: Download entfernt (Code ist weg :[ )

    So wie in dem Beispiel Code von [ S]WhiteJoker sollte niemand ein Script zum Routen abfahren / Rennen erstellen (Ob nun Rennen oder irgendwelche Routen abfahren,ist ja das Gleiche).
    Ich hab das Script vor langer Zeit mal verbessert damit man nun viel viel vieeeel einfacher die Route abändern kann Müllabfuhr - Script

    Ich bin mir nicht mehr ganz sicher,aber ich glaube dieser Kram tritt auf wenn man durch 0 teilt,was mathematisch ja nicht möglich ist.Kann auch sein das es auftrat wenn man float als Integer oder String anzeigen ließ.Glaub aber eher es hatte was mit dem durch 0 teilen zutun.

    public JetPackCheck()
    {
    for(new i = 0;i < MAX_PLAYERS;i++) { // Hier war derFehler
    if(IsPlayerConnected(i)) {
    if (GetPlayerSpecialAction(i) == SPECIAL_ACTION_USEJETPACK) {
    Kick(i);
    }
    }
    }
    return 1;
    }