TDM-Gamemode [Teil1]

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, und willkommen zu meinem ersten Tutorial! Ich möchte in diesem Tutorial zeigen, wie man einen simpelen TDM-Gamemode scriptet. Dieses Tutorial ist vorallem an Anfänger gerichtet, die noch keinen richtigen Gamemode gescriptet haben sondern jediglich die Grundlagen kennen. Also, fangen wir an!


    Das Grundgerüst


    Zuallererst erstellen wie einen neuen Gamemode. Die Callbacks "OnFilterScriptInit()" und "OnFilterScriptExit()" können wir problemlos entfernen, da es sich ja um einen Gamemode handelt. Der Code, der bei "OnGameModeInit()" miterstellt wird, kann bis auf das "return 1;" entfernt werden. Dort fügen wir zuerst unsere "Spielerklassen" ein, also die Figuren, die man dann im Spiel auswählen kann. Dazu benötigen wir zuerst die Postion, an der die Spielerfigur spawnen; also wo man nach der Figurauswahl steht; soll. Diese können wir ingame mit dem Befehl "/save", der auf jedem Server vorhanden ist, abspeichern. Es empfiehlt sich, nach "/save" noch zu schreiben, um was es sich für eine Postion handelt. Dies ist bei größeren Mengen an gespeicherten Postionen natürlich von Vorteil. Also z. B. "/save Ballas Spawn". Die Postionen werden dann in eurem GTA San Andreas Ordner in der Datei savedpositions.txt gespeichert. Wenn ihr die Datei nun öffnet, könnte es so aussehen:

    AddPlayerClass(288,1939.2563,-1117.9183,26.4455,179.6119,0,0,0,0,0,0); // Ballas Spawn

    Beim 2.,3. und 4. Parameter kann man die Koordinaten ablesen. Beim 5. Parameter kann man die Richtung ablesen. Nun haben wir also die Koordinaten + Richtung. Nun kehren wir wieder zu unserem Pawn-Editor zurück und fügen bei OnGameModeInit folgende Zeilen ein:

    AddPlayerClass(105,2511.2092,-1688.0992,13.5621,44.2817,24,60,26,100,18,8); // grove1
    AddPlayerClass(106,2512.6931,-1672.5791,13.5036,66.8167,6,1,31,400,22,80); // grove2
    AddPlayerClass(107,2517.3416,-1661.4232,14.2167,100.0303,32,550,23,50,4,1); // grove3
    AddPlayerClass(102,1910.1559,-1123.0077,25.5906,183.7904,24,60,26,100,18,8); // ballas1
    AddPlayerClass(103,1939.0726,-1114.7036,27.4523,178.7263,6,1,31,400,22,80); // ballas2
    AddPlayerClass(104,2002.9470,-1115.9773,27.1250,181.3781,32,550,23,50,4,1); // ballas3

    Wie ihr seht, habe ich ein bisschen vorgearbeitet und schon viele Postionen gesaved. Ihr seht, dass beim ersten Parameter verschiedene Zahlen sind. Es handelt sich hierbei um SkinIDs. Jeder Skin (=Spielerfigur) hat eine eigene ID, mit der man sie bestimmen kann. Alle SkinIDs findet ihr hier. Aber wofür sind die 6 letzten Parameter? Sie sind dafür da, um den Spielerfiguren Waffen zu geben! Somit wissen wir nun, wie AddPlayerClass aufgebaut ist, nämlich so:

    AddPlayerClass(SkinID,x,y,z,richtung,WaffenID1,Munition1,WaffenID2,Munition2,WaffenID3,Munition3);

    Aber woher bekommen wir nun die WaffenIDs? Genauso einfach wie bei den SkinIDs!Nämlich hier! Wenn ihr also wollt, dass der Spieler eine 9mm mit 20 Schuss bekommt, ist WaffenID1 = 22 und Munition1 = 20! Nun haben wir schon verschiedene Spielerklassen. Das einzige Problem: Wir sehen bei der Spielerauswahl unseren Skin nicht! Das ist natürlich ein wenig blöd. Wir entfernen also nun den vorgefertigten Code beim Callback "OnPlayerRequestClass()" bis auf das "return 1;" und fügen nun folgende Abfragen ein:

    if (classid == 0) //grove1
    {
    }
    if (classid == 1)//grove2
    {
    }
    if (classid == 2)//grove3
    {
    }
    if (classid == 3)//ballas4
    {
    }
    if (classid == 4)//ballas5
    {
    }
    if (classid == 5)//ballas6
    {
    }

    "Wozu brauche ich für jede classid eine Abfrage?", fragt ihr euch vielleicht. Wenn ihr meine Spielerklassen verwendet, werdet ihr sicherlich bemerkt haben, dass jede Spielerfigur eine andere Postion hat. Somit muss die Kamera ihre Position/Richtung auch jedesmal ändern, damit wir unsere ausgewählte Spielerklasse sehen. Dies macht SAMP allerdings nicht von alleine. Deshalb gibt es die Funktionen SetPlayerCameraPos(playerid, x,y,z) (Ändert die Postion der Kamera auf x,y,z) und SetPlayerCameraLookAt(playerid,x,y,z); (Lässt die Kamera auf die Postion x,y,z gucken). Ich habe eine kleine Grafik erstellt, um das ganze etwas anschaulicher zu erklären. Diese findet ihr hier. Kümmern wir uns zuerst um die erste if-Abfrage, also grove1:

    if (classid == 0) //grove1
    {
    SetPlayerPos(playerid, 2511.2092,-1688.0992,13.5621);
    SetPlayerFacingAngle(playerid,44.2817);
    SetPlayerCameraPos(playerid, 2508.6785,-1685.8330,13.5628);
    SetPlayerCameraLookAt(playerid, 2511.2092,-1688.0992,13.5621);
    }

    Eventuell etwas verständlicher:

    if (classid == 0) //grove1
    {
    SetPlayerPos(playerid, x,y,z); //x,y,z = Postion auf der der Spielerskin steht
    SetPlayerFacingAngle(playerid,richtung); //richtung = Richtung, in die der Spielerskin steht
    SetPlayerCameraPos(playerid, x,y,z); //x,y,z = Postion der Kamera
    SetPlayerCameraLookAt(playerid, x,y,z); //x,y,z = Position vom Skin, auf den die Kamera guckt
    }

    Genau so geht das auch bei den anderen if-Abfragen! Bei mir sehen diese jetzt so aus:

    if (classid == 0) //grove
    {
    SetPlayerPos(playerid, 2511.2092,-1688.0992,13.5621);
    SetPlayerFacingAngle(playerid,44.2817);
    SetPlayerCameraPos(playerid, 2508.6785,-1685.8330,13.5628);
    SetPlayerCameraLookAt(playerid, 2511.2092,-1688.0992,13.5621);
    }
    if (classid == 1)//grove
    {
    SetPlayerPos(playerid, 2518.0532,-1677.3661,14.3649);
    SetPlayerFacingAngle(playerid,48.3784);
    SetPlayerCameraPos(playerid, 2515.3792,-1674.7891,13.7942);
    SetPlayerCameraLookAt(playerid, 2518.0532,-1677.3661,14.3649);
    }
    if (classid == 2)//grove
    {
    SetPlayerPos(playerid, 2518.9741,-1661.5500,14.3701);
    SetPlayerFacingAngle(playerid,95.8370);
    SetPlayerCameraPos(playerid, 2516.1572,-1662.0303,14.0208);
    SetPlayerCameraLookAt(playerid, 2518.9741,-1661.5500,14.3701);
    }
    if (classid == 3)//ballas
    {
    SetPlayerPos(playerid, 1910.1559,-1123.0077,25.5906);
    SetPlayerFacingAngle(playerid,183.7904);
    SetPlayerCameraPos(playerid, 1910.4298,-1126.7048,24.7416);
    SetPlayerCameraLookAt(playerid, 1910.1559,-1123.0077,25.5906);
    }
    if (classid == 4)//ballas
    {
    SetPlayerPos(playerid, 1939.0726,-1114.7036,27.4523);
    SetPlayerFacingAngle(playerid,178.7263);
    SetPlayerCameraPos(playerid, 1938.8990,-1116.4243,26.9467);
    SetPlayerCameraLookAt(playerid, 1939.0726,-1114.7036,27.4523);
    }
    if (classid == 5)//ballas
    {
    SetPlayerPos(playerid, 2002.9470,-1115.9773,27.1250);
    SetPlayerFacingAngle(playerid,181.3781);
    SetPlayerCameraPos(playerid, 2002.8882,-1118.4071,26.7813);
    SetPlayerCameraLookAt(playerid, 2002.9470,-1115.9773,27.1250);
    }

    So... Das war's für diesen Abschnitt.


    Verschiedene Teams


    Mittlerweile haben wir nun ein Grundgerüst. Dieses ist jedoch noch sehr mager. Deshalb möchten wir uns mit einem der wichtigsten Sachen eines TDM-Gamemodes beschäftigen - den Teams. Wie ihr es (hoffentlich) mitbekommen habt, habe ich in meinem Gamemode 2 Teams bzw. Gangs: Ballas und Grove Street. Es ist nun wichtig zu wissen, welcher Spieler welcher Gang angehört. Dazu erstellen wir ein Array:

    new Gang[MAX_PLAYERS];

    Nun editieren wir die if-Abfragen bei OnPlayerRequestClass():

    if (classid == 0) //grove
    {
    ...
    Gang[playerid] = 1;
    }
    if (classid == 1)//grove
    {
    {
    ...
    Gang[playerid] = 1;
    }
    if (classid == 2)//grove
    {
    {
    ...
    Gang[playerid] = 1;
    }
    if (classid == 3)//ballas
    {
    ...
    Gang[playerid] = 2;
    }
    if (classid == 4)//ballas
    {
    ...
    Gang[playerid] = 2;
    }
    if (classid == 5)//ballas
    {
    ...
    Gang[playerid] = 2;
    }

    Ihr erkennt vermutlich sofort, dass wenn man classid 0 - 2 nimmt, gang[playerid] = 1 (1 = Grove) ist und wenn die classid 3 - 5 ist, gang[playerid] = 2 (2 = Ballas) ist. Nun können wir jederzeit herausfinden, wer welchem Team gehört. Jetzt bauen wir eine Überprüfung ein, die prüft, wieviele Teamkills jemand gemacht hat. Sind es über 4, wird die Person gekickt. Dazu brauchen wir wiedermal ein Array:

    new teamkills[MAX_PLAYERS];

    Wichtig ist, dass wir den Wert des Arrays auf 0 Setzen, wenn jemand auf den Server kommt. Wieso? Stellt euch vor, jemand hat 2 Teamkills und verlässt den Server. Wenn nun jemand auf den Server kommt und die gleiche Playerid wie der vorherige Spieler hat, der ja schon 2 Teamkills hat, hat der Spieler der den Server gerade betreten hat schon 2 Teamkills, obwohl er ja noch nicht mal gespawnt ist. Um dies zu umgehen, genügt es, folgende Zeile beim Callback OnPlayerConnect() hinzuzufügen:

    teamkills[playerid] = 0;

    Aber nun zum Wichtigsten: Dem Zählen der Teamkills. Um herauszufinden, wer jemanden aus seinem eigenen Team gekillt hat, benutzen wir OnPlayerDeath(). Wir prüfen dabei einfach, ob gang[playerid] den gleichen Wert hat wie gang[killerid]. Wenn beide den gleichen Wert haben, bekommt killerid einen Teamkill. Das OnPlayerDeaht()-Callback in Code gefasst:

    public OnPlayerDeath(playerid, killerid, reason)
    {
    if (gang[playerid] == gang[killerid])
    {
    teamkills[killerid] = teamkills[killerid] + 1;
    if (teamkills[killerid] > 4)
    {
    Kick(killerid);
    }
    }
    return 1;
    }

    Wenn killerid mehr als 4 Teamkills hat, wird er gekickt.

  • Kleinigkeiten


    Hier möchte ich noch Kleinigkeiten besprechen. Als ihr euren Gamemode getestet habt, habt ihr sicherlich feststellen müssen, dass die Spielerfigur(en) etwas andere Animationen zum Laufen verwenden, als ihr sie von anderen Servern kennt. Um die "normalen" Animationen (die im Singleplayer für CJ auch verwendet werden) für alle Spielerfiguren zu verwenden, fügt ihr einfach folgende Zeile in OnGameModeInit() ein:

    UsePlayerPedAnims();

    Wie wär's, wenn die Spielernamen - je nachdem in welcher Gang die Spieler sind - in unterschiedlichen Farben dargestellt sind? Das geht ebenfalls sehr einfach. Dazu fügt ihr folgende Codezeilen beim Callback OnPlayerSpawn() ein:

    if (Gang[playerid] == 1) { SetPlayerColor(playerid,0x33AA33AA); }
    else if (Gang[playerid] == 2) { SetPlayerColor(playerid,0x8B008BAA }

    Hier wird einfach abgefragt, zu welcher Gang der Spieler gehört. Je nach dem wird dann mit SetPlayerColor() die Farbe des Spielernamens umgeändert. Näheres zu Farben findet ihr hier.


    Tipp: Wenn ihr Farben mehrmals verwendet, macht ein #define. Das heißt, ihr fügt oben - vor den Callbacks - z. B. #define COLOR_RED 0xAA3333AA ein. Anstatt SetPlayerColor(playerid,0xAA3333AA); zu schreiben könnt ihr dann SetPlayerColor(playerid,COLOR_RED); schreiben. Dies erhöht zudem die Lesbarkeit von Code.


    Ende


    Für's erste ist das Tutorial zu Ende. Sicherlich ist es kein TDM-Gamemode, der schon wirklich spielreif ist, allerdings möchte ich hier nicht alles erklären (was ich in einem einzigen Tutorial nicht schaffen würde) und möchte euch dazu bewegen, kreativ zu sein und eigene Ideen einzubauen. Es gibt noch einige Sachen, die man machen könnte, z. B.:

    • Einen Befehl, mit dem die Spieler auf andere Spieler Kopfgeld setzen können.
    • einen Teamchat
    • Mehr Gangs, Fahrzeuge etc.
    • eure eigenen Ideen :)


    Naja, aufjedenfall hoffe ich, dass es euch gefallen hat. Wenn ihr irgendwelche Vorschläge habt, die ich im nächsten Tutorial einbauen könnte oder auch Verbesserungen, postet sie bitte.


    (c) by Nichts95 & NichtsNT & Brotfischer


    Das Tutorial darf weitergegeben werden. Auf einer anderen Seite als dem Breadfish Forum (http://www.samp.breadfish.de oder http://www.forum.sa-mp.de) darf dieses Tutorial allerdings nicht ohne meine Erlaubnis zum Download angeboten werden oder gepostet werden.


    Edit: Ich weiß, Doppelposts sind nicht erlaubt, aber da man leider nur maximal 10 000 Zeichen verwenden kann...
    Edit²: Noch als Downloadversion hier.
    Edit³: Und den Gamemode als Download hier.

  • Ja, sieht ganz gut aus, nur zwei Kleinigkeiten:
    1. du erstellst Gang[MAX_PLAYERS] und benutzt gang[playerid], mach das Gang zu gang
    2. bitte nutze die [ PWN ] Klammern :D


    Ich scripte NICHT mehr, ich möchte mit NIEMANDEM einen Server aufmachen habe auch NICHTS mehr mit LoH zu tun, also lasst es mit den PNs!

  • ich hab shcon bei
    if (classid == 0) //grove
    {
    ...
    Gang[playerid] = 1;
    }
    if (classid == 1)//grove
    {
    {
    ...
    Gang[playerid] = 1;
    }
    if (classid == 2)//grove
    {
    {
    ...
    Gang[playerid] = 1;
    }
    if (classid == 3)//ballas
    {
    ...
    Gang[playerid] = 2;
    }
    if (classid == 4)//ballas
    {
    ...
    Gang[playerid] = 2;
    }
    if (classid == 5)//ballas
    {
    ...
    Gang[playerid] = 2;
    }
    C:\Documents and Settings\Administrator\Desktop\samp03asvr_R4_win32\gamemodes\GangwarLS.pwn(122) : error 017: undefined symbol "classid"
    C:\Documents and Settings\Administrator\Desktop\samp03asvr_R4_win32\gamemodes\GangwarLS.pwn(125) : warning 217: loose indentation
    C:\Documents and Settings\Administrator\Desktop\samp03asvr_R4_win32\gamemodes\GangwarLS.pwn(125) : error 017: undefined symbol "classid"
    C:\Documents and Settings\Administrator\Desktop\samp03asvr_R4_win32\gamemodes\GangwarLS.pwn(128) : error 017: undefined symbol "classid"
    C:\Documents and Settings\Administrator\Desktop\samp03asvr_R4_win32\gamemodes\GangwarLS.pwn(131) : error 017: undefined symbol "classid"
    C:\Documents and Settings\Administrator\Desktop\samp03asvr_R4_win32\gamemodes\GangwarLS.pwn(134) : error 017: undefined symbol "classid"
    C:\Documents and Settings\Administrator\Desktop\samp03asvr_R4_win32\gamemodes\GangwarLS.pwn(137) : error 017: undefined symbol "classid"
    C:\Documents and Settings\Administrator\Desktop\samp03asvr_R4_win32\gamemodes\GangwarLS.pwn(140) : error 017: undefined symbol "classid"
    C:\Documents and Settings\Administrator\Desktop\samp03asvr_R4_win32\gamemodes\GangwarLS.pwn(143) : error 017: undefined symbol "classid"
    C:\Documents and Settings\Administrator\Desktop\samp03asvr_R4_win32\gamemodes\GangwarLS.pwn(146) : error 017: undefined symbol "classid"
    Pawn compiler 3.2.3664 Copyright (c) 1997-2006, ITB CompuPhase



    9 Errors.



    ???

    526C4Hj.png Mit freundlichen Grüßen,
    Noneatme

  • Bei mir kommen 7 errors


    C:\Programme\Rockstar Games\GTA San Andreas\Server 14\gamemodes\BallasVsGS.pwn(11) : error 026: no matching "#if..."
    C:\Programme\Rockstar Games\GTA San Andreas\Server 14\gamemodes\BallasVsGS.pwn(26) : error 026: no matching "#if..."
    C:\Programme\Rockstar Games\GTA San Andreas\Server 14\gamemodes\BallasVsGS.pwn(31) : warning 217: loose indentation
    C:\Programme\Rockstar Games\GTA San Andreas\Server 14\gamemodes\BallasVsGS.pwn(49) : error 017: undefined symbol "SetPlayerFacingangle"
    C:\Programme\Rockstar Games\GTA San Andreas\Server 14\gamemodes\BallasVsGS.pwn(52) : error 017: undefined symbol "gang"
    C:\Programme\Rockstar Games\GTA San Andreas\Server 14\gamemodes\BallasVsGS.pwn(52) : warning 215: expression has no effect
    C:\Programme\Rockstar Games\GTA San Andreas\Server 14\gamemodes\BallasVsGS.pwn(52) : error 001: expected token: ";", but found "]"
    C:\Programme\Rockstar Games\GTA San Andreas\Server 14\gamemodes\BallasVsGS.pwn(52) : error 029: invalid expression, assumed zero
    C:\Programme\Rockstar Games\GTA San Andreas\Server 14\gamemodes\BallasVsGS.pwn(52) : fatal error 107: too many error messages on one line


    Compilation aborted.Pawn compiler 3.2.3664 Copyright (c) 1997-2006, ITB CompuPhase



    7 Errors.

  • kann mir einer mal bitte helfen?
    Kriege einen error: C:\Users\sergej\Desktop\SA-MP Selfmade\pawno\new3.pwn(39) : error 010: invalid function or declaration
    Pawn compiler 3.2.3664 Copyright (c) 1997-2006, ITB CompuPhase



    1 Error.


    bei:


    public OnPlayerRequestClass(playerid, classid)
    if (classid == 0) //groove
    {
    SetPlayerPos(playerid, 2496.1343,-1708.5537,1014.7422);
    SetPlayerFacingAngle(playerid,179.7233);
    SetPlayerCameraPos(playerid, 2508.6785,-1685.8330,13.5628);
    SetPlayerCameraLookAt(playerid, 2511.2092,-1688.0992,13.5621);
    }
    if (classid == 1) //ballaz
    {
    SetPlayerPos(playerid, 725.4605,-1449.7977,17.6953);
    SetPlayerFacingAngle(playerid,3.3617);
    SetPlayerCameraPos(playerid, 2508.6785,-1685.8330,13.5628);
    SetPlayerCameraLookAt(playerid, 2511.2092,-1688.0992,13.5621);
    }


    ich finde da nicht denn fehler


    //Edit: Zeile 39 ist : if (classid == 1) //ballaz

  • Setz ma /* vor public OnPlayerRequestClass(playerid, classid) und am ende */


    /*


    public OnPlayerRequestClass(playerid, classid)
    if (classid == 0) //groove
    {
    SetPlayerPos(playerid, 2496.1343,-1708.5537,1014.7422);
    SetPlayerFacingAngle(playerid,179.7233);
    SetPlayerCameraPos(playerid, 2508.6785,-1685.8330,13.5628);
    SetPlayerCameraLookAt(playerid, 2511.2092,-1688.0992,13.5621);
    }
    if (classid == 1) //ballaz
    {
    SetPlayerPos(playerid, 725.4605,-1449.7977,17.6953);
    SetPlayerFacingAngle(playerid,3.3617);
    SetPlayerCameraPos(playerid, 2508.6785,-1685.8330,13.5628);
    SetPlayerCameraLookAt(playerid, 2511.2092,-1688.0992,13.5621);
    }


    */


    dann müsste es gehen

  • Hey bei mir kommt das hier


    C:\Programme\Rockstar Games\Grand Theft Auto San Andreas\gamemodes\new.pwn(37) : warning 217: loose indentation
    C:\Programme\Rockstar Games\Grand Theft Auto San Andreas\gamemodes\new.pwn(356) : warning 202: number of arguments does not match definition
    C:\Programme\Rockstar Games\Grand Theft Auto San Andreas\gamemodes\new.pwn(357) : warning 202: number of arguments does not match definition
    C:\Programme\Rockstar Games\Grand Theft Auto San Andreas\gamemodes\new.pwn(358) : warning 202: number of arguments does not match definition
    C:\Programme\Rockstar Games\Grand Theft Auto San Andreas\gamemodes\new.pwn(359) : error 017: undefined symbol "Gang"
    C:\Programme\Rockstar Games\Grand Theft Auto San Andreas\gamemodes\new.pwn(359) : warning 215: expression has no effect
    C:\Programme\Rockstar Games\Grand Theft Auto San Andreas\gamemodes\new.pwn(359) : error 001: expected token: ";", but found "]"
    C:\Programme\Rockstar Games\Grand Theft Auto San Andreas\gamemodes\new.pwn(359) : error 029: invalid expression, assumed zero
    C:\Programme\Rockstar Games\Grand Theft Auto San Andreas\gamemodes\new.pwn(359) : fatal error 107: too many error messages on one line


    Compilation aborted.Pawn compiler 3.2.3664 Copyright (c) 1997-2006, ITB CompuPhase



    4 Errors.


  • So ist der Code ohne dem eingefügten. Ich habe es vorerst gelöscht weil ich noch andere sachen an meinem script mache.
    Man kann sich es einfach vorstellen ich habe es genau wie oben beschrieben gemacht 2x.


    Noch ne frage gibts hier ein TuT für

    • Pickups einfügen wie z.B. Armor, Waffen und Heal
    • Objecte bewegen ( der auch funktioniert ) wie z.B. ein Gate auf die seite.
    • Gangautos ( Nur ballas können in ballas autos ... )
    • Admin Commands