[jTuT] Interaktive Dialoge

Wichtiger Hinweis: Bitte ändert nicht manuell die Schriftfarbe auf schwarz sondern belasst es bei der Standardeinstellung. Somit tragt ihr dazu bei dass euer Text auch bei Verwendung unseren dunklen Forenstils noch lesbar ist!

Tipp: Ihr wollt längere Codeausschnitte oder Logfiles bereitstellen? Benutzt unseren eigenen PasteBin-Dienst Link
  • [jTuT] Interaktive Dialoge




    Externer Inhalt www.youtube.com
    Inhalte von externen Seiten werden ohne Ihre Zustimmung nicht automatisch geladen und angezeigt.
    Durch die Aktivierung der externen Inhalte erklären Sie sich damit einverstanden, dass personenbezogene Daten an Drittplattformen übermittelt werden. Mehr Informationen dazu haben wir in unserer Datenschutzerklärung zur Verfügung gestellt.




    Hallo zusammen,
    dies ist mein erstes Tutorial. Es wird in diesem Tutorial erklärt, wie man Dialoge interaktiv machen kann, das heißt, dass sich listitems während ein Dialog geöffnet ist, hinzufügen und entfernen lassen.


    Kurzer Überblick

    • Was bewirkt dieses Tutorial am Ende und warum lest ihr euch das durch?
      Ganz einfach! Mit wenigen Schritten und ein paar kleinen Funktionen ist es möglich, die Dialoge im Menu-Style interaktiv zu machen. Das bedeutet, es lassen sich listitems zu einem Menu hinzufügen oder entfernen, und das während der Dialog einem oder mehrerer Spieler gezeigt wird. Es werden hier keinerlei Timer benutzt, das heißt die ganze Sache wirkt sich keineswegs negativ auf die Rechenleistung eures Servers aus.
      Schaut es euch doch einfach mal an, es wird sich lohnen.





    Wir arbeiten uns durch den Code

    • Als erstes überlegen wir uns, was wir denn überhaupt an Variablen bzw. Speichermedien brauchen um unser Vorhaben zu realisieren.


      Um später wissen zu können, welcher Spieler gerade welchen Dialog offen hat, müssen wir eine globale (g_) Variable für alle Spieler erstellen (daher das MAX_PLAYERS-Array). Um Fehler zu verhindern, setzen wir den Wert für alle Spieler gleich auf -1.

      C
      new g_PlayerDialog[MAX_PLAYERS] = {-1,...};
    • Anschließend müssen wir auch noch Variablen definieren, die wir später brauchen, um die Dialoge sauber und mit möglichst wenig Aufwand wieder anzeigen zu können. Außerdem wollen wir ja verhindern, zig mal das gleiche im Code stehen zu haben, daher machen wir es gleich mit Variablen, die wir später flexibel aufrufen können.
      Dazu benötigen wir eine Konstante MAX_OWN_DIALOGS, diese gibt an, wie viele Dialoge im gesamten Code benutzt werden. Hierbei sollte die größte Dialog-ID, die benutzt wird, beachtet werden.
      Außerdem brauchen wir noch globale Variablen für die Überschrift (Caption), den Menutext (Info) und die zwei Buttons (Button1 & Button2). Die Zahlen geben die jeweilige maximale Länge an, diese kann beliebig geändert werden, falls mehr benötigt wird. Zu beachten sei hier aber, dass je größer die Arrays, desto mehr Speicher muss später reserviert werden.

      C
      #define MAX_OWN_DIALOGS 100
      new g_dCaption[MAX_OWN_DIALOGS][36];
      new g_dInfo[MAX_OWN_DIALOGS][256];
      new g_dButton1[MAX_OWN_DIALOGS][8];
      new g_dButton2[MAX_OWN_DIALOGS][8];
    • Jetzt erstellen wir die Funktion, die uns das Menu anzeigen lässt und gleichzeitig die jeweiligen vergebenen Werte speichert.

    • Und wenn wir schon dabei sind, dann erstellen wir noch ein paar kleine aber nützliche Funktionen um später die Werte angenehm auszulesen.
      Die jeweilige Funktion gibt lediglich den definierten Wert der jeweiligen zu einem Dialog gehörenden Variable zurück.

      C
      stock GetPlayerDialog(playerid)
      {
      	return g_PlayerDialog[playerid];
      }


      C
      stock GetDialogCaption(dialogid)
      {
      	return g_dCaption[dialogid];
      }


      C
      stock GetDialogInfo(dialogid)
      {
      	return g_dInfo[dialogid];
      }


      C
      stock GetDialogButton1(dialogid)
      {
      	return g_dButton1[dialogid];
      }


      C
      stock GetDialogButton2(dialogid)
      {
      	return g_dButton2[dialogid];
      }
    • Und wenn wir schon dabei sind, dann definieren wir auch gleich noch SpielerName, einfach eine kleine Funktion die uns das Leben leichter macht.


      C
      stock SpielerName(playerid)
      {
      	new l_name[MAX_PLAYER_NAME];
      	GetPlayerName(playerid, l_name, sizeof(l_name));
      	return l_name;
      }
    • Jetzt kommen wir zu einem sehr wichtigen Teil der interaktiven Dialoge, dem Hinzufügen und dem Entfernen von Items im Menu.
      Fangen wir mit dem Hinzufügen an. Wir definieren eine Funktion AddItemToDialog in der wir die dialogid und den Text des Items mitgeben. Um Fehler zu verhindern, überprüfen wir, ob das selbe Item bereits in der Liste ist, falls ja, wird es entfernt und erneut hinzugefügt.


    • Das Selbe machen wir nun auch mit dem Entfernen von Items aus dem Dialog.


    • Jetzt haben wir die Funktion UpdateDialogForAll zwar schon zwei mal aufgerufen, wir haben sie aber noch gar nicht definiert. Das machen wir jetzt:


    • Kurze Erklärung zu dem hier:

      C
      g_dInfo[g_PlayerDialog[i]]


      Was macht das?
      Es ruft den Info-Text (g_dInfo) von der dialog-id auf (g_PlayerDialog) die der Spieler (i) geöffnet hat auf.

    • Wir benötigen jetzt noch eine kleine Funktion, die uns ein item anhand des listitems von OnDialogResponse zurückgibt:
      Dazu zählen wir einfach die Zeilenumbrüche (\n). Wurde die richtige Anzahl gefunden (=listitem), dann wird der string zerstückelt und das item zurückgegeben.
      Ich spare mir hier die Erklärungen im Code, das würde es nur unleserlich und unverständlich machen.

    • Dann kommen wir jetzt zu den Callbacks die wir bestücken. Fangen wir zuerst mit dem kürzesten an:


      C
      public OnPlayerDisconnect(playerid, reason)
      {
      	//Wenn der Spieler den Server verlässt, dann hat er/sie keinen Dialog mehr offen, also sagen wir, dass die offene dialogid -1 ist.
      	g_PlayerDialog[playerid] = -1;
      	return 1;
      }
    • Und zu guter Letzt noch ein Nutzungsbeispiel der Funktionen:


    • Abschließend dann noch das Beispiel zu OnDialogResponse:


    • Und damit wären wir auch durch. Alles ist jetzt funktionsfähig und kann beliebig erweitert werden.





    Für die Faulen unter uns

    • Natürlich habe ich für die Faulen unter uns einen fertigen FilterScript.









    Damit wäre alles gesagt. Falls noch Fragen sind, gerne hier in diesem Thread stellen. Ich hoffe dem einen oder anderen hilft dieses Tutorial. Damit es auch noch anderen hilft, hinterlasst doch einfach kurz eine Rückmeldung, damit der Thread nicht stirbt.
    Gerne freue ich mich auch, wenn Ihr den grünen Daumen drückt und damit eure Anerkennung zeigt.


    Beste Grüße,
    Jeffry 8)

    3HZXdYd.png

    4 Mal editiert, zuletzt von Jeffry () aus folgendem Grund: 22.06.2015: PasteBin-Bild repariert | 08.11.2015: Code-Formatierung an WBB4 angepasst

  • Also...du lässt einfach während dem Anzeigen eines Dialoges, dem Spieler noch einen Dialog mit anderem content anzeigen...der 1. verschwindet und der 2. wird angezeigt und es sieht so aus, als ob sich der content vom 1. Dialog geändert hätte? :huh:


    Gut zu wissen, dass da samp mitspielt ^^


    //Edit:
    PS: Verwende anstatt Funktionen Makros:


    #define GetPlayerDialog(%0) g_PlayerDialog[%0]


    mfg. :thumbup:

    ast2ufdyxkb1.png


    Leute, lernt scripten und versucht mal lieber etwas selber zu schreiben, als es aus einem GF zu kopieren. :S

  • Zuerst, nette Idee, merkwürdige Umsetzung


    Wie von Kaliber: schon angesprochen, vernünftiger wäre es sicherlich gewesen Makros zu nutzen, dafür gibt es sie ja schließlich :D


    Die Caption in Dialogen hat übrigens 64 Zeichen, nicht 36 -> 64 + 1 | wegen \0
    der Infotext wie die Listitems sind 2048 Zeichen "stark" nicht nur 256 ^^


    Kleine Dinge - große Wirkung :P


    Wie auch immer.
    Einen fehler hast du.
    Schön und gut, dass SA:MP den Dialog "updatet" wenn man einen anderen anzeigen lässt.
    Besser wäre es, für den Clienten, wenn man den Dialog vorher verschwinden lässt.


    Dialogid kann dann einfach -1 sein, dann verschwindet der, dann kann man den auch gut wieder anzeigen lassen. :thumbup:

    "Bevor ich mir Informationen aus der "Bild" hole,
    werde ich anfangen, Wahlergebnisse danach vorauszusagen,
    neben welchen Busch unsere Katze gepinkelt hat."

    Margarete Stokowski

  • Die Caption in Dialogen hat übrigens 64 Zeichen, nicht 36 -> 64 + 1 | wegen \0
    der Infotext wie die Listitems sind 2048 Zeichen "stark" nicht nur 256 ^^


    Zitat

    Die Zahlen geben die jeweilige maximale Länge an, diese kann beliebig geändert werden, falls mehr benötigt wird. Zu beachten sei hier aber, dass je größer die Arrays, desto mehr Speicher muss später reserviert werden.


    Warum in aller Welt soll ich ein Array von 2048 Zeichen reservieren, wenn ich 90% davon sparen kann, weil ich es eh nie benötigen werde? Also das macht ja mal gar keinen Sinn. Wenn es benötigt wird, kann die Array-Größe angepasst werden, aber 99.9% werden wohl nie ein Menu mit einer Textlänge von 2048 Chars haben...


    Einen fehler hast du.


    Der da wäre?


    Schön und gut, dass SA:MP den Dialog "updatet" wenn man einen anderen anzeigen lässt.
    Besser wäre es, für den Clienten, wenn man den Dialog vorher verschwinden lässt.


    Und die Begründung dazu ist? Ohne eine Begründung ist diese Aussage wertlos. Ich kann im Gegensatz dazu sagen, dass es schlecht ist den Dialog erst zu entfernen, da es dann, bei schnellen Änderungen (so wie im Video) dazu kommen kann, dass der Dialog "Blinkeffekte" zeigt, ganz einfach deshalb, weil der Dialog in der Zeitspanne entsprechend der Ping des Spielers weg ist!
    Außerdem fehlt jeglicher Beweis, dass dies für den Client "besser" sein soll. Angesichts des Ressourcenverbrauchs und der Tatsache, dass Blinkeffekte auftreten werden, wird es dafür wohl auch keinen Beweis geben, falls doch bin ich jederzeit offen diesen zu sehen.

  • Warum in aller Welt soll ich ein Array von 2048 Zeichen reservieren, wenn ich 90% davon sparen kann, weil ich es eh nie benötigen werde? Also das macht ja mal gar keinen Sinn. Wenn es benötigt wird, kann die Array-Größe angepasst werden, aber 99.9% werden wohl nie ein Menu mit einer Textlänge von 2048 Chars haben...

    Meiner Meinung nach sollte man die Funktionsweise nicht absichtlich einschränken - auch wenn 2048 Zeichen etwas viel sind.


    Und die Begründung dazu ist? Ohne eine Begründung ist diese Aussage wertlos. Ich kann im Gegensatz dazu sagen, dass es schlecht ist den Dialog erst zu entfernen, da es dann, bei schnellen Änderungen (so wie im Video) dazu kommen kann, dass der Dialog "Blinkeffekte" zeigt, ganz einfach deshalb, weil der Dialog in der Zeitspanne entsprechend der Ping des Spielers weg ist!
    Außerdem fehlt jeglicher Beweis, dass dies für den Client "besser" sein soll. Angesichts des Ressourcenverbrauchs und der Tatsache, dass Blinkeffekte auftreten werden, wird es dafür wohl auch keinen Beweis geben, falls doch bin ich jederzeit offen diesen zu sehen.

    Vielleicht weil diese vorgehensweise in nächsten SA:MP Versionen nicht unbedingt unterstützt werden muss?
    Sowas kann durchaus als Sicherheitslücke eingestuft werden.


    #Brotfischbaron


    In schā'a llāh

  • Meiner Meinung nach sollte man die Funktionsweise nicht absichtlich einschränken - auch wenn 2048 Zeichen etwas viel sind.


    Warum nicht? Du kannst mir doch nicht erzählen, dass du bei jedem Dialog einen string mit der Größe 2048 deklarierst. Da wird sich der Compiler aber schnell beschweren, bzw. die RAM, da du jedes mal zig tausende an Bytes verschwendest durch unnötige freie Belegungen.
    Begründung?



    Vielleicht weil diese vorgehensweise in nächsten SA:MP Versionen nicht unbedingt unterstützt werden muss?
    Sowas kann durchaus als Sicherheitslücke eingestuft werden.


    Ich musste mir grade 10 mal ins Gesicht schlagen um sicher zu gehen, dass ich richtig gelesen habe.
    Wie in aller Welt soll denn das bitte eine Sicherheitslücke sein?
    Und "vielleicht wird es nicht mehr unterstützt"? Ernsthaft? Vielleicht wird in SA:MP 1.0 SendClientMessage nicht mehr unterstützt, vielleicht geht die Welt morgen unter, vielleicht regnet es heute Nacht Pizza. :pinch:
    Also bitte, wenn du solche Aussagen machst, dann begründe die doch wenigstens im Ansatz.


    (Übrigens: Pizza-Regen kann durchaus auch als Sicherheitslücke in der Biosphäre der Erde eingestuft werden!)

  • Danke für deine Mühe, sehr sauberes Tutorial! ;)
    Die ganzen Präfixe, die du bei deiner Variablendeklaration benutzt, verwirren mich etwas, aber das wird schon. Ist doch eher was für Fortgeschrittene einen interaktiven Dialog zu scripten.

  • Danke für deine Mühe, sehr sauberes Tutorial! ;)


    Die ganzen Präfixe, die du bei deiner Variablendeklaration benutzt, verwirren mich etwas, aber das wird schon. Ist doch eher was für Fortgeschrittene einen interaktiven Dialog zu scripten.


    Danke für die Rückmeldung.


    Das kann ich dir gerne erklären:


    g_ - steht für Globale Variablen, das heißt alle Callbacks und Funktionen im Code können darauf zugreifen.
    l_ - steht für Lokale Variablen, das heißt nur die Funktion bzw. das Callback kann auf die Variable zugreifen.
    c_ - steht für einen Counter.


    Natürlich kannst du die auch anders nennen, das bleibt jedem selbst überlassen. :)

  • do.de - Domain-Offensive - Domains für alle und zu super Preisen
  • Mir ist noch nicht ganz klar, warum die globalen Variablen zu Caption, Menutext und Buttons unbedingt nötig sind.


    Diese sind für die Aktualisierung der Dialoge notwendig. Vor allem für die Funktion "UpdateDialogForAll", da der Server ja sonst nicht weiß, was er dort hinschreiben soll, das heißt du müsstest es wieder jedes mal selbst angeben, und das wollen wir ja nicht. :)


    Ich hoffe, deine Frage ist damit beantwortet. Falls nicht, oder falls du noch weitere Fragen hast, einfach fragen.

  • Ich versteh noch nicht so ganz, wie ich ein einziges listitem in einem Dialog "updaten" kann.


    Wenn ich nun diesen Dialog habe...
    COMMAND:dm(playerid, params[])
    {
    new stringDE[512],
    stringEN[512];
    format(stringDE, sizeof(stringDE), "[%d] DM1 [Sniper, Desert Eagle, Shotgun]\n[%d] DM2 [Desert Eagle, Combat Shotgun]\n[%d] DM3 [Sawnoff Shotgun, Uzi]\n");
    strcat(stringDE, "[%d] DM4 [Katana]\n[%d] DM5 [Minigun]\n[%d] Paintball [Country Rifle, 5mm Pistole]\n[%d] Battlefield [M4, Uzi, Granaten, Combat Shotgun, Raketenwerfer]");
    format(stringEN, sizeof(stringEN), "[%d] DM1 [Sniper, Desert Eagle, Shotgun]\n[%d] DM2 [Desert Eagle, Combat Shotgun]\n[%d] DM3 [Sawnoff Shotgun, Uzi]\n");
    strcat(stringEN, "[%d] DM4 [Katana]\n[%d] DM5 [Minigun]\n[%d] Paintball [Country Rifle]\n[%d] Battlefield [M4, Uzi, Grenades, Combat Shotgun, Rocket Launcher]");
    return ShowLanguageDialog(playerid, DIALOG_DM, DIALOG_STYLE_LIST, "Deathmatches", "Deathmatches", stringDE, stringEN, "OK", "OK", "Zurück", "Back");
    }


    ...und überall die aktuelle Spielerzahl zeigen möchte. Was muss ich dann genau in jedem einzelnen DM CMD und im Dialog machen lassen?


    Also, ich hab mir zuerst überlegt globale Variablen als Counter für jedes DM zu erstellen. Wenn ein Spieler das DM betritt, dann zähl ich das im CMD hoch und beim Verlassen wieder runter. Soweit so gut, das ist ja noch einfach. Muss ich dann gleich im CMD UpdateDialogForAll auch benutzen? Was genau muss ich eig im Dialog machen? Ich find das alles sehr verwirrend.^^

  • Das ist mir klar, deswegen "updaten" auch in Anführungsstrichen. Ich kann den Code größtenteils nachvollziehen, nur an der korrekten Anwendung hapert es noch ein wenig. Hoffentlich kann Jeffry da aushelfen.


    Du kannst eine eizelne Zeile nicht nachladen du musst dir die texte ggf. zwischenspeichern und die Zeile dann ändern
    Notfalls musst du mit \n splitten, falls das geht bei pawn

  • Was genau muss ich eig im Dialog machen? Ich find das alles sehr verwirrend.^^


    Willst du die DMs in der Reihenfolge so wie sie sind (1,2,3,...) bleiben?
    Wenn ja, dann muss ich noch eine Funktion hinzufügen, um ein vorhandenes Item zu aktualisieren, ohne es nach unten zu verschieben, da das so noch nicht geht.


    Ansonsten könntest du das Item suchen, entfernen und neu hinzufügen, dann steht es eben ganz unten.
    Sag Bescheid wie du es haben willst, dann mache ich dir das kurz, bzw. füge es dem Tutorial hinzu.



    EDIT:
    Falls du die Reihenfolge gleich haben willst:

    Spoiler anzeigen
    stock UpdateItemInDialog(dialogid, olditem[], newitem[])
    {
    //Wir suchen das item.
    new l_pos = strfind(g_dInfo[dialogid], olditem);

    //Wurde das item nicht gefunden, dann wird auch nichts gemacht.
    if(l_pos == -1) return 0;

    //Ansonsten wird es entfernt.
    strdel(g_dInfo[dialogid], l_pos, l_pos+strlen(olditem)+1);

    Spoiler anzeigen
    //Und das neue item wird eingefügt, zuvor geben wir dem item noch einen Zeilenumbruch mit.
    strcat(newitem, "\n", 256);
    strins(g_dInfo[dialogid], newitem, l_pos);

    //Wir beenden die Funktion mit der Anweisung, den Dialog für alle Spieler zu aktualisieren.
    return UpdateDialogForAll(dialogid);
    }

    Ich konnte es noch nicht testen, das müsstest du machen.


    Den Dialog musst du bei OnGameModeInit erstellen, und zwar so:
    AddItemToDialog(dialogid_von_DE, "[0] DM1 [Sniper, Desert Eagle, Shotgun]");
    AddItemToDialog(dialogid_von_DE, "[0] DM2 [Desert Eagle, Combat Shotgun]");
    //usw...
    //ebenso beim Englischen.
    Ich nehme an das [0] ist die Anzahl der Spieler.


    Dialog anzeigen wie im Beispiel.


    Item aktualisieren:
    format(tmpstr, 128, GetItemFromDialog(dialogid, DM_ID_HIER));
    //dann das neue Item formatieren, also mit switch-case über die DM_ID neu setzen
    //Beispiel:
    format(newstr, 128, "[%d] DM2 [Desert Eagle, Combat Shotgun]", Spieler_In_dem_DM);
    //Dann updaten:
    UpdateItemInDialog(dialogid_von_DE, tmpstr, newstr);


    //Dann das gleichen nochmal für Englisch machen.



    Versuche dich mal daran, falls Fragen auftauchen kannst du gerne Fragen. Wenn du die Funktion getestet hast (ansonsten mache ich es am Wochenende selbst), kann ich die auch oben hinzufügen.

    3HZXdYd.png

    2 Mal editiert, zuletzt von Jeffry ()

  • Ja, die Reihenfolge soll erhalten bleiben. Wäre schön, wenn du das noch in das Tutorial integrieren könntest! :thumbup:


    Heißt das, ich brauche 2 dialogids für zwei Sprachen?
    Also, ich hab jetzt mal versucht mein Sprachsystem in die Funktionen einzubauen.


    Spoiler anzeigen
    stock ShowUpdateDialog(playerid, dialogid, style, captionDE[], captionEN[], infoDE[], infoEN[], button1DE[], button1EN[], button2DE[], button2EN[])
    {
    DialogOpened[playerid] = dialogid;
    ShowLanguageDialog(playerid, dialogid, style, captionDE[], captionEN[], infoDE[], infoEN[], button1DE[], button1EN[], button2DE[], button2EN[]);
    if(dialogid > -1 && dialogid < MAX_DIALOGS)
    {
    if(pInfo[playerid][Language] == LANGUAGE_DE)
    {
    format(CaptionDE[dialogid], sizeof(CaptionDE[]), caption);
    format(InfoDE[dialogid], sizeof(InfoDE[]), info);
    format(Button1DE[dialogid], sizeof(Button1DE[]), button1);
    format(Button2DE[dialogid], sizeof(Button2DE[]), button2);
    }
    if(pInfo[playerid][Language] == LANGUAGE_EN)
    {
    format(CaptionEN[dialogid], sizeof(CaptionEN[]), caption);
    format(InfoEN[dialogid], sizeof(InfoEN[]), info);
    format(Button1EN[dialogid], sizeof(Button1EN[]), button1);
    format(Button2EN[dialogid], sizeof(Button2EN[]), button2);
    }
    }
    return 1;
    }

    Spoiler anzeigen
    stock GetPlayerDialog(playerid)
    {
    return DialogOpened[playerid];
    }

    Spoiler anzeigen
    stock GetDialogCaption(playerid, dialogid)
    {
    if(pInfo[playerid][Language] == LANGUAGE_DE) return CaptionDE[dialogid];
    if(pInfo[playerid][Language] == LANGUAGE_EN) return CaptionEN[dialogid];
    }

    Spoiler anzeigen
    stock GetDialogInfo(playerid, dialogid)
    {
    if(pInfo[playerid][Language] == LANGUAGE_DE) return InfoDE[dialogid];
    if(pInfo[playerid][Language] == LANGUAGE_EN) return InfoEN[dialogid];
    }

    Spoiler anzeigen
    stock GetDialogButton1(playerid, dialogid)
    {
    if(pInfo[playerid][Language] == LANGUAGE_DE) return Button1DE[dialogid];
    if(pInfo[playerid][Language] == LANGUAGE_EN) return Button1EN[dialogid];
    }

    Spoiler anzeigen
    stock GetDialogButton2(playerid, dialogid)
    {
    if(pInfo[playerid][Language] == LANGUAGE_DE) return Button2DE[dialogid];
    if(pInfo[playerid][Language] == LANGUAGE_EN) return Button2EN[dialogid];
    }

    Spoiler anzeigen
    stock AddItemToDialog(playerid, dialogid, item[])
    {
    new ItemPosition;
    if(pInfo[playerid][Language] == LANGUAGE_DE) ItemPosition = strfind(InfoDE[dialogid], item);
    if(pInfo[playerid][Language] == LANGUAGE_EN) ItemPosition = strfind(InfoEN[dialogid], item);
    if(ItemPosition != -1)
    {
    if(pInfo[playerid][Language] == LANGUAGE_DE)
    {
    strdel(InfoDE[dialogid], ItemPosition, ItemPosition(item) + 1);
    format(InfoDE[dialogid], sizeof(InfoDE[]), "%s%s\n", InfoDE[dialogid], item);
    }
    if(pInfo[playerid][Language] == LANGUAGE_EN)
    {
    strdel(InfoEN[dialogid], ItemPosition, ItemPosition(item) + 1);
    format(InfoEN[dialogid], sizeof(InfoEN[]), "%s%s\n", InfoEN[dialogid], item);
    }
    }
    return UpdateDialogForAll(dialogid);
    }

    Spoiler anzeigen
    stock RemoveItemFromDialog(playerid, dialogid, item[])
    {
    new ItemPosition;
    if(pInfo[playerid][Language] == LANGUAGE_DE) ItemPosition = strfind(InfoDE[dialogid], item);
    if(pInfo[playerid][Language] == LANGUAGE_EN) ItemPosition = strfind(InfoEN[dialogid], item);
    if(ItemPosition == -1) return 0;
    if(pInfo[playerid][Language] == LANGUAGE_DE) strdel(InfoDE[dialogid], ItemPosition, ItemPosition + strlen(item) + 1);
    if(pInfo[playerid][Language] == LANGUAGE_EN) strdel(InfoDE[dialogid], ItemPosition, ItemPosition + strlen(item) + 1);
    return UpdateDialogForAll(dialogid);
    }

    Spoiler anzeigen
    stock UpdateDialogForAll(dialogid)
    {
    for(new i = 0; i < MAX_PLAYERS; i++)
    {
    {
    ShowLanguageDialog(i, DialogOpened[i], DIALOG_STYLE_LIST, CaptionDE[DialogOpened[i]], CaptionEN[DialogOpened[i]], InfoDE[DialogOpened[i]], InfoEN[DialogOpened[i]], Button1DE[DialogOpened[i]], Button1EN[DialogOpened[i]], Button2DE[DialogOpened[i]], Button2EN[DialogOpened[i]]);
    }
    }
    return 1;
    }

    Spoiler anzeigen
    stock GetItemFromDialog(playerid, dialogid, listitem)
    {
    new l_str[64],
    c_count,
    l_lastpos = -1,
    tmpDE[sizeof(InfoDE[])],
    tmpEN[sizeof(InfoEN[])];

    Spoiler anzeigen
    if(pInfo[playerid][Language] == LANGUAGE_DE)
    {
    for(new i=0; i<strlen(InfoDE[dialogid]); i++)
    {
    if(InfoDE[dialogid][i] == "\n")
    {
    if(c_count == listitem)
    {
    tmpDE = InfoDE[dialogid];
    strdel(tmpDE, i, strlen(InfoDE[dialogid]));
    strdel(tmpDE, 0, l_lastpos+1);
    break;
    }
    c_count++;
    l_lastpos = i;
    }
    }
    format(l_str, sizeof(l_str), tmpDE);
    }
    if(pInfo[playerid][Language] == LANGUAGE_EN)
    {
    for(new i=0; i<strlen(InfoEN[dialogid]); i++)
    {
    if(InfoEN[dialogid][i] == "\n")
    {
    if(c_count == listitem)
    {
    tmpEN = InfoEN[dialogid];
    strdel(tmpEN, i, strlen(InfoEN[dialogid]));
    strdel(tmpEN, 0, l_lastpos+1);
    break;
    }
    c_count++;
    l_lastpos = i;
    }
    }
    format(l_str, sizeof(l_str), tmpEN);
    }
    return l_str;
    }

    Spoiler anzeigen
    stock UpdateItemInDialog(playerid, dialogid, olditem[], newitem[])
    {
    new l_pos;
    if(pInfo[playerid][Language] == LANGUAGE_DE) l_pos = strfind(InfoDE[dialogid], olditem);
    if(pInfo[playerid][Language] == LANGUAGE_EN) l_pos = strfind(InfoEN[dialogid], olditem);
    if(l_pos == -1) return 0;
    if(pInfo[playerid][Language] == LANGUAGE_DE) strdel(InfoDE[dialogid], l_pos, l_pos+strlen(olditem)+1);
    if(pInfo[playerid][Language] == LANGUAGE_EN) strdel(InfoEN[dialogid], l_pos, l_pos+strlen(olditem)+1);
    strcat(newitem, "\n", 256);
    if(pInfo[playerid][Language] == LANGUAGE_DE) strins(InfoDE[dialogid], newitem, l_pos);
    if(pInfo[playerid][Language] == LANGUAGE_EN) strins(InfoEN[dialogid], newitem, l_pos);
    return UpdateDialogForAll(dialogid);
    }


    Würde das so gehen? Oder gibt es einen einfacheren Weg?


    Außerdem, was meinst du mit "Dialog unter OnGameModeInit erstellen"? Ich bin es gewohnt das unter OnDialogResponse zu machen. 8|


    Edit: Code Updates.

    2 Mal editiert, zuletzt von Manyula ()

  • Was hast du denn da gemacht?! 8|


    Das geht viel einfacher.
    Ich versuche es nochmal zu erklären:


    OnGameModeInit:
    AddItemToDialog(dialogid_von_DE, "[0] DM1 [Sniper, Desert Eagle, Shotgun]");
    AddItemToDialog(dialogid_von_DE, "[0] DM2 [Desert Eagle, Combat Shotgun]");
    //usw...
    //Auch für das Englische machen.



    Dann dort, wo der Spieler dem DM beitritt:
    format(tmpstr, 128, GetItemFromDialog(dialogid, DM_ID_HIER));
    //dann das neue Item formatieren, also mit switch-case über die DM_ID neu setzen
    switch(DM_ID_VARIABLE)
    {
    case 0: format(newstr, 128, "[%d] DM2 [Desert Eagle, Combat Shotgun]", Spieler_In_dem_DM_0);
    //usw...
    }
    //Dann updaten:
    UpdateItemInDialog(dialogid_von_DE, tmpstr, newstr); //Die Funktion steht In Post #17


    //Dann das gleiche nochmal für Englisch machen.



    Dein Befehl sieht dann so aus:
    COMMAND:dm(playerid, params[])
    {
    if(pInfo[playerid][Language] == LANGUAGE_DE) ShowPlayerDialog_Ex(playerid, dialogid_von_DE, DIALOG_STYLE_LIST, "DMs", GetDialogInfo(dialogid_von_DE), "Schließen", "Beitreten")
    if(pInfo[playerid][Language] == LANGUAGE_EN) ShowPlayerDialog_Ex(playerid, dialogid_von_EN, DIALOG_STYLE_LIST, "DMs", GetDialogInfo(dialogid_von_EN), "Close", "Join")
    return 1;
    }
    Mehr ist es nicht.


    Die Funktionen von mir musst du nicht ändern. Wenn du die änderst funktioniert es nicht mehr.


    Das Prinzip ist, dass ein Dialog erstellt wird (wie ein Auto).

  • Folgendes: Ich habe diese Funktion hier, die mir die if-Abfragen erspart.
    stock ShowLanguageDialog(playerid, dialogid, style, captionDE[], captionEN[], infoDE[], infoEN[], button1DE[], button1EN[], button2DE[], button2EN[])
    {
    if(pInfo[playerid][Language] == LANGUAGE_DE) return ShowPlayerDialog(playerid, dialogid, style, captionDE, infoDE, button1DE, button2DE);
    else if(pInfo[playerid][Language] == LANGUAGE_EN) return ShowPlayerDialog(playerid, dialogid, style, captionEN, infoEN, button1EN, button2EN);
    return 1;
    }


    Deswegen hab ich bereits in den stock Funktionen an sich zu unterscheiden, damit das mit der genannten Funktion harmoniert.


    Und nochmal, brauch ich dann separate dialogids für beide Sprachen?
    COMMAND:dm(playerid, params[])
    {
    if(pInfo[playerid][Language] == LANGUAGE_DE) ShowUpdateDialog(playerid, DIALOG_DM, DIALOG_STYLE_LIST, "Deathmatches", GetDialogInfo(dialogid_von_DE), "Schließen", "Beitreten")
    if(pInfo[playerid][Language] == LANGUAGE_EN) ShowUpdateDialog(playerid, DIALOG_DM, DIALOG_STYLE_LIST, "Deathmatches", GetDialogInfo(dialogid_von_EN), "Close", "Join")
    return 1;
    }
    Hier habe ich ja in beiden Dialogen dieselbe dialogid.

  • do.de - Domain-Offensive - Domains für alle und zu super Preisen