Nützliche Stocks | Kleinigkeiten, um dem Scripter einiges zu vereinfachen

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
  • Hallo,


    Ich möchte euch gerne einige Stocks von mir vorstellen,
    die ich schon eine Zeit lang nutze, mit denen ich mir so einiges
    vereinfache.
    Worin liegen nun die vereinfachungen? Überwiegend geht
    es um die Menge des schreibens, warum 10x hintereinander den selben Code
    aufschreiben, wenn man
    ihn doch hübsch als Stock verpacken kann?
    Sämtliche Stocks sind von mir, aber ihr dürft sie natürlich verändern und bearbeiten, also ich erhebe keinerlei Urheberrechte!




    PlaySound

    Als erstes gibt es den Stock: "PlaySound".
    Er
    erinnert sehr an den Befehl 'PlayerPlaySound' und er ist es
    letztendlich auch, nur etwas präperiert . Mich hat es unheimlich
    genervt, dass ich andauernd, nur um
    mal einen Sound abzuspielen die
    Position des Spielers erfassen muss und das raubt wertvolle Zeit, gerade
    wenn man nur kurz etwas ändern will!


    stock PlaySound(playerid,soundid)
    {
    new Float:X,Float:Y,Float:Z;
    GetPlayerPos(playerid,X,Y,Z);
    PlayerPlaySound(playerid,soundid,X,Y,Z);
    return 1;
    }


    Wie
    verwende ich nun diesen Stock? Einfacher geht es nun wirklich nicht,
    einfach die jeweilige playerid einfügen und danach die SoundID un das
    war es auch schon!



    GetSpielerName


    Als nächstes gibt es den Stock: "GetSpielerName"
    Ganz
    schnell erklärt, er gibt den Spielernamen der jeweiligen PlayerID
    wieder. Dies ist gut zu verwenden, wenn man eh schon Strings formatiert
    und darin gerne einen Spielernamen
    einbinden möchte, weiter unten ein Beispiel dafür!


    stock GetSpielerName(playerid)
    {
    new name[MAX_PLAYER_NAME];
    GetPlayerName(playerid,name,sizeof(name));
    return name;
    }


    Mehr zauber ist da auch nicht hinter ^^
    Nun ein Beispiel zur verwendung:


    new TestString[128];
    format(TestString,sizeof(TestString),"Der Spieler %s möchte gerne einen Keks haben!",GetSpielerName(playerid));


    Achtung! Trotz allem gibt es eine bessere Methode den selben Effekt zu erzeugen! Meine Methode stammt noch aus meinen Anfangsjahren, also solltet
    ihr besser die folgende Verwenden.


    Definiert ganz oben dieses:


    new UserName[MAX_PLAYERS][MAX_PLAYER_NAME];


    Geht als nächstes unter OnPlayerConnect und schreibt dort dieses hinein:


    GetPlayerName(playerid,UserName[playerid],MAX_PLAYER_NAME);


    So nun könnt ihr den Spielernamen abfragen auch ohne den oben genannten Stock. An der Stelle danke an Beavis und BlackAce!


    format(TestString,sizeof(TestString),"Der Spieler %s möchte gerne einen Keks haben!",UserName[playerid]);



    GivePlayerSaveWeapon


    Weiter geht es mit einem etwas komplexeren Stock, der aber dafür zusätzliche Sicherheit garantiert! Dem Stock "GivePlayerSaveWeapon"
    Grundgedanke
    war, dass es dem durchschnittlichen Cheater/Hacker oder auch Buguser
    schwerer fällt an Waffen zu kommen. Ich erkläre nun kurz das System. Waffen
    werden nun nicht weiter mit GivePlayerWeapon vergeben, sondern ab nun
    mit diesem Stock! Das einzige das ihr dafür tun müsst, ist:



    GivePlayerSaveWeapon//anstatt
    GivePlayerWeapon


    Hier nun der fertige Stock, aber achtung, es gehört noch mehr dazu, sonst erlebt ihr später eine Böse Überraschung!


    stock GivePlayerSaveWeapon(playerid,weaponid,ammo)
    {
    GivePlayerWeapon(playerid,weaponid,ammo);
    SetPVarInt(playerid,"SaveWeapon",1);
    return 1;
    }


    Hier
    wird lediglich dem Spieler die Waffe mit der gewünschten Munition
    gegeben. Außerdem wird die PVar "SaveWeapon" auf 1 gesetzt, damit hat
    der Spieler die Erlaubnis eine Waffe
    zu besitzen! Nun möchte man noch, dass der Spieler gekickt wird, wenn er trotz der fehlenden Erlaubnis eine Waffe bekommt!
    Dieses hier am besten unter "OnPlayerUpdate"!


    if(GetPlayerWeapon(playerid)!=0)
    {
    if(GetPVarInt(playerid,"SaveWeapon")!=1)return Kick(playerid);
    return 1;
    }


    Der
    Spieler sollte auf jeden Fall nur gekickt oder entwaffnet werden. Denn
    es können immer wieder Bugs oder Fehler auftreten und dann ist ein
    Spieler zu unrecht gebannt!
    Nun muss noch unbedingt unter
    "OnPlayerDeath" oder auch an jede Stelle, an der der Spieler seine
    Waffen entzogen bekommt, beispielsweise durch "ResetWeapons", die PVar
    wieder auf 0 gesetzt werden!


    SetPVarInt(playerid,"SaveWeapon",0);



    Achtung!
    Ihr solltet auf jeden Fall das ganze Script überprüfen, ob ihr nicht
    doch noch irgendwo GivePlayerWeapon anstatt GivePlayerSaveWeapon gesetzt
    habt. Hier kann
    die Replacefuntkion Abhilfe schaffen! Außerdem solltet ihr die gesamten Codes noch etws anpassen!



    MeAction


    Der
    Nächste Stock ist eine kleine Erleichterung für alle, die ein Reallife
    Script oder ähnliches betreiben. Hier fügen wir eine komplett neue
    Funtkion mithilfe eines Stock ein,
    nämlich "MeAction"!
    Es
    Hilft wirklich sehr, man möchte ja einerseits nicht, dass man andauernd
    diese langen Codezeilen an jeder Stelle hat und andererseits nervt es
    wirklich andauernd das
    selbe Tippen zu müssen^^. Mit MeAction wird
    eine Nachricht vom Spieler an alle, die sich in einem bestimmten Umkreis
    vom Spieler befinden, gesendet.


    stock MeAction(playerid,msg[])
    {
    new Float:X,Float:Y,Float:Z,meactstring[350];
    GetPlayerPos(playerid,X,Y,Z);
    format(meactstring,sizeof(meactstring),"* %s %s",GetSpielerName(playerid),msg);
    PlaySound(playerid,1138);
    for(new i=0; i<MAX_PLAYERS; i++)
    {
    if(IsPlayerInRangeOfPoint(i,20,X,Y,Z))//ggf. die Range (hier im Falle die 20) anpassen!
    {
    SendClientMessage(i,0xFF00E1FF,meactstring);
    }
    }
    return 1;
    }


    Nun
    wird diese Nachricht in einem wunderschönen Lilaton, der gar nicht
    stört^^, an alle Spieler geschickt, die sich in einem Umkreis von 20 San
    Andreas Einheiten um ihn befinden.
    Ihr musst dann noch lediglich an die entsprechenden Stellen dies einfügen:


    MeAction(playreid,"beginnt zu husten");
    der Output sähe dann so aus!
    * [Spielername] beginnt zu husten


    Ich hoffe ich konnte euch einige Stocks schmackhaft machen, danke für das Lesen des Threads :D


    MfG KTP

    Einmal editiert, zuletzt von KTP ()

  • Als nächstes gibt es den Stock: "GetSpielerName"
    Ganz
    schnell erklärt, er gibt den Spielernamen der jeweiligen PlayerID
    wieder. Dies ist gut zu verwenden, wenn man eh schon Strings formatiert


    Was ist daran Gut zu verwenden wenn du dafür eine Extra Funktion machst?
    Am einfachsten ist immernoch oben das hinzuschreiben:
    new UserName[MAX_PLAYERS][MAX_PLAYER_NAME];
    OnPlayerConnect dann das
    GetPlayerName(playerid,UserName[playerid],MAX_PLAYER_NAME);
    Aufruf in Strings etc
    format(TestString,sizeof(TestString),"Der Spieler %s möchte gerne einen Keks haben!",UserName[playerid]);


    Spart Zeit und es ist schonender für den Server

    All in all it's just another brick in the wall

  • es ist schonender für den Server

    Das ist relativ zu sehen. Du belastest mit der Erstellung der Variable UserName den Server im vorraus egal ob jemand Online ist oder nicht bei einem Stock ist das ganz anders der wird erst verwendet wenn er benötigt wird also bei 5 von 500 Spielern bezweifel ich das deine Version besser ist (Man muss jetzt natürlich auch schauen wie oft der Stock im Script verwendet wird etc.)

  • Du belastest mit der Erstellung der Variable UserName den Server im vorraus egal ob jemand Online ist oder nicht bei einem Stock ist das ganz anders der wird erst verwendet wenn er benötigt wird also bei 5 von 500 Spielern bezweifel ich das deine Version besser ist (Man muss jetzt natürlich auch schauen wie oft der Stock im Script verwendet wird etc.)


    Du willst uns hier also erzählen, das es mehr Sinn macht den Server mehr als einmal mit dem herausfinden des Spielernamens zu belasten?


    Der Server muss ständig anfragen gegenüber dem Clienten machen wie der User denn jetzt heißt.
    Meinst du das macht ernsthaft Sinn, den Traffic und die CPU dadurch zu belasten?


    Warum sollte man nicht direkt auf den RAM zugreifen, der dort viel schneller agieren kann?
    Zu dem kann man darüber sogar feststellen ob ein Spieler online ist, d.h. ich muss nicht über IsPlayerConnected gehen.


    Zudem kosten Funktionsaufrufe Zeit, die in manchen Teilen ausschlaggebend sein können :thumbup:

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

    Margarete Stokowski

  • do.de - Domain-Offensive - Domains für alle und zu super Preisen
  • Ich hab hier noch eine schöne Funktion mit der man eine zufällige Zahl in einem definierten Bereich erstellen kann.


    Anwendung: randomEx(minval, maxval);



    stock RandomEx (miv, mav)
    {
    return (random (mav - miv) + miv);
    }

    Erfahrung ist der beste Lehrmeister. Nur das Schulgeld ist teuer.
    Thomas Carlyle (1795-1881)

  • Ich wollte mich nicht auf die Geschwindigkeit beziehen sondern auf den Speicher.


    Nunja, du belegst auch dauerhaft während der Runtime Speicher.
    Ob ich mir den jetzt zur Laufzeit immer wieder initialisieren muss oder gleich am Anfang ist wieder ein Spiel der Geschwindigkeit.

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

    Margarete Stokowski

  • Der Server muss ständig anfragen gegenüber dem Clienten machen wie der User denn jetzt heißt.
    Meinst du das macht ernsthaft Sinn, den Traffic und die CPU dadurch zu belasten?


    Wenn alle *Get...*-Funktionen Anfragen an den Clienten erzeugen würden, dann würde SA-MP nicht funktionieren. All diese Daten hat der Server schon im Speicher (gibt sie lediglich zurück)


    mit eurer Logik müsste man dann ja ALLE *Get...*-Funktionen(die sich nicht ständig ändern, und das sind viele) in Variablen zwischenspeichern :whistling:
    Für mich ist das nur sparen an falscher Stelle.


    //Goldkiller: Danke für deinen Beitrag.

  • Der Server muss ständig anfragen gegenüber dem Clienten machen wie der User denn jetzt heißt.
    Meinst du das macht ernsthaft Sinn, den Traffic und die CPU dadurch zu belasten?

    Warum sollte der Server bei jedem GetPlayerName() erst eine Anfrage an den Clienten des Spielers schicken?
    Spielername und restliche Informationen wie IP werden bereits beim Verbindungsaufbau definiert. Wo kämen wir denn hin, wenn der Client mitten im Spiel einfach solche Informationen ändern könnte und diese dann auch mit dem Server synchronisiert werden würden?

    Warum sollte man nicht direkt auf den RAM zugreifen, der dort viel schneller agieren kann?

    Durch den Funktionsaufruf GetPlayerName() wird auch ausschließlich auf den RAM zugegriffen, das einzige was die ganze Sache marginal langsamer macht (ich rede nicht von Benchmarks, sondern vom normalen Serverbetrieb), ist der durch den Funktionsaufruf (stock GetSpielerName()) und dem damit verbundenen Aufruf der AmxNative entstehende Overhead.


    btw: Trotzdem bin ich der Meinung, dass man den Spielernamen in einem Enum speichern sollte :D


    //edit: Da war d0. wohl schneller :(

  • Ich finde PlaySound unnötig, in dem Sinn wie du die Funktion vorstellst.
    Man muss nicht die Position des Spielers rausfinden, wenn der Sound für den Spieler abgespielt werden soll, unabhängig davon wo er gerade ist.
    Es reicht wenn man dort als Position nur 0.0 angibt. Bsp: PlayerPlaySound(playerid, 1130, 0.0, 0.0, 0.0);
    Wenn du nun aber den "Ton" 10 Meter weiter weg von ihm abspielen möchtest, dann braucht man die Coordinaten.


    Steht übrings auch im Wiki ;)
    http://wiki.sa-mp.com/wiki/PlayerPlaySound


  • http://wiki.sa-mp.com/wiki/Function:SendClientMessage

    Zitat

    Important Notes:


    If a message is longer than 144 characters, it will not be sent. Truncation can be used to prevent this. Displaying a message on multiple lines will also solve this issue.


    Daher ist "meactstring[350]" zu groß. Die Nachricht wird eventuell nicht gesendet und ist um etwas mehr als 200 Zellen zu groß.


    //Edit: Bevor ich es vergesse : [ SCRIPTING ] Der Mythos "stock"

    Spoiler anzeigen
    Hast dich für das Tutorial qualifiziert :)