Beiträge von IPrototypeI

    Mach mir mal bitte ein Beispiel was du damit meinst. Komme gerade nicht mit deinem Satz klar.




    stock CreateHaus(Float:x,Float:y,Float:z,Float:xi,Float:yi,Float:zi,preis,level,int,rooms)
    {
    new i;
    for(;i != MAX_HAUS; ++i)if(HausInfo[i][haus_id] == 0)break;
    if(i == (MAX_HAUS-1))return 1;
    new query[500];
    format(query, 500, "INSERT INTO `haus` (`Besitzer`, `Preis`, `X`, `Y`, `Z`, `XI`, `YI`, `ZI`, `Level`, `Rooms`, `Interior`, `Lock`, `Hausid`) VALUES ('Niemand', '%i', '%f', '%f', '%f', '%f', '%f', '%f', '%i', '%i', '%i', '1', 0)", preis,x,y,z,xi,yi,zi,level,rooms,int);
    mysql_query(query);
    return LoadHaus(i,mysql_insert_id());
    }
    stock LoadHaus(hausid,lastinsert){
    new query[400];
    format(query,64,"SELECT * FROM `haus` WHERE `Hausid` == %d;",lastinsert);
    HausInfo[hausid][haus_vw] = lastinsert;
    mysql_query(query);
    mysql_store_result();
    mysql_fetch_row_format(query);
    sscanf(query, .....
    return mysql_free_result(query);


    }




    Also ich würde das ganze in Abhängigkeit von deiner Vorgehensweise so machen.



    Persönlich nochmal ganz anders die ganzen Häuser erst laden wenn der Server hochfährt und beim erstellen ingame erst der datenbank hinzufügen und aus den restlichen Standartwerten das direkt ohne erneut zu laden erstellen, jedoch benötigt man dennoch dafür die id des datensatzes hier hausid


    hausid ist schon ein argument deiner Funktion LoadHaus
    sprich:



    stock LoadHaus(hausid)

    So kann man dir nicht wirklich helfen, dazu poste doch mal deine Funktion LoadHaus.


    Aber so nebenbei die logik deines Codes muss man nicht wirklich verstehen ?


    Die wird in dem fall immer 1 sein in der Datenbank es sei den du hast hausid auf AUTO_INCREMENT gestellt.


    Zu dem so wie du die Schleife nutzt ist das eher eine Zweckentfremdung, da du diese gleich abbrichst.


    Ich vermute jedoch eher das dein Fehler wie schon oben angemerkt bei "LoadHaus" befindet.


    Ja klar deine funktion kannst du auch nutzen nur solltest du halt schauen das du nicht über 2000 Fahrzeuge kommst :D weil mehr kannst du ohne einen streamer nicht erstellen

    for(new i; i != MAX_VEHICLES; ++i){
    format(fahrzeugdatei, sizeof(fahrzeugdatei), "/Cars/%i.ini", i);
    if(dini_Exists(fahrzeugdatei))continue;

    printf("Freier Slot id %d",i);
    return 1;


    }


    Dein Code funktioniert so nicht der müsste eigentlich sofort abbrechen aufgrund des < Operators. dini_Exists gibt 0 beziehungsweise 1 zurück.
    1 fürexistiert schon und 0 für existiert nicht.


    carid benötigst du nicht extra für was hast du deine schleife.
    ich hab dir mal oben die schleife richtig gestellt MAX_VEHICLES ist das Limit für die Fahrzeuge die du erstellen kannst.
    sollte die datei existieren so wird mit continue direkt der nächste durchlauf eingeleitet anstatt den Anweisungsblock weiter durchzugehen.
    Sollte der wert nicht existieren wird dir die id ausgegeben in der Serverlog und die funktion mit dem return 1; abgebrochen an dem Punkt.


    Gute Anmerkung! Habe extra eine Passage zum Semikolon hinzugefügt und die Queries um je ein Semikolon erweitert.


    Okay gut, sonst zum Tutorial ist es gut gelungen und ich hoffe mal es wird einigen Leuten helfen, wenn du willst kannst ja noch ein zweiten Teil rausbringen über die Nutzung von SQL-Befehlen.

    Jetzt könnte man noch daran appelieren, dass du jeweils das Semikolon vergessen hast bei den einzelnen Beispielen , welche auch seine ordnung hat und zwar signalisiert dies MySQL das der eingegebene SQL Befehl beendet ist und nachfolgende Befehle haben keine direkte Einwirkung auf den abgeschlossenen Befehl sondern werden nachfolgend abgeschickt

    oh auf das erste return hatte ich garnicht geachtet


    also so


    PHP
    stock PlayerActionForbidden(playerid)
    {
    	if(IsPlayerAFK[playerid])  SendLanguageMessage(playerid, COLOR_RED, "[WARNUNG] Du bist AFK. Du kannst keine Aktion durchführen. Melde dich mit /back zurück!", "[WARNING] You are AFK. You can't take any action. Use /back to come back!"), return 1;
     	if(IsPlayerInDM[playerid]) SendLanguageMessage(playerid, COLOR_RED, "[WARNUNG] Du bist schon im DM! Benutze /cancel um das DM zu verlassen!", "[WARNING] You are already in a DM! Use /cancel to exit the DM!"), return 1;
    	if(!UseTeleports[playerid]) SendLanguageMessage(playerid, COLOR_RED, "[WARNUNG] Du kannst im Moment keine Teleports nutzen! (Kampf/Skin Selection/DM-Arena)", "[WARNING] Currently, you can't use teleports! (Fight/Skin Selection/DM-Arena)"), return 1;
    	return 0;
    }


    das was du davor gepostet hast war nicht falsch ^^
    Du hast das lediglich nur rum gedreht mal so als kleiner Tipp zu return



    return SendLanguageMessage(playerid, COLOR_RED, "[WARNUNG] Du kannst im Moment keine Teleports nutzen! (Kampf/Skin Selection/DM-Arena)", "[WARNING] Currently, you can't use teleports! (Fight/Skin Selection/DM-Arena)"),1;


    könntest du hier auch machen da der letzte wert zurück gegeben wird . SendClientMessage gibt den wert 1 zurück und dieser funktion SendLanguageMessage auch daher bräuchte man dein return 1 oder
    die vereinfachte form von mir nicht und kann somit auch return SendLanguageMessage(playerid, COLOR_RED, "[WARNUNG] Du kannst im Moment keine Teleports nutzen! (Kampf/Skin Selection/DM-Arena)", "[WARNING] Currently, you can't use teleports! (Fight/Skin Selection/DM-Arena)"); nutzen

    Ich kapier das iwie nicht. Bei meinem Waffen befehl, also auch im /sell muss man ja andere sachen angeben:
    if(strcmp(name,"waffe",true) == 0)
    {
    if(sscanf(params,"usi",pID,weapon_name,price))


    Dann würde das so funktionieren ohne sich noch auf weitere abfragen zu beziehen


    if(!strcmp(cmdtext,"/sell",true,5)){
    new befehl[10],id, weaponname[20],preis;
    if(sscanf(cmdtext,"{s[6]}s[10]i",befehl,id) && sscanf(cmdtext,"{s[6]}s[10]s[20]ud",befehl,weaponname,id,preis))return SendClientMessage(playerid,-1,"....");
    if(!strcmp(befehl,"fish",true))return printf("so viele Fische %d",id),1;
    else if(!strcmp(befehl,"waffen",true))return printf("Waffe %s an id %d und preis %d",weaponname,id,preis),1;
    else return SendClientMessage(playerid,-1,"....");
    }


    du kannst mir auch mal dein ganzen befehl posten und ich kann dir den umschreiben + erklärungen auf der seite oder dir das ganze auch erklären jedoch müsste ich wissen wo es bei dir hengt.
    Es gibt bei sscanf noch weitere möglichkeiten du benutzt doch wahrscheinlich das sscanf plugin da du auch deine eigenen specifer erstellen kannst.

    Weil auch immer 1 zurück gegeben wird


    stock PlayerActionForbidden(playerid)
    {
    if(IsPlayerAFK[playerid]) return SendLanguageMessage(playerid, COLOR_RED, "[WARNUNG] Du bist AFK. Du kannst keine Aktion durchführen. Melde dich mit /back zurück!", "[WARNING] You are AFK. You can't take any action. Use /back to come back!");
    if(IsPlayerInDM[playerid]) return SendLanguageMessage(playerid, COLOR_RED, "[WARNUNG] Du bist schon im DM! Benutze /cancel um das DM zu verlassen!", "[WARNING] You are already in a DM! Use /cancel to exit the DM!");
    if(!UseTeleports[playerid]) return SendLanguageMessage(playerid, COLOR_RED, "[WARNUNG] Du kannst im Moment keine Teleports nutzen! (Kampf/Skin Selection/DM-Arena)", "[WARNING] Currently, you can't use teleports! (Fight/Skin Selection/DM-Arena)");
    return 0;
    }


    sollte SendLanguageMessage 1 zurück geben dann sollte alles funktionieren

    Ja Befindet er sich ^^ werde erstmal das erste probieren dann die zweite variante.


    /edit: kein bock mehr auf sscanf mache es jetzt wie ich es sonst mache! mit strtok


    Also so funktioniert es ohne probleme



    if(!strcmp(cmdtext,"/sell",true,5)){
    new befehl[10],id;
    if(sscanf(cmdtext,"{s[6]}s[10]i",befehl,id))return SendClientMessage(playerid,-1,"....");
    if(!strcmp(befehl,"fish",true))return printf("so viele Fische %d",id),1;
    else if(!strcmp(befehl,"waffen",true))return printf("so viele Waffen %d",id),1;
    else return SendClientMessage(playerid,-1,"....");
    }

    du hast dazu paar möglichkeiten
    die erste wäre hier den befehl zu überspringen
    new befehl[10],id;
    if(sscanf(cmdtext,"{s[6]}s[10]i",befehl,id))return SendClientMessage(playerid,-1,"....");


    oder du kannst auch den befehl von dem gesamt string entfernen


    strdel(cmdtext,0,strfind(cmdtext,"\32;",false)+1);


    somit könntest du den code von .Makaveli nutzen


    //edit mal so eine Frage der code befindet sich schon unter OnPlayerCommandText den du gepostet hast


    Du hast ja schon die Fahrzeugid daher musst du sie nicht auslesen und vor allem nicht mit GetPlayerVehicleID da das erste argument der spieler ist somit würdest du ein ganz falsches auto ausschalten.




    public BenzinVerlust(){
    for(new i; i<MAX_VEHICLES; i++) {
    if (!Motor[i])continue;
    if (--Tank[i] < 1) {
    Motor[i] = false;
    GetVehicleParamsEx(i,engine,lights,alarm,doors,bonnet,boot,objective);
    SetVehicleParamsEx(i,VEHICLE_PARAMS_OFF,lights,alarm,doors,bonnet,boot,objective);
    }
    }
    return 1;
    }


    Danach solltest du noch deine formatierung des strings Tank umändern von


    format(Tank, 10,"Tank: %d",100);
    zu
    format(Tank, 10,"Tank: %d",Tank[veh]);


    strlen würde nicht funktioninieren.


    Ob ich nämlich in der zweiten Spalte "iiiiiiii" oder "MMMMMMMM" habe, macht einen großen Unterschied.


    Ich hab dir mal solch eine funktion geschrieben


    stock ConvertDialogString(string[]){
    new Count[2];
    for(new i,x; ; ++i){
    switch(string[i]){
    case '\n':{
    printf("%d",(i - x));
    if((i - x) > Count[0])Count[0] = (i - x);
    x = i;
    } case EOS:{
    if((i - x) > Count[0])Count[0] = (i - x);
    break;
    }
    }
    }
    for(new i,x=-1; ; ++i){
    switch(string[i]){
    case ' ' :Count[1]= i;
    case '\n':{
    if((i - x) < Count[0])for(; 0 != (Count[0] - (i - x)); ++i)strins(string,"\32;",Count[1],1);
    x = i;
    } case EOS:{
    if((i - x) < Count[0])for(; 0 != (Count[0] - (i - x)); ++i)strins(string,"\32;",Count[1],1);
    break;
    }
    }
    }
    return 1;
    }





    new string[200]="1. Dennis 12.01.1992\n2. Hansmeierdieter 12.01.1992\n3. Gottlob 12.01.1992";
    ConvertDialogString(string);
    printf(string);


    //edit


    Das wäre ein kleine kopie von deinem dialog vom Aufbau her



    new string[200]="ID Name Datum\n1. Dennis 12.01.1992\n2. Hansmeierdieter 12.01.1992\n3. Gottlob 12.01.1992\n4. Wal 12.01.1992";
    ConvertDialogString(string);
    new x = strfind(string,"Datum",false);
    strdel(string,x-5,x);
    printf(string);

    mysql_tquery kannst du zeug updaten insert etc.
    Das geht beim andern eig auch aber das macht sich behilflich beim laden, dabei wird ein public aufgerufen.



    Das ist bei mysql_function_query auch so
    #define mysql_function_query(%0,%1,%2,%3,"%4"%5) mysql_tquery(%0,%1,%3,#%4%5)


    Das t steht hier nur nochmal extra für threaded query nur mysql_query an sich sendet none threaded querys,


    http://wiki.sa-mp.com/wiki/MySQL/R33#mysql_query


    Nur hatte ich im Bezug auf meine vorherige Antwort entweder etwas überlesen oder es hat sich geändert seit dem letzten blick in das wiki.



    Am besten erstellst du den Timer in dem Callback, zu dem ist es besser mysql_tquery zu verwenden somit gehst du auch über Threaded Querys.
    Ich weiß ja nicht was du schon davor absendest jedoch wartet dein Server nicht darauf bis dein query verarbeitet ist.



    if(rows)
    {
    ServerStuff[AutomaticUserSaveTimer]=cache_get_field_content_int(0,"SaveAllUserTimer",sqlconnection);
    print("Serverstuff loaded");
    printf("Savetimer auf %d ms",ServerStuff[0][AutomaticUserSaveTimer]);
    SetTimer("Name",ServerStuff[AutomaticUserSaveTimer],true);
    }