Beiträge von IPrototypeI

    Kann man eben nicht, da Pawno kein eigenes PAWN Syntax Highlighting hat sondern das Syntax Highlighting von C/C++, und da ist das kein Keyword.
    Und bei Pawnfox habe ich es vergessen als Keyword zu markieren :D


    Anthrax schon hast du eine idee für ein update von PawnFox ^^ oder du verwendest es privat


    Nun gut zu der Sache zu den Keywords in Notepad ++ wird es angezeigt jetzt für state in pawno habt ihr recht da wird das leider nicht angezeigt
    mein fehler bin gerade nur davon ausgegangen die Datentypen werden auch angenommen char , int , float und co

    Was vorallem wichtig ist:
    Wegen diesem Teil gibt es diese seltsamen "unlösbaren" Errors wenn man eine Variable "state" nennen will...
    Hat mich schon viel Zeit gekostet xD


    xD Keywords werden nicht umsonst blau angezeigt bei pawno. Daher kann man sich schon denken das solch eine bennung einen besonderen stellenwert hat.


    Zum Tutorial muss ich sagen ih kannte das ganze schon seit einer längeren Zeit habe ja auch Kaliber mal darauf auch aufmerksam gemacht :D
    und nutzt es auch in manchen fällen selbst.
    Dein Alltagsbeispiel hättest du anderes gestalten können meiner meinung nach.
    Das man wenn man den o chat aktiviert hat automatisch bei OnPlayerText im o-chat schreibt, wäre meines erachtens sinnvoller gewesen.
    Aber nun gut das kann jeder selbst entscheiden was im zur verwendung sinnvoll erscheint.
    Was mich hier etwas stört ist warum hier auch nicht beschrieben wird warum dies hier schneller ist. Ich mag generell keine Tutorials die
    auf dem "es ist halt so" Aspekt aufbauen.



    Mehr kann man auch nochmal hier nachlesen im "orginalen" Tutorial ( dies hier ist eher mehr eine veranschaulichung)
    http://forum.sa-mp.com/showthread.php?t=86850

    du hast doch schon den verbrauch pro zehntel sekunde teile das durch hundert und multipliziere dies mit der geschwindigkeit.da hebt sich das bei hundert auf bei einer geringeren geschwindigkeit ist der verbrauch geringer und bei einer hoeheren ist der verbrauch groessser

    Nein nicht pro 100KM sondern pro der zentelsekunde.
    Aber der verbrauch wurde in "Liter pro 100KM" angegeben.


    MFG Piet


    also du hast doch eigentlich deine berechnung schon gegeben
    (((Geschwindigkeit[vID])/60)/60)/10;


    damit berechnest du die geschwindigkeit pro 0.1 sekunden das kannst du noch auch mit dem tank machen
    tankverbrauch /6
    (((tankverbrauch/60)/60)/10);
    dan hast du die auch pro 0.1 sekunden es sei den du willst ein realistischen verbrauch errechnen


    //edit


    kw des motors, verbrennwert des benzins, nutzenergie,

    Das ist doch wohl ein schlechter Scherz?


    sowas kannst du unter codeschnipsel posten aber doch nicht als include
    zu dem , wenn du eine richtige include erstellen möchtest dann gedenk sowas auch richtig zu machen
    das hier sind 13 Zeilen bullshit.

    wie macht ihr das eigentlich lädet ihr das von einer datei aus oder ist das im script drin.


    Tut mir leid ich wusste nicht wie dein stock aussieht eine andere möglichkeit wäre es per array zu machen


    enum words
    {
    germantext[64],
    englishtext[64],
    };
    new LanguageInfo[][words] ={
    {"Hallo","Hello"},
    {"How are you?","Wie geht es dir?"}
    };



    stock SendMessage(playerid, color, textid)
    {
    if(GetPVarInt(playerid,"Sprache"))return SendClientMessage(playerid,color,LanguageInfo[textid][germantext]);
    else if(GetPVarInt(playerid,"Sprache")== 2)return SendClientMessage(playerid,color,LanguageInfo[textid][englishtext]);
    return SendClientMessage(playerid,color,"Unknow Text");
    }

    ocmd:tor(playerid,params[]) { if(IsPlayerInFrakt(playerid,2)){ if(IsPlayerInRangeOfPoint(playerid,10,285.82, 1821.20, 20.09))return MoveObject(armytor[0],285.82, 1821.20, 20.09-10,5)return SetTimer("testtimer",5000,true); else if(IsPlayerInRangeOfPoint(playerid,10,135.20, 1941.17, 21.55))return MoveObject(armytor[1],135.20, 1941.17, 21.55-10,5)return SetTimer("testtimer",5000,true); else if(IsPlayerInRangeOfPoint(playerid,10,96.94, 1920.34, 16.58))return MoveObject(armytor[2],96.94, 1920.34, 16.58-10,5)return SetTimer("testtimer",5000,true); else if(IsPlayerInRangeOfPoint(playerid,10,214.6000061,1875.3000488,12.8999996))return MoveObject(armytor[3],214.6000061,1875.3000488,12.8999996-10,5)return SetTimer("testtimer",5000,true); else if(IsPlayerInRangeOfPoint(playerid,10,345.0000000,1797.9000244,20.2000008))return MoveObject(einnahmetor[0],345.0000000,1797.9000244,20.2000008-10,5)return SetTimer("testtimer",5000,true); } return 1; }


    da kannst dies nicht machen ein doppel return


    ocmd:tor(playerid,params[])
    {
    if(IsPlayerInFrakt(playerid,2)){
    if(IsPlayerInRangeOfPoint(playerid,10,285.82, 1821.20, 20.09)){
    SetTimer("testtimer",5000,true);
    return MoveObject(armytor[0],285.82, 1821.20, 20.09-10,5);
    }else if(IsPlayerInRangeOfPoint(playerid,10,135.20, 1941.17, 21.55)){
    SetTimer("testtimer",5000,true);
    return MoveObject(armytor[1],135.20, 1941.17, 21.55-10,5);
    }else if(IsPlayerInRangeOfPoint(playerid,10,96.94, 1920.34, 16.58)){
    SetTimer("testtimer",5000,true);
    return MoveObject(armytor[2],96.94, 1920.34, 16.58-10,5);
    }else if(IsPlayerInRangeOfPoint(playerid,10,214.6000061,1875.3000488,12.8999996)){
    SetTimer("testtimer",5000,true);
    return MoveObject(armytor[3],214.6000061,1875.3000488,12.8999996-10,5);
    }else if(IsPlayerInRangeOfPoint(playerid,10,345.0000000,1797.9000244,20.2000008)){
    SetTimer("testtimer",5000,true);
    return MoveObject(einnahmetor[0],345.0000000,1797.9000244,20.2000008-10,5);
    }
    }
    return 1;
    }


    MoveObject zu returnen geht auch nur da es OnPlayerCommandText egal ist was er zurück bekommt außer
    es ist eine float oder ein string.
    Zu dem bist du dir sicher das du jedesmal ein Timer aufrufen willst dieser wiederholt sich


    entferne doch bitte die unnötige klammern


    ocmd:tor(playerid,params[])
    {
    if(IsPlayerInFrakt(playerid,2)){
    if(IsPlayerInRangeOfPoint(playerid,10,285.82, 1821.20, 20.09))return MoveObject(armytor[0],285.82, 1821.20, 20.09-10,5);
    else if(IsPlayerInRangeOfPoint(playerid,10,135.20, 1941.17, 21.55))return MoveObject(armytor[1],135.20, 1941.17, 21.55-10,5);
    else if(IsPlayerInRangeOfPoint(playerid,10,96.94, 1920.34, 16.58))return MoveObject(armytor[2],96.94, 1920.34, 16.58-10,5);
    else if(IsPlayerInRangeOfPoint(playerid,10,214.6000061,1875.3000488,12.8999996))return MoveObject(armytor[3],214.6000061,1875.3000488,12.8999996-10,5);
    }
    return 1;
    }

    Dann benutz AddStaticVehicleEx oder CreateVehicle und setzt den letzen parameter auf -1
    da AddStaticVehicle eigentlich eine respawn delay von 15 minuten hat , wenn es nicht besetzt ist .




    Guten Tag liebe Leser dieses Tutorial.
    Diesen Tutorial befasst sich mit dem erstellen eines Zollsystems , welches sehr einfach erweiterbar ist in der hinsicht auf
    weitere
    Zollschranken. Zu dem wird hier auch noch gezeigt wie man diese
    Zollschranken auch ganz einfach per Dialog verschließen kann.


    Da dies mein erstes Tutorial ist , welches ich als offizielles Tutorial hier in diesem Bereich
    zur Verfügung stelle. Möchte ich zu mal die Schwierigkeitgrade der System, welche hier wo möglich noch von
    mir beschrieben und vorgestellt werden erläutern.Dies soll dazu dienen das
    man weiß, ob man mit diesem Tutorial auf Grund seiner eigenen Leistungen
    bewältigen kann und somit noch was dazu lernt.Mein Ansicht ist dazu das es nichts
    bringt , wenn man ein Tutorial absolvierr, da man nicht
    weiß was man macht beziehungsweise nicht weiß , welche Elemente genau dafür benutzt werden und warum.


    [tabmenu]


    [tab='Einsteiger']
    Wenn man frisch in PAWN ist, so bist du bei solch einem Tutorial genau richtig hier werden
    nicht so fortgeschrittenere Themen aufgezogen und sämtliche
    Funktionen/Callbacks/Operator... und ihre funktionen werden hier genau
    erklärt und verdeutlicht.
    [tab='Anfänger']
    Solltest du schon ein bisschen Ahnung haben von PAWN von den
    Callbacks/Funktionen/Operator und den meisten Keywords haben so bist du
    bei diesen Schwierigkeitsgrad genau richtig. Hier werden nur untypische Verwendungen Erklärt.
    [tab='Fortgeschritten']
    Solltest du Ahnung von PAWN haben den meisten
    Callbacks/Functionen/Operator/Keyword .. haben so bist du bei diesem
    Schwierigkeitsgrad genau richtig.
    Hier heißt es selbst mit denken sehr schwierge Bereiche werden
    angesprochen die meist in Ausnahmefällen ihre ständige verwendet
    erfordert.
    [/tabmenu]




    [tabmenu]


    [tab='Bilder']

    Bilder









    [/tabmenu]


    Inhaltsverzeichniss


    • 1.0 Vorraussetzungen
    • 1.1 Basis zum Zollsystem
    • 1.2 Erstellen der Zollschranken zum Zollsystem
    • 1.3 Command zum Zollsystem
    • 1.4 Timer für die Zollschranken
    • 2. Command zum schließen der Zollschranken | Aufruf des Dialoges
    • 2.1 Dialog zum schließen/öffnen der Zollschranken

    Vorraussetzungen

    Bevor wir Anfangen benötigen wir erstmal 2 Plugins das sscanf & streamer plugin , welche auf folgenden Link zu finden sind

    1.1 Basis zum Zollsystem


    Nun erstellen wir erstmal die Basis. Dazu benötigen wir zu mal ein enum, welches als index für das folgende 2D Array dient.

    Das enum beinhaltet 12 Floats da wir die X- Koordinate, Y- Koordinate, Z- Koordinate, RoatationX- Koordinate,

    RoatationY- Koordinate und die RoatationZ- Koordinate brauchen und dies zwei mal da wir in das Array die
    Position des
    Zollschranken eintragen einmal geschlossen und einmal offen.
    zObject wird für die Modelid genutzt und zID ist nicht umbedingt nözig jedoch

    schreibe ich dies einfach dazu da wir die ID des Objektes in einer Variabel speichern müssen,
    um das Object mit MoveDynamicObject zu verschieben.

    zState ist der Status der Zollschranke, welchen wir abfragen werden beim "/zoll" Befehl damit das Skript
    erkennt das die jeweiligen Zollschranke gesperrt ist.



    Nun
    haben wir den Index für die zweite Dimension des Arrays , welches wir
    natürlich auch nun erstellen. Der Vorteil mit einem Array zu arbeiten in
    diesem falle
    ist das dies sehr übersichtlich ist und somit kann man neue Zollschranken ganz leicht hinzufügen mit nur einer Zeile.


    Code
    new ZollInfo[MAX_ZOLLGATES][zollsys] = {
    {0,978,53.61148071,-1525.98864746,4.87745094,0.00000000,0.00000000,83.37002563,53.61148071,-1525.98864746,-6.87745094,0.00000000,0.00000000,83.37002563,false},
    {1,978,55.77261353,-1539.03112793,4.95321989,0.00000000,0.50000000,79.91503906,55.77261353,-1539.03112793,-6.95321989,0.00000000,0.50000000,79.91503906,false},
    };


    Wie
    man hier schon sieht habe ich schon zwei Tore hinzugefügt und es
    existiert hier schon MAX_ZOLLGATES was man natürlich noch definieren
    muss mit

    Code
    #define MAX_ZOLLGATES (Toranzahl)


    in meinem Falle

    Code
    #define MAX_ZOLLGATES (2)


    Die
    defines sind konstante Werte und existieren beim Kompielen in der AMX
    nicht mehr da diese ersetzt werden durch den Wert, String , Code oder
    Farbcode, welcher sich dahinter verbirgt.


    Beispiel:

    Code
    for(; i < MAX_ZOLLGATES; ++i)


    wird zu

    Code
    for(; i < 2; ++i)


    Die Klammern sind nicht nötig beim deklarieren von Zahlen.
    Was
    man jedoch auch noch zum Thema Array wissen sollte ist, das dies
    weniger Memory verbraucht als das deklarieren von mehreren Variabeln.
    Der Grund dafür ist das Arrays beim compilen keine einzelne Zeile einnimmt pro Wert.

    Code
    new array[5] ={1, ...};
    1,1,1,1,1


    Code
    new var1=1,var2=1,var3=1,var4=1,var5=1;
    1
    1
    1
    1
    1


    1.2 Erstellen der Zollschranken zum Zollsystem


    So
    nun haben wir das Array mit den Toren nun sollten diese auch erstellt
    werden unter OnGameModeInit dies tuhen wir mit einer for-Schleife(loop).


    Code
    new i;
    for(;
     i < MAX_ZOLLGATES; ++i)ZollInfo[i][zID] = 
    CreateDynamicObject(ZollInfo[i][zObject],ZollInfo[i][zCX],ZollInfo[i][zCY],ZollInfo[i][zCZ],
    ZollInfo[i][zCRx],ZollInfo[i[zCRy],ZollInfo[i][zCRz]);


    Was
    man hier sieht ist das , das i außerhalb der for-schleife deklariert
    habe. Was bewirken soll, dass die for-Schleife schneller ist. Ob dies
    der fall ist
    garantiere ich nicht jedoch war dies bei mir so nach
    mehreren Tests, dass diese Art der For-schleife schneller war, als die
    alt bekannte Variante
    for(new i; i < MAX_ZOLLGATES; ++i). Jetzt
    werden sich auch bestimmt ein paar Fragen warum ++i und nicht i++ das
    ist in PAWN Leider das selbe.
    Normal ist das erhöhen von einem Werte
    mit ++i dem Inkrement Operator schneller als mit dem Dekrement Operator,
    da der Postfix-Version
    eine Kopie von sich anlegen, erst dann kann sie sich Inkrementieren. Das muss die Präfix-Version nicht daher ist sie schneller.
    Jedoch gilt dies nicht meines Erachtens in PAWN.


    1.3 Command
    zum öffen/schließen der Zollschranken



    Zum Befehl hin könnt ihr natürlich auch einen Commandprozessor verwenden ob YCMD, ZCMD , RCMD , OCMD ... es ist völlig egal,
    jedoch gibts hier unterschiede in der Geschwindigkeit. Der schnellste Commandprozessor ist YCMD.
    Nun mal zum Aufruf des Befehls allgemein mit strcmp.
    Es gibt ja viele möglichkeiten dies zu tun

    Code
    if (!strcmp(cmdtext,"/zoll"))


    Code
    if (!strcmp(cmdtext,"/zoll", true))


    Code
    if (strcmp("/zoll", cmdtext, true, 5) == 0)


    Aber warum geht den dies überhaupt mit dem Ausrufezeichen (!) ?


    Es geht daher, da es wie bei jedem anderen code auch die selbe abkürzung für 1 ist. Was meine ich damit genau ?

    Code
    new var = 1; 
    if(var){ 
    
    
    }


    Hier sieht man die vereinfachung von

    Code
    if(var == 1)


    Also sähe das ursprünglich bei dem strcmp befehl so aus

    Code
    if (!strcmp(cmdtext,"/zoll", true) == 1)


    beziehungsweise in der richtigen Form

    Code
    if (strcmp(cmdtext,"/zoll", true) != 1)


    Also alles außer 1 und da strcmp beim Vergleich unterschiedliche werte zurück gibt, wie sollte der string identisch sein so wird der wert 0 wieder gegeben.
    Daher kann man sich merken sollte eine Funktion die man benutz oder eine Variabel den wert 1 haben so
    ist dies die mögliche Abfrageform.


    Nun gehen wir zum weiteren Teil des Command hier wird eine for-schleife benutzt die durch die ganzen Werte geht , welche in de Array enthalten sind.
    Manche werden sich bestimmt fragen, warum hier ein boolean benutz wird. Nun gut lasst es mich erklären. Ich benutze dies um
    falls der Spieler nicht in der nähe einer Zollschranke ist zum Schluss die Nachricht auszugeben das der Spieler nicht am Zollschranke ist.
    Daher wird der wert das Boolean auf den wert true gesetzt und wie man vorher lernen konnte ist dies auch dies zum Schluss eine mögliche Abfrageform ob der Wert 1 ist.
    Sollte dies sein, so bekommt der Spieler die Nachricht. Nun sollte der Spieler an einer Zollschranke sein
    so wird der Code an der Stelle abgebrochen und daher auch der Wert auf 0 gesetzt in dem Falle hier false. (false = 0 | true = 1)
    Nun beim Timer ist dies so das hier die Ordnungszahl des jeweiligen Tores an das public per SetTimerEx übergeben wird.
    Was man hier noch von eurer Seite hinzufügen kann ist das automatisch beim betätigen des Command der jeweilige Timer Abgebrochen
    und danach neu Aufgerufen wird, dass hätte den Vorteil ,das nicht aufeinmal die Zollschranke zu geht nachdem man die Zollgebühr bezahlt hat.
    Aber ich hab dies mit absicht weg gelassen. Sollte jemand das Tutorial bis hier in ausführlich gelesen haben so ist er auch dementsprechend
    informiert und sollte/könnte dies auch noch hinzufügen.







    1.4 Timer zum schließen der Zollschranke







    Code
    forward CloseZollGate(zollid); 
    public CloseZollGate(zollid) MoveDynamicObject(ZollInfo[zollid][zID],ZollInfo[zollid][zCX],ZollInfo[zollid][zCY],ZollInfo[zollid][zCZ],2.0,ZollInfo[zollid][zCRx],ZollInfo[zollid][zCRy],ZollInfo[zollid][zCRz]);


    Hier wird die Zollschrank auf ihre ursprünglich Position gesetzt. Man braucht dafür keine Klammern solang nur einmal
    ein Aufruf einer Funktion statt findet oder die Veränderung eines Wertes usw... .


    Daher ist sowas auch möglich man kann sich somit auch die Klammern sparen

    Code
    for(new i; i < MAX_PLAYERS; ++i)if(IsPlayerConnected(i))SetPlayerPos(i,0.0,0.0,0.0);


    geht auch so


    Code
    for(new i; i < MAX_PLAYERS; ++i) 
    	if(IsPlayerConnected(i)) 
       	SetPlayerPos(i,0.0,0.0,0.0);


    Das macht jedoch kein Unterschied zur Benutzung mit Klammern in dem Fall.





    Command zum schließen der Zollschranke






    Code
    else if (!strcmp(cmdtext,"/cgate")){ 
    ShowPlayerDialog(playerid,DIALOG_CLOSE_ZOLL,DIALOG_STYLE_LIST,"Zollverwaltung",ZOLLCSTRING,"Auswählen","Schließen"); 
    return 1; 
    }



    Nun gut hier wird ein Dialog aufgerufen mit der jeweiligen ID, welche wir mit einem #define festgelegt haben. Da ich mir noch was kleines Einfallen lassen hab verwenden wir hier einen schlauen String "ZOLLCSTRING". Der ist in sofern schlau da er die größe des String beim compilen festlegt. Daher auch

    Code
    new ZOLLCSTRING[(MAX_ZOLLGATES*50)];


    Beim compilen multipliziert er 50 mit der Anzahl von MAX_ZOLLGATES sollte dies 2 Sein so ist der String 100 Zeichen groß.


    Jedoch das der string das was wir wollen enthält so müssen wir den String natürlich erstmal formatieren

    Code
    stock ZollDialogText() 
    { 
    strdel(ZOLLCSTRING,0,sizeof(ZOLLCSTRING)); 
    new i; 
    for(; i < MAX_ZOLLGATES; ++i)format(ZOLLCSTRING,sizeof(ZOLLCSTRING),"%s{FFFFFF}Zoll %d | %s\n",ZOLLCSTRING,i,((ZollInfo[i][zState])?("{FF0000}geschlossen"):("{00FF00}offen"))); 
    }


    Dazu will ich noch anmerken das man 1 String für alles benutzen kann solange man ihn vor der Verwendung leert.
    Um vorzubeugen das andere Elemente doch im string enthalten sind. Da hier der string formatiert werden muss wegen dem Status der Schranke ist man gezwungen format zu benutzen sollte dies nicht der Fall sein so empfehle ich die string Functionen zu benutzen da dies meist schneller sind als format.


    Tja wenn es bei mir nicht geht kann ich ja nix falsches machen ?



    Da liegt du, aber sehr falsch was ist daran so schwer



    hier das boolean zu defineirt zu haben


    new bool:unwanted[MAX_VEHICLES];


    und drunter den command


    ocmd


    ocmd:autorspawn(playerid,params[])
    {
    new string[128], i;
    if(!IstSpielerAdmin(playerid,2))return SendClientMessage(playerid,ROT,"[System]Du bist nicht berechtigt diesen Befehl zu benutzen !");
    for(; i <MAX_PLAYERS; i++)if(IsPlayerInAnyVehicle(i))unwanted[GetPlayerVehicleID(i)]=true;
    for(i =0; i < MAX_VEHICLES; i++)if(!unwanted[i]) SetVehicleToRespawn(i);
    GetPlayerName(playerid, sendername, sizeof(sendername));
    format(string, sizeof(string), "AdminSystem: Alle unbesetzten Autos wurden zurückgespawnt von %s.", sendername);
    BroadCast(COLOR_RED,string);
    return 1;
    }


    oder von mir aus auch so ist ja nicht mein skript


    ocmd:autorspawn(playerid,params[])
    {
    new string[128], i, bool:unwanted[MAX_VEHICLES];
    if(!IstSpielerAdmin(playerid,2))return SendClientMessage(playerid,ROT,"[System]Du bist nicht berechtigt diesen Befehl zu benutzen !");
    for(; i <MAX_PLAYERS; i++)if(IsPlayerInAnyVehicle(i))unwanted[GetPlayerVehicleID(i)]=true;
    for(i =0; i < MAX_VEHICLES; i++)if(!unwanted[i]) SetVehicleToRespawn(i);
    GetPlayerName(playerid, sendername, sizeof(sendername));
    format(string, sizeof(string), "AdminSystem: Alle unbesetzten Autos wurden zurückgespawnt von %s.", sendername);
    BroadCast(COLOR_RED,string);
    return 1;
    }


    Da sollte man ein wneig englisch kenntnisse besitzen so würde man wissen das der Error


    error 017: undefined symbol "unwanted"


    darauf zurück zu führen ist das unwanted nicht im skript existiert es wurde nicht definiert oder auch vom kompiler dan nicht erkannt , weil wahrscheinlich
    die definition unter dem command ist oder sonst drunter

    ich bräuchte eig nur die titel aber großen dank :)


    Ich möchte dir noch einen Tipp mit geben falls du nach weitere audiostreams suchst :
    1. Meist sind die Streams schon angeben auf der Seite
    2. Du kannst manche audiostreams per Winamp oder Windowsmediaplayer abspielen dort kannst du auf Titelinfo gehen dort wird somit
    auch der stream angezeigt
    3. Seitenquelltext anzeigen lassen und mal sich mal ein bissle durchklicken bei den quellcodes von den javascripts
    4. Es gibt programm die jegliche links locken welche aufgerufen werden sowas kannst auch benutzen

    Ich hab es genau da so stehen und es geht bei mir ;)


    Mann sollte nur anmerken das dem Großteil solcher Leute , welche nach sowas fragen Beispiel: der Threadersteller es an geistiger Kompetenz mangelt
    new bool:unwanted[MAX_VEHICLES];


    entweder über dem Befehl du deklarieren oder es direkt unter den ganzen anderen Deklarationen von Variabeln und Co in einem GF-skript hinzuzufügen.