Beiträge von Double-O-Seven

    Meine Güte, schon soviele Posts und überall nur Blödsinn?
    Wie schwer kann es sein, denn Error zu lesen und die entsprechende Zeile dann anzuschauen.
    Das Problem liegt bei GetPlayerHealth.
    Korrekt:
    showmedicdia(playerid)
    {
    new string[1000], name[MAX_PLAYER_NAME];
    new Float:pHealth;
    for(new i; i < MAX_PLAYERS; i++)
    if(GetPVarInt(i,"MedicHelp") == 1)
    {
    GetPlayerHealth(i, pHealth);// Jetzt ist es korrekt...
    GetPlayerName(i,name,sizeof(name));
    // Und hier beachten, dass pHealth ein Float ist -> Runden (floatround)
    format(string,sizeof(string),"%s\n%s (ID %d): %d HP",string,name,i,floatround(pHealth));
    }
    ShowPlayerDialog(playerid,diaMedic,DIALOG_STYLE_LIST,"Eingegangene Notrufe",string,"OK","Abbrechen");
    }


    // EDiT: An Andre_R's Post oben:
    Ebenfalls nicht korrekt, denn GetPlayerHealth gibt NICHT Health zurück, dass gibt höchstens n Nonsense zurück.

    #define ALT_COMMAND:%0<%1>(%2,%3[]) \
    COMMAND:%0(%2,%3[]) { return cmd_%1(%2,%3); } \
    COMMAND:%1(%2,%3[])


    So anwenden:
    ALT_COMMAND:test<t>(playerid, params[])
    {
    // Code
    return 1;
    }

    Double-O-Users


    Was ist Double-O-Users?
    Double-O-Users ist ein Accountsystem, welches alle Benutzerdaten automatisch speichert.
    Der Scripter, der dies verwendet muss lediglich einen Login- und Registercommand scripten und die gegebene Loginfunktion anwenden und dann kann er ganz normal PVars benutzen mit einem kleinen Unterschied:
    PVar muss mit UVar ersetzt werden.
    Das heisst, man kann UVars FAST GENAU gleich wie PVars anwenden, jedoch werden diese AUTOMATISCH gespeichert!



    Funktionen
    native RegisterUser(playerid, password[]);
    native CheckUserLogin(playerid, password[]);
    native LoginUser(playerid);
    native StoreUserData(playerid);
    native IsUserRegistered(playerid);
    native IsUserLoggedIn(playerid);
    native SetUserPassword(playerid, password[]);
    native SetAutoLogin(playerid, bool:autologin);
    native SetUVarInt(playerid, uvar[], value);
    native UpdateUVarInt(playerid, uvar[], value);
    native GetUVarInt(playerid, uvar[]);
    native SetUVarFloat(playerid, uvar[], Float:value);
    native UpdateUVarFloat(playerid, uvar[], Float:value);
    native Float:GetUVarFloat(playerid, uvar[]);
    native SetUVarString(playerid, uvar[], string[]);
    native GetUVarString(playerid, uvar[], string[], len = sizeof string);
    native DeleteUVar(playerid, uvar[]);


    Die Funktionsnamen sollten selbsterklärend sein.
    Und wie gesagt, kann man UVars genauso wie PVars anwenden, wobei diese NICHT einfach so untereinander kompatibel sind.


    Beispiel:
    #include <a_samp>
    #include <zcmd>
    #define USER_ACCOUNT_PATH "%s.ini" // Anpassen bitte, für Benutzerdatei.
    #include <Double-O-Users>


    COMMAND:register(playerid, params[])
    {
    if (IsUserRegistered(playerid))
    {
    SendClientMessage(playerid, 0xFF0000FF, "Du bist schon registriert!");
    return 1;
    }

    if (RegisterUser(playerid, params))
    SendClientMessage(playerid, 0x00AA00FF, "Du hast Dich erfolgreich registriert!");
    else
    SendClientMessage(playerid, 0xFF0000FF, "Registrierung fehlgeschlagen!");
    return 1;
    }


    COMMAND:login(playerid, params[])
    {
    if (!IsUserRegistered(playerid))
    {
    SendClientMessage(playerid, 0xFF0000FF, "Bitte registriere Dich zuerst mit /register <Passwort>!");
    return 1;
    }

    if (!CheckUserLogin(playerid, params))
    SendClientMessage(playerid, 0xFF0000FF, "Falsches Passwort!");
    else
    {
    LoginUser(playerid);
    SendClientMessage(playerid, 0x00AA00FF, "Willkommen zurück!");
    }
    return 1;
    }


    public OnPlayerRequestSpawn(playerid)
    {
    // Zwinge Spieler, sich erst einzuloggen!
    if (IsUserRegistered(playerid) && !IsUserLoggedIn(playerid))
    {
    SendClientMessage(playerid, 0xFF0000FF, "Bitte logge Dich ein mit /login <Passwort>!");
    return 0;
    }
    return 0;
    }


    public OnPlayerDeath(playerid, killerid, reason)
    {
    UpdateUVarInt(playerid, "Deaths", 1); // + 1
    if (killerid != INVALID_PLAYER_ID)
    UpdateUvarInt(playerid, "Kills", 1); // + 1
    return 1;
    }
    Das obige Script ist grundsätzlich schon fertig. Jetzt kann man einfach noch weitere UVars hinzufügen.


    Download
    Double-O-Users (Pastebin)
    Double-O-Files 2, notwendig (Pastebin)

    Mir ist gerade eine Idee gekommen.
    Vor kurzem habe ich im Codeschnipsel-Thread folgendes gepostet:
    http://pastebin.com/wz9UMyqY


    Du verwendest ja für jede Variable die gleiche enum-Struktur.
    Zum Abspeichern eines Floats oder eine Integer, ist dies jedoch sehr ineffizient, da du IMMER 512 Bytes für die Strings verwendest.


    Wenn du nun die Pointerfunktionen von oben benutzen würdest, könntest einfach den Pointer und den Typ übergeben.
    Mit dem Pointer könntest du auch beliebig Lange Strings übergeben.

    Es gibt da einen Bug, der in den meisten Fällen nicht kritisch sein wird.
    Dennoch:
    Du verwendest dreimal
    for(new i = 0;i<sizeof(VarTree[]);i++)
    Was du ja eigentlich willst, ist die Anzahl solcher Einträge:
    enum pVariables_Save
    {
    var_name[MAX_VAR_NAME],
    var_type,
    def_val_str[128],
    def_val_int,
    Float:def_val_float
    };


    Was du aber in Wahrheit mit sizeof(VarTree[]) abfragst, ist die Grösse EINES EINZIGEN solchen Eintrages.
    Und dies ist standardmässig MAX_VAR_NAME + 1 + 128 + 1 + 1.
    Übergibt man also irgendeinmal eine Array, der grösser ist als diese Summe, wird das ganze wohl abschmieren oder sonst irgendetwas passiert.


    Du hast also sizeof(VarTree[]), was du aber ja willst, ist sizeof(VarTree) was dann wirklich die Länge dieses Arrays zurückgeben WÜRDE, FALLS diese Länge schon bekannt wäre.
    Da du dem Callback aber nur VarTree[][pVariables_Save] übergibst, ohne Angabe der Länge, wird das dann einen Error geben, da du in diesem Fall sizeof(...) garnicht anwenden kannst.
    Du musst dem Callback also noch ein zusätzliches Argument für die entsprechende Länge von VarTree übergeben.


    PS.: Wieso VarTree? Ein normaler Array wie bei dir ist höchstens ein zu einer linearen Liste degenerierter Baum^^

    Falsch. Dies sind keine Bots. Hier wurde die Objekte zusammen gesetzt, welche erscheinen, wenn man im Singleplayer-Modus (UNCUT) mit dem Mähdrescher Fussgänger erntet.
    Dann noch Kameraposition rausfinden und berechnen, ob eine Spieler auf einen Zombie ballert.

    Lol, ich habe gerade was ähnliches in den Startlöchern :o


    Wenn ich das richtig sehe, übergibst du einfach bei OnPlayerConnect einen Array des gegeben Formats und lädst das ganze?
    Und bei OnPlayerDisconnect speicherst du es ab?


    Habe einen Schönheitsfehler entdeckt :x
    Es sollte DoesPlayerAccExist heissen.


    Aber sonst schön.^^

    Und das kann ich wofür verwenden?


    Wird man wohl sehr selten oder garnicht brauchen.


    Aber mit
    new TestArray[] = {1, 2, 3, 4, 5};
    new Pointer:ptr = GetPointer(TestArray);

    gilt:


    val = GetData(ptr, 2); entspricht val = TestArray[2];
    SetData(ptr, 1337, 2); entspricht TestArray[2] = 1337;

    GetPointer gibt die Addresse der Variable, welche als Argument übergeben wurde zurück.
    SetData schreibt value in die Addresse, welche im Pointer gespeichert ist.
    GetData liest den Wert aus Addresse, welche im Pointer gespeichert ist.


    stock Pointer:GetPointer(...)
    {
    #emit LOAD.S.pri 0x0C
    #emit RETN

    return Pointer:0;
    }


    stock SetData(Pointer:ptr, value, idx = 0)
    {
    #emit LOAD.S.pri idx // PRI = idx
    #emit SMUL.C 0x04 // PRI = 4 * idx
    #emit LOAD.S.alt ptr // ALT = ptr
    #emit ADD // PRI = ptr + 4 * idx
    #emit LOAD.S.alt value // ALT = value
    #emit XCHG // ALT = ptr + 4 * idx, PRI = value
    #emit STOR.I // [ptr + 4 * idx] = value ([ALT] = PRI)
    }


    stock GetData(Pointer:ptr, idx = 0)
    {
    #emit LOAD.S.pri idx // PRI = idx
    #emit SMUL.C 0x04 // PRI = 4 * idx
    #emit LOAD.S.alt ptr // ALT = ptr
    #emit ADD // PRI = ptr + 4 * idx
    #emit LOAD.I // PRI = [PRI] = [ptr + 4 * idx]
    #emit RETN

    return 0;
    }

    Mal mein erster Tipp:


    Mache mal bei OnPlayerCommandText(...) ganz oben
    LogCommand(playerid, cmdtext);
    hin.


    Hier die Funktion:
    LogCommand(playerid, cmd[])
    {
    new name[MAX_PLAYER_NAME];
    GetPlayerName(playerid, name, sizeof name);
    printf("[command] %s: %s", name, cmd);
    }


    Danach wird man sehen, was er genau eingibt, sobald wir das sehen, können wir sicher feststellen, wo das Problem liegt, wenn nicht, muss man mit härteren Mitteln eingreifen.

    NEIN, hört mal auf mit euren Klammerfehlern!!!


    Du hast irgendwo ein return; und Code danach, der wegen dem return; nicht mehr erreicht werden kann!


    Poste den Code inklusive die 10 Zeilen vor dieser Zeile und 10 Zeilen nach dieser Zeile.

    Omg und ist uns doch egal wie du es gemacht hast ich finde mann sollte es erst nach videos machen weil mann ja garnicht richtig weiß was das bringen könnte oder was mann machen könnte und dann kann mann eben selber was machen und könnte googlen wenn mann z.b dini nicht versteht und dann würde mann auch schon was schaffen alleine ohne videos oder so aber ungefähr 40% des forums als bobs zu bezeichnen finde ich einfach nur arm


    Ich kann nichts dafür wenn gleicher jeder mit einem Godfather zu scripten und sich von Anfang an gleich überfordert anstatt sich erstmal mit den Basics und Konzepten des Programmierens auseinanderzusetzen.


    Ahja, ich habe nur auf die Frage im Titel des Threads geantwortet.