Beiträge von Jeffry

    Die Berechnung ist ziemlich einfach.


    Du speicherst global den Timestamp wenn es 0 Uhr ist und du speicherst den momentanen Timestamp in die Spielerdatei wenn er den Server verlässt.
    Den globalen Timestamp solltest du für den Fall eines Server Neustarts in einer Einstellungsdatei speichern und beim Start des Servers laden.


    Beim Login berechnest du dann, wenn der Timestamp on der Spielerdatei kleiner ist als der global gespeicherte:
    tage = ((global - Datei)/86400) + 1


    Das wären die Tage, die er zahlen muss.
    Gegebenenfalls kann man auch noch eine Schleife machen, die es den Spielern die online sind direkt abzieht.


    Ich denke, die Codes dazu bekommst du hin.
    Falls Probleme auftreten, einfach nachfragen!

    Was du da vor hast ist eine ganz schlechte Idee. Willst du wirklich alle Spieler die registriert sind durchloopen?
    Stell dir mal vor wenn du 10.000 Accounts hast (und das geht schnell, ca. 1/2 Jahr bei mir, pro 10.000 Accounts). Es muss um diese Zeit dann jede Datei geöffnet werden, sprich 10.000 Dateiöffnungen, Daten auslesen, Daten schreiben und dann die Datei wieder speichern.
    Du kannst das ja testweise mal mit einer Datei testen, und diese 10.000 Mal öffnen, auslesen, beschreiben und dann wieder speichern. Dann sieh dir die Zeit an wie lange das dauert.


    Generell:
    Wenn du das machen willst, dann nutze das FileManager Plugin, damit geht es auf jeden Fall.


    Oder, und das ist die wesentlich bessere Variante für dieses Vorhaben, nutze MySQL.


    ODER, und das ist die allerbeste Variante:
    Ziehe dem Spieler das Geld ab, wenn er auf den Server kommt und sich einloggt, direkt beim einloggen.
    Wie? Du berechnest die Tage die er nicht mehr online war und ziehst ihm dann X mal den Wert ab, den er abgezogen bekommen soll.

    Ich nutze das R7 Plugin nicht, verwendet das die Cache Funktionen? Wenn nicht, dann rate ich dir dringend, auf R39-2 umzusteigen.
    Die Performance ist wesentlich besser.


    Ansonsten musst du den Code ggf. anpassen.


    Deklaration:
    #define MAX_TEXTS 100
    #define MAX_LANGS 3
    #define MAX_TLEN 145
    #define MAX_DLEN 32
    new gLanguageText[MAX_TEXTS][MAX_LANGS][MAX_TLEN]; //100 Texte in 3 Sprachen zu je maximal 145 Zeichen.
    new gDefinition[MAX_TEXTS][MAX_DLEN]; //100 Texte die jeweils eine Definition ("hello.world") zu 32 Zeichen haben.


    Laden aus Datenbank:
    OnGameModeInit:
    mysql_tquery(conHandle, "SELECT * FROM texts", "OnTexteInit", "");


    Unten im Code:
    forward OnTextsInit();
    public OnTextsInit()
    {
    new rows = cache_get_row_count();
    new str[MAX_TLEN], inserted, textID;
    for(new i = 0; i < rows; i++)
    {
    cache_get_field_content(i, "language", str);
    if(!strcmp(str, "de")) lang = 0;
    else if(!strcmp(str, "en")) lang = 1;
    else if(!strcmp(str, "es")) lang = 2;
    cache_get_field_content(i, "definition", str);
    textID = -1;
    for(new j = 0; j < inserted; j++)
    {
    if(!strcmp(gDefinition[j], str))
    {
    textID = j;
    break;
    }
    }
    if(textID == -1)
    {
    if(inserted >= MAX_TEXTS) return print("Error: Text-Limit überschritten");
    format(gDefinition[inserted], MAX_DLEN, str);
    textID = inserted;
    inserted++;
    }
    cache_get_field_content(i, "text", str);
    format(gLanguageText[textID][lang], MAX_TLEN, str);
    }
    return 1;
    }


    Textausgabe:
    Hier kannst du dir es sogar mit einem Stock zurückgeben lassen, da du ja kein Query mehr brauchst.


    stock GetLanguageText(langstr[], def[])
    {
    new str[MAX_TLEN], lang=-1, textID=-1;
    if(!strcmp(langstr, "de")) lang = 0;
    else if(!strcmp(langstr, "en")) lang = 1;
    else if(!strcmp(langstr, "es")) lang = 2;

    for(new i = 0; i < MAX_TEXTS; i++)
    {
    if(!strcmp(gDefinition[i], def) && strlen(gDefinition[i]) > 0)
    {
    textID = i;
    break;
    }
    }

    if(lang != -1 && textID != -1) format(str, sizeof(str), gLanguageText[textID][lang]);
    return str;
    }


    In der Tabelle hast du die Spalten:
    language
    definition
    text



    Beachte:
    Ich habe das ohne Compiler und ohne es ausprobieren zu können geschrieben.
    Falls Fehler auftreten, poste bzw. beschreibe diese bitte.


    Bei Fragen einfach melden.

    MYSQL R5


    Ich habe dir hier mal angefangen, für das was du beschrieben hast.


    #define MAX_FRAKTIONEN 15
    enum FrakDaten
    {
    fName[128],
    fRang1[30],
    fRang2[30],
    fRang3[30],
    fRang4[30],
    fRang5[30],
    fRang6[30],
    Float:fSpawnX,
    Float:fSpawnY,
    Float:fSpawnZ,
    fSpawnI
    };
    new FDaten[MAX_FRAKTIONEN][FrakDaten];


    ocmd:createfraktion(playerid,params[])
    {
    if(SpielerInfo[playerid][pAdminlevel] < 6) return SendClientMessage(playerid,Rot,"Möglich ab: "COLO" Adminrank 6");
    new input[128];
    if(sscanf(params,"s",input))return SendClientMessage(playerid,Rot,""COLO"Verwendung: "COLR"/createfraktion [Fraktionsname]");
    new i = GetFreeFrakID();
    if(i == -1) return SendClientMessage(playerid,Rot,"Es kann keine neue Fraktion erstellt werden. Maximum erreicht.");
    format(FDaten[i][fName], 128, input);
    GetPlayerPos(playerid, FDaten[i][fSpawnX], FDaten[i][fSpawnY], FDaten[i][fSpawnZ]);
    FDaten[i][fSpawnI] = GetPlayerInterior(playerid);
    new query[256];
    format(query, sizeof(query), "INSERT INTO fraktionen (id, fname, fx, fy, fz, fi) VALUES ('%d', '%s', '%f', '%f', '%f', %d)",
    i, FDaten[i][fName], FDaten[i][fSpawnX], FDaten[i][fSpawnY], FDaten[i][fSpawnZ], FDaten[i][fSpawnI]);
    mysql_query(query);
    return 1;
    }
    Hier darf AUTO_INCREMENT für die Spalte id nicht (!) verwendet werden, allerdings muss id den UNIQUE Key haben.


    Außerdem brauchst du natürlich:
    stock GetFreeFrakID()
    {
    for(new i=0; i<MAX_FRAKTIONEN; i++)
    {
    if(!strlen(FDaten[i][fName])) return i;
    }
    return -1;
    }


    Edit [PeL]Smiley: Habe die Tags hinzugefügt. Die SpielerInfo Variable musst du natürlich zu dem ändern wie es bei dir ist.

    Das kannst du so direkt nicht mit diesen Funktionen machen, da dir die Funktion wie gesagt keinen String zurückgibt.
    Du solltest das wie folgt machen:
    GetTextFromLanguage(language[], text[]);
    zu:
    SendPlayerLanguageMessage(playerid, color, text[]);

    Dann kannst du in dem public direkt die Nachricht ausgeben:
    mysql_function_query(MySQL, Query, true, "SendPlayerLanguageMessage", "dds", playerid, 0xFF0000FF, "Hallo Welt!");


    In der Funktion kannst du dann die entsprechende Sprache von playerid abfragen und die entsprechende Nachricht ausgeben.
    Dem Prinzip nach wie wir es in den kleinen Scripting Fragen besprochen haben, das kommt gut hin.



    Zu deinem Edit:
    Nein, du musst einen Loop durch das Array machen, den Text auf deutsch suchen und die entsprechende Sprache ausgeben.

    Ja, das wäre eine Möglichkeit. Man müsste dann eben noch einen Befehl erstellen, der bei Bedarf die Daten neu aus der Datenbank ausließt.
    Allerdings kommt es darauf an, wie viele Nachrichten man hat, denn man muss beachten, dass man ja für jede Nachricht dann Speicherplatz in Form eines Arrays reservieren muss, und das kann viel werden, allerdings denke ich, dass das kein Problem werden sollte, da keiner 1 Million Nachrichten hat.

    Ist zwar auch nicht ganz so performant wie es direkt in den Code zu schreiben, allerdings hat man die Möglichkeit die Nachrichten im laufenden Betrieb anzupassen, das kann man also durchaus so machen, da der Nutzen dem Verbrauch überwiegt.
    Das wäre für ein mehrsprachiges System sicherlich eine der besten Möglichkeiten.

    Den anderen Codes zufolge bin ich mir wie @[MRPG]AyKut zu 90% sicher, dass es daran liegt. Sowas hatte ich schon vermutet, deshalb habe ich nach dem Screenshot gefragt.
    In einem sql query ist es völlig egal, aber die Cache Funktionen sind keine Queries, deshalb kann das sehr wohl sein.


    cache_get_field_content_int(i, "id");
    Zu
    cache_get_field_content_int(i, "ID");


    CptSky_: Hab schon geschlafen. ;)

    @Azcaq: Das ist prinzipiell ja genau das gleiche, nur dass du die Texte eben in der Datenbank speicherst, was hinsichtlich Performance keine gute Idee ist, vor allem dann, wenn du viele Nachrichten auf einmal an viele Spieler sendest.


    Ich würde davon abraten das so zu machen, da es keinen Unterschied im Handling macht, wo die Texte stehen, dafür aber sehr wohl in der Performance.

    Das kann aber nicht durch diese eine Änderung passieren, daß PlayerCarConnect hat ja gar nichts mit dem kaufen des Fahrzeugs zu tun.


    Oder hast du es noch woanders geändert?
    An dem was zuvor getan hat darf sich eigentlich nichts ändern durch diese eine Änderung.


    Der Log den du gepostet hast ist ok, daran ist nichts falsch. Das Fahrzeug sollte korrekt in der Datenbank stehen.

    Kannst du mal noch einen Screenshot von der Tabelle in der Datenbank posten (Struktur und Daten)?


    Wenn sich da auch nichts findet, was auf die fehlende id Spalte hinweist, dann muss ich es mir doch mal anschauen indem ich mich draufschalte.

    Ändere das query mal von:
    format(TextString, sizeof(TextString), "SELECT * FROM `cars` WHERE `sqlid`=%i", PlayerInfo[playerid][pSQLID]);
    zu:
    format(TextString, sizeof(TextString), "SELECT * FROM `cars` WHERE `sqlid`=%i AND `carkey`=%d", PlayerInfo[playerid][pSQLID], h);



    Was steht dann im Log?

    @Mew:
    Nein, nicht wirklich.


    Du könntest höchstens jeder Nachricht eine ID geben, und dann eine Funktion aufrufen, die die Nachricht über die ID und die eingestellte Sprache ausgibt, dann hast du die Abfrage nicht jedes mal in jedem Code stehen.
    stock SendLanguageMessage(playerid, id)
    {
    if(pInfo[playerid][Language] == 1)
    {
    switch(id)
    {
    case 0: SendClientMessage(playerid, -1, "Hallo Welt!");
    }
    }
    if(pInfo[playerid][Language] == 2)
    {
    switch(id)
    {
    case 0: SendClientMessage(playerid, -1, "Hello World!");
    }
    }
    return 1;
    }

    if(newkeys & KEY_YES)
    {
    if(GetPlayerState(playerid) != PLAYER_STATE_DRIVER)return SendClientMessage(playerid,COLOR_GRAU,"Du bist kein Fahrer eines Fahrzeuges");
    new vehicleid;
    vehicleid = GetPlayerVehicleID(playerid);
    GetVehicleParamsEx(vehicleid, engine, lights, alarm, doors, bonnet, boot, objective);
    if(engine == 1)
    {
    engine = 0;
    SendClientMessage(playerid,COLOR_WHITE,"Info: Der Motor wurde ausgeschaltet.");
    }
    else if(engine == 0)
    {
    engine = 1;
    SendClientMessage(playerid,COLOR_WHITE,"Info: Der Motor wurde eingeschaltet.");
    }
    SetVehicleParamsEx(vehicleid, engine, lights, alarm, doors, bonnet, boot, objective);
    }


    Du hattest die Zahlen vertauscht.


    EDIT:
    Siehe auch hier: http://forum.sa-mp.de/gta-mult…lock-befehl-2#post2012021

    Ja, das ist ja auch gut so, das haben wir ja oben behoben.



    Der Log den du gepostet hast ist der Log vom speichern. Wenn das Fahrzeug nicht lädt, dann musst du den Log vom Laden der Fahrzeuge posten. ;)
    Mit dem Log den du gepostet hast fange ich nichts an.


    Und wenn du schon dabei bist, poste zum Log vom laden auch gleich den Code vom laden dazu, dann habe ich das auch gleich.