Ein- und Ausgänge einfach gemacht. - Teil 1

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
  • Liebe sa-mp.de Benutzer,


    ich habe gerade mal die Suchfunktion im Tutorial-Bereich benutzt, um zu schauen, ob dieses Tutorial überhaupt notwendig ist.
    Und ja es ist notwendig :rolleyes: .
    Es gibt hier viele Tutorials über eigene Ein und Ausgänge ohne CMD, aber irgendwie, zumindest kommt es so rüber, dass ich bei ca. 100 Ein und Ausgängen nachher mehr Code davon habe, als der Rest vom Script.
    Daher finde ich es doch notwenig, mal zu zeigen wie Ich soetwas lösen würde, da es natürlich bestimmt noch andere Varianten gibt.


    Um eigene Ein- und Ausgänge zu erstellen, müssen die alten erstmal raus.
    Dafür gibt es eine leichte Methode, nämlich:


    DisableInteriorEnterExits();
    Das fügt ihr bei dem Callback: OnGameModeInIt hinein, sollte eigentlich bekannt sein.
    Nunja, um Teleporter zu erstellen, brauchen wir erstmal etwas, was diese als solche kennzeichnet, kurz gesagt "PickUps".
    Wie euch bekannt sein sollte, braucht die Funktion "CreatePickup" natürlich Übergabeparameter, nämlich Erscheinungsbild(model),Typ(type),Position(X,Y,Z) und Virtual-World.


    So nun gibt es Leute unter uns, die fangen so an:


    new pickup1;
    new pickup2;
    //usw.


    Dann gibt es "schlauere" Leute, die fangen so an:


    new pickups[100]; .


    Doch alle machen dann den Fehler bei OnGameModeInit.


    Sieht dann ungefähr so aus:


    pickup1 = CreatePickup(...)
    oder so
    pickups[0] = CreatePickup(...)


    Bei 100 Ein- und Ausgängen wünsche ich den Leuten an dieser Stelle viel Spaß.
    So nun kommen wir zu meinem Vorschlag.


    Ein 2-D(imensionales) Array + eine enum Struktur arbeiten viel effektiver.


    Zur Erklärung:


    By Goldkiller :


    Zitat

    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)

    Nunja in diesem Enum können wir also verschiedene Typen haben, was bei den Übergabeparametern ja ebenfalls der Fall ist. Zufall? Wer weiß?


    Also das enum würde so aussehen:


    enum picks{
    Float:eX,
    Float:eY,
    Float:eZ,
    interior,
    bool:Rueck,
    Virtualworld
    }


    Die X,Y,Z - Werte sind also Float-Werte, wer nicht weiß, was Float-Werte sind, sollte in einer neuen Registerkarte, das Wiki durchstöbern.
    Wofür interior?
    Um uns am Ende viel Code zu ersparen geben wir hier das Interior an, in welchem sich das Pickup befindet.
    Rueck vom Typ bool(ean), gibt an, ob es ein Hin, oder Rück-Teleporter ist, in diesem Falle Im Gebäude, oder draussen.
    Virtualworld ist ein Übergabeparameter für die Funktion CreatePickup(...).
    Das ganze packen wir nun in ein 2-Dimensionales Array.


    new PickUpsCoords[PICK_UPS][picks] = {};


    Wir werden dem Array eine Größe durch etwas definiertes ausdrücken.


    Nämlich:


    #define PICK_UPS 2 // Die 2 steht für die Anzahl ALLER Teleporter (Hin und Rück - Differenziert)


    So nun müssen wir ja aber auch die Werte im enum initialisieren.
    Dies passiert so:


    new PickUpsCoords[PICK_UPS][picks] = {


    // Nach dem Schema: X,Y,Z,Interior des Pickups, Rück Porter - ja / nein, VW
    {-316.1541,829.8519,14.2422,0,false,0}, // Amunation IN
    {285.8248,-40.8825,1001.5156,1,true,0} // Amunation OUT


    Wie schon erklärt: Der erste Wert stell eX des enum dar, der zweite eY, der dritte eZ, der vierte interior, der fünfte Rueck und der sechste Virtualworld.
    Wichtig dabei ist, dass ihr Schemata/Schemas(xD, ja ist leider so) beibehalten: Ersten das, was ich einen Satz zuvor erklärt habe. Und zweitens, dass immer der Hin-Teleporter, in diesem Falle der draussen vor dem Gebäude ist immer als erstes kommt. Sprich wenn ich jetzt Vier Teleporter erzeugen möchte, sieht das Array so aus:


    new PickUpsCoords[PICK_UPS][picks] = {


    // Nach dem Schema: X,Y,Z,Interior des Pickups, Rück Porter - ja / nein, VW
    {-316.1541,829.8519,14.2422,0,false,0}, // Amunation IN
    {285.8248,-40.8825,1001.5156,1,true,0}, // Amunation OUT
    172.9729,1177.1868,14.7578,0,false,0}, // Cluckin Bell IN
    {365.0766,-11.8404,1001.8516,9,true,0} // Cluckin Bell OUT


    };


    Und so weiter.. Natürlich müssten wir jetzt bei 4 Teleportern folgendes ändern.


    #define PICK_UPS 4


    So nun müssen wir noch ein Array erstellen, was die Pickup-ID's also die return-Werte von der Funktion CreatePickup(...) speichert.


    new PickUps[PICK_UPS];


    Dass wir wieder mit "PICK_UPS" arbeiten, macht es einfach, denn so sind beide Arrays, also das 1D und 2D immer von der Größe gleich.


    So nun erzeugen wir die Pickups mit der Funktion CreatePickup, und zwar unter OnGameModeInit.
    Hier haben wir schon das erste Ziel meines Tutorials erreicht. Anstatt jetzt z.B 100 Pickups per Hand zu erstellen, übernimmt eine For-Schleife diese arbeit.
    Das ganze sieht dann so aus bei OnGameModeInIt.


    for(new i = 0; i <= sizeof(PickUps); i++)
    {
    PickUps[i] = CreatePickup(1318,23,PickUpsCoords[i][eX],PickUpsCoords[i][eY],PickUpsCoords[i][eZ],PickUpsCoords[i][Virtualworld]);
    }
    Damit sparen wir schonmal die erste "Handarbeit".
    1318 ist das Pickup Model, in diesem Falle der Pfeil nach unten und 23 der Pickup Typ, in diesem Falle, pickupable(!) but dont disappear on pickup, glaube ich.
    Also für uns der richtige Typ, denn es geht so weiter.


    Wir betrachten das Callback: OnPlayerPickUpPickup, welches zwar klein, aber wichtig für uns ist.


    Dort fügt ihr folgendes ein:


    for(new i = 0; i <= sizeof PickUps; i++)
    {
    if(pickupid == PickUps[i])
    {
    StehtaufPickUp[playerid] = pickupid;
    }
    }


    Warum brauchen wir das Spielerbezogene Array StehtaufPickUp?
    Ganz einfach, wir könnten uns das jetzt sparen und mit einer Timer-Delay Struktur arbeiten, aber auf den modernen Servern benutzt man jetzt gerne die Enter Taste um Gebäude zu betreten, was ich hier jetzt auch umsetzen werde.
    Da also pickupid uns ausserhalb des Callbacks nicht mehr zur Verfügung steht, speichern wir den Wert eben in das Array hinein.


    Also brauchen wir oben im Script noch ein


    new StehtaufPickUp[MAX_PLAYERS];


    und bei OnPlayerConnect ein:


    StehtaufPickUp[playerid] = -1


    Soweit so gut, aber richtig viel ist uns noch nicht erspart geblieben, durch dieses Tutorial, aber das ändert sich jetzt.
    Wir wollten uns ja mit dem "Entertaste-Teleporter" beschäftigen, also brauchen wir das Callback: OnPlayerKeyStateChange.


    Dort fügen wir folgendes ein.


    if(newkeys == KEY_SECONDARY_ATTACK)
    {
    if(PlayerIsNearToEnterExit(playerid))
    {
    for(new i = 0; i <= sizeof(PickUps); i++)
    {
    if(PickUps[i] == StehtaufPickUp[playerid])
    {
    if(PickUpsCoords[i][Rueck] == false)
    {
    SetPlayerPos(playerid,PickUpsCoords[i+1][eX],PickUpsCoords[i+1][eY],PickUpsCoords[i+1][eZ]);
    SetPlayerInterior(playerid,PickUpsCoords[i+1][interior]);
    SetPlayerVirtualWorld(playerid,PickUpsCoords[i+1][Virtualworld]);
    StehtaufPickUp[playerid] = -1;
    }
    else if(PickUpsCoords[i][Rueck] == true)
    {
    SetPlayerPos(playerid,PickUpsCoords[i-1][eX],PickUpsCoords[i-1][eY],PickUpsCoords[i-1][eZ]);
    SetPlayerInterior(playerid,PickUpsCoords[i-1][interior]);
    SetPlayerVirtualWorld(playerid,PickUpsCoords[i-1][Virtualworld]);
    StehtaufPickUp[playerid] = -1;
    }
    }
    }
    }


    Erklärung:


    if(newkeys == KEY_SECONDARY_ATTACK):
    Fragt ab, ob der Spieler die Enter / F Taste gedrückt hat.
    Wenn das zutrifft, dann:
    if(PlayerIsNearToEnterExit(playerid))
    Wird abgefragt, ob der Spieler sich an einem PickUp befindet. Diese Funktion müssen gleich noch implementieren.
    Wenn das zutrifft, dann:
    Erstellen wir eine For-Schleife die uns durch das Array PickUps begleitet:
    Es wird dann abgefragt, ob wir auf einem Pickup gestanden haben, was einen Teleporter da stellt:

    2 Mal editiert, zuletzt von 8D ()

  • if(PickUps == StehtaufPickUp[playerid])
    Erinnert ihr euch? Wir hatten eine Variable im enum des Typs bool(ean).
    Das ist jetzt entscheidend. Es wird abgefragt, ob diese Variable den Wert true, oder false hat, sprich ob es ein Hin-Teleporter, also das Pickup ist vor dem Gebäude(false) oder ein Rück-Teleporter, also das Pickup befindet sich im Gebäude(true), ist.
    if(PickUpsCoords[Rueck] == false)
    Wenn wir uns also auf einem Pickup befinden, was der Hin-Teleporter sein soll, müssen wir, da wir ja brav sind, und uns am Schemata gehalten haben, uns die Infomationen des nächsten Speicherplatz holen, also vom Rückteleporter.
    Also:
    SetPlayerPos(playerid,PickUpsCoords[i+1][eX],PickUpsCoords[i+1][eY],PickUpsCoords[i+1][eZ]);
    SetPlayerInterior(playerid,PickUpsCoords[i+1][interior]);
    SetPlayerVirtualWorld(playerid,PickUpsCoords[i+1][Virtualworld]);
    StehtaufPickUp[playerid] = -1;
    Ihr seht ja, was ich gerade erklärt habe, am [i+1].
    Falls wir uns nun aber auf einem Pickup befinden, was der Rück-Teleporter sein soll, müssen wir ja umgekehrt arbeiten, und uns die Informationen des vorherigen Speicherplatz holen, sprich von Hinteleporter.


    Also:


    SetPlayerPos(playerid,PickUpsCoords[i-1][eX],PickUpsCoords[i-1][eY],PickUpsCoords[i-1][eZ]);
    SetPlayerInterior(playerid,PickUpsCoords[i-1][interior]);
    SetPlayerVirtualWorld(playerid,PickUpsCoords[i-1][Virtualworld]);
    StehtaufPickUp[playerid] = -1;


    Alle geschweiften offenen Klammern wieder schließen und fertig.
    Das ist der Teil des Tutorials, der uns Codes für 100 Ein-und Ausgänge, sprich ca. 2000 Zeilen Code mit if(PlayerToPoint) oder if(IsPlayerInRangeOfPoint) Abfragen für jeden Teleporter spart :).


    Zum Schluss müssen wir uns noch die Funktion IsPlayerNearToEnterExit einbauen, da ja bei OnPlayerPickUpPickup, die Variable StehtaufPickUp einmalig gesetzt wird, bis man aufs nächste Pickup geht.
    Das hätte zur Folge, dass wir uns ja dann einmal aufs Pickup stellen, ganz weit weglaufen, Enter drücken und uns teleportieren könnten, also nicht sehr realistisch.
    Genug zur Theorie. Fügt das Ende des Scripts ein.


    public PlayerIsNearToEnterExit(playerid)
    {
    new Float:x, Float:y, Float:z;
    GetPlayerPos(playerid,x,y,z);
    for(new i = 0; i <= sizeof PickUps; i++)
    {
    if(IsPlayerInRangeOfPoint(playerid,0.5,PickUpsCoords[i][eX],PickUpsCoords[i][eY],PickUpsCoords[i][eZ]))
    {
    return 1;
    }
    }
    return 0;
    }


    Und oben im Script noch ein:


    forward PlayerIsNearToEnterExit(playerid)


    So jetzt könnt ihr ganz leicht Ein- und Ausgänge erstellen, einfach das Definierte erhöhen immer, und dann im Array PickUpsCoords Hin und danach Rückteleporter-Informationen nach den beiden Schemata einfügen.


    Ich hoffe, dass ich alles ausführlich erklärt habe und freue mich auf Kritik.


    Fabi / 8D.

  • Der ID Eintrag für das Pickup ließe sich auch noch in die Struktur der Enum einbringen so musst du nich 100 unnötige Pickups
    vordefinieren und das ganze ist etwas Dynamischer ^^

    Mfg. BlackFoX_UD_ alias [BFX]Explosion


  • hallo,


    ich denke habe alles so gemacht wie im tut aber bekomme diese errors:


    (14578) : error 022: must be lvalue (non-constant)
    (14578) : warning 215: expression has no effect
    (14583) : error 022: must be lvalue (non-constant)
    (14583) : warning 215: expression has no effect
    (14591) : error 022: must be lvalue (non-constant)
    (14591) : warning 215: expression has no effect
    (14596) : error 022: must be lvalue (non-constant)
    (14596) : warning 215: expression has no effect
    (14604) : error 022: must be lvalue (non-constant)
    (14604) : warning 215: expression has no effect
    (14609) : error 022: must be lvalue (non-constant)
    (14609) : warning 215: expression has no effect


    Zeilen:


    immer diese funktion ist error:


    pickups++;



    Danke schonmal im vorraus.



    mfG

  • ? Das kommt in dem Tutorial nicht vor, ausser als schlechte Lösung, eventuell nochmal lesen.


    Was sein kann, dass du ein pickup[...] Array hast, was du nun mit ++ hochzählen willst, das geht aber nicht ;)


    Ich weiß nicht, was du gemacht hast, das steht aber nicht in dem Tutorial ;)

  • D:\GTA - San Andreas\Reallife x3\gamemodes\sgsscript.pwn(724) : error 010: invalid function or declaration
    D:\GTA - San Andreas\Reallife x3\gamemodes\sgsscript.pwn(726) : error 010: invalid function or declaration
    D:\GTA - San Andreas\Reallife x3\gamemodes\sgsscript.pwn(728) : error 010: invalid function or declaration
    D:\GTA - San Andreas\Reallife x3\gamemodes\sgsscript.pwn(730) : error 010: invalid function or declaration
    D:\GTA - San Andreas\Reallife x3\gamemodes\sgsscript.pwn(732) : error 010: invalid function or declaration
    D:\GTA - San Andreas\Reallife x3\gamemodes\sgsscript.pwn(739) : error 010: invalid function or declaration
    D:\GTA - San Andreas\Reallife x3\gamemodes\sgsscript.pwn(749) : error 010: invalid function or declaration
    Pawn compiler 3.2.3664 Copyright (c) 1997-2006, ITB CompuPhase



    7 Errors.


    Hier die zeilen:
    if(newkeys == KEY_SECONDARY_ATTACK)
    {
    if(PlayerIsNearToEnterExit(playerid))
    {
    for(new i = 0; i <= sizeof(PickUps); i++)
    {
    if(PickUps[i] == StehtaufPickUp[playerid])
    {
    if(PickUpsCoords[i][Rueck] == false)
    {
    SetPlayerPos(playerid,PickUpsCoords[i+1][eX],PickUpsCoords[i+1][eY],PickUpsCoords[i+1][eZ]);
    SetPlayerInterior(playerid,PickUpsCoords[i+1][interior]);
    SetPlayerVirtualWorld(playerid,PickUpsCoords[i+1][Virtualworld]);
    StehtaufPickUp[playerid] = -1;
    }
    else if(PickUpsCoords[i][Rueck] == true)
    {
    SetPlayerPos(playerid,PickUpsCoords[i-1][eX],PickUpsCoords[i-1][eY],PickUpsCoords[i-1][eZ]);
    SetPlayerInterior(playerid,PickUpsCoords[i-1][interior]);
    SetPlayerVirtualWorld(playerid,PickUpsCoords[i-1][Virtualworld]);
    StehtaufPickUp[playerid] = -1;
    }
    }
    }
    }

    (¯`*•.¸,¤°´'`°¤, ¸.•*´¯)
    ¸,¤°´'`°•.¸¸.•°´'`°¤,¸
    |¯¯¯¯¯¯¯¯¯`•[____________•´¯¯¯¯¯¯¯¯¯|
    ZuckerstangeLP
    |_________ .•¯¯¯¯¯¯¯¯¯¯¯¯•. _________|
    *´'`°¤¸¸ .•'´`'•.¸¸ ¤°´'`*
    (_¸.•*´'`°¤¸.¸¤°´'`*•.¸_)

    Youtube Kanal

  • also wenn ich es raus nehme sind keine errors aber dann kann ich ja nicht mit enter rein

    (¯`*•.¸,¤°´'`°¤, ¸.•*´¯)
    ¸,¤°´'`°•.¸¸.•°´'`°¤,¸
    |¯¯¯¯¯¯¯¯¯`•[____________•´¯¯¯¯¯¯¯¯¯|
    ZuckerstangeLP
    |_________ .•¯¯¯¯¯¯¯¯¯¯¯¯•. _________|
    *´'`°¤¸¸ .•'´`'•.¸¸ ¤°´'`*
    (_¸.•*´'`°¤¸.¸¤°´'`*•.¸_)

    Youtube Kanal

  • Ich habe nochmal alles gecheckt ich habe alles drinn:
    public OnPlayerKeyStateChange(playerid, newkeys, oldkeys)
    {
    /*if(newkeys == KEY_SECONDARY_ATTACK)
    {
    if(PlayerIsNearToEnterExit(playerid))
    {
    for(new i = 0; i <= sizeof(PickUps); i++)
    {
    if(PickUps[i] == StehtaufPickUp[playerid])
    {
    if(PickUpsCoords[i][Rueck] == false)
    {
    SetPlayerPos(playerid,PickUpsCoords[i+1][eX],PickUpsCoords[i+1][eY],PickUpsCoords[i+1][eZ]);
    SetPlayerInterior(playerid,PickUpsCoords[i+1][interior]);
    SetPlayerVirtualWorld(playerid,PickUpsCoords[i+1][Virtualworld]);
    StehtaufPickUp[playerid] = -1;
    }
    else if(PickUpsCoords[i][Rueck] == true)
    {
    SetPlayerPos(playerid,PickUpsCoords[i-1][eX],PickUpsCoords[i-1][eY],PickUpsCoords[i-1][eZ]);
    SetPlayerInterior(playerid,PickUpsCoords[i-1][interior]);
    SetPlayerVirtualWorld(playerid,PickUpsCoords[i-1][Virtualworld]);
    StehtaufPickUp[playerid] = -1;
    }
    }
    }
    }*/

    (¯`*•.¸,¤°´'`°¤, ¸.•*´¯)
    ¸,¤°´'`°•.¸¸.•°´'`°¤,¸
    |¯¯¯¯¯¯¯¯¯`•[____________•´¯¯¯¯¯¯¯¯¯|
    ZuckerstangeLP
    |_________ .•¯¯¯¯¯¯¯¯¯¯¯¯•. _________|
    *´'`°¤¸¸ .•'´`'•.¸¸ ¤°´'`*
    (_¸.•*´'`°¤¸.¸¤°´'`*•.¸_)

    Youtube Kanal

  • Markier mal die Zeilen, nicht alle kommentieren...

  • achso das meinst du :P


    723: if(newkeys == KEY_SECONDARY_ATTACK)
    725: if(PlayerIsNearToEnterExit(playerid))
    727: for(new i = 0; i <= sizeof(PickUps); i++)
    729: if(PickUps[i] == StehtaufPickUp[playerid])
    731: if(PickUpsCoords[i][Rueck] == false)
    738: else if(PickUpsCoords[i][Rueck] == true)
    749: war ein return :P habe ich gelöscht und der error von 749 war weg^^

    (¯`*•.¸,¤°´'`°¤, ¸.•*´¯)
    ¸,¤°´'`°•.¸¸.•°´'`°¤,¸
    |¯¯¯¯¯¯¯¯¯`•[____________•´¯¯¯¯¯¯¯¯¯|
    ZuckerstangeLP
    |_________ .•¯¯¯¯¯¯¯¯¯¯¯¯•. _________|
    *´'`°¤¸¸ .•'´`'•.¸¸ ¤°´'`*
    (_¸.•*´'`°¤¸.¸¤°´'`*•.¸_)

    Youtube Kanal

  • Gefixxt problem war das dadrüber als ich deins als erstes gemacht habe und 2 klammern dazu gemacht habe ging es =)

    (¯`*•.¸,¤°´'`°¤, ¸.•*´¯)
    ¸,¤°´'`°•.¸¸.•°´'`°¤,¸
    |¯¯¯¯¯¯¯¯¯`•[____________•´¯¯¯¯¯¯¯¯¯|
    ZuckerstangeLP
    |_________ .•¯¯¯¯¯¯¯¯¯¯¯¯•. _________|
    *´'`°¤¸¸ .•'´`'•.¸¸ ¤°´'`*
    (_¸.•*´'`°¤¸.¸¤°´'`*•.¸_)

    Youtube Kanal