Beiträge von Brotfischer

    Ist ja recht schwer zu beantworten. Je nachdem welches Ziel und was man im Gamemode machen kann. Forwards brauchst du für die Funktionen, die du selber scriptest und defines normalerweiße nur für Farben & Teams.

    Zitat


    PS: wie macht man das der Name bei der Skinauswahl steht?


    Meinst du jetzt den Spielernamen oder irgendwelche gangnamen oder wie?


    #include <a_samp>


    forward IfAutoKaputtTimer(playerid);
    forward Float:GetDistanceBetweenPlayers(p1,p2);
    #define COLOR_RED 0xE60000FF
    #define COLOR_WHITE 0xFFFFFFFF
    static bool:PlayerMessageMotorschaden[MAX_PLAYERS] = { false };
    public OnFilterScriptInit()
    {
    print("\n--------------------------------------");
    print(" Feuerwehr Script by Funsocke");
    print("--------------------------------------\n");
    SetTimer("IfAutoKaputtTimer", 1000, 1);
    return 1;
    }
    strtok(const string[], &index)
    {
    new length = strlen(string);
    while ((index < length) && (string[index] <= ' '))
    {
    index++;
    }


    new offset = index;
    new result[20];
    while ((index < length) && (string[index] > ' ') && ((index - offset) < (sizeof(result) - 1)))
    {
    result[index - offset] = string[index];
    index++;
    }
    result[index - offset] = EOS;
    return result;
    }
    public OnPlayerDisconnect(playerid, reason)
    {
    PlayerMessageMotorschaden[playerid] = false;
    return 1;
    }
    public OnPlayerPrivmsg(playerid, recieverid, text[])
    {
    return 1;
    }
    public Float:GetDistanceBetweenPlayers(p1,p2){
    new Float:x1,Float:y1,Float:z1,Float:x2,Float:y2,Float:z2;
    if (!IsPlayerConnected(p1) || !IsPlayerConnected(p2)){
    return -1.00;
    }
    GetPlayerPos(p1,x1,y1,z1);
    GetPlayerPos(p2,x2,y2,z2);
    return floatsqroot(floatpower(floatabs(floatsub(x2,x1)),2)+floatpower(floatabs(floatsub(y2,y1)),2)+floatpower(floatabs(floatsub(z2,z1)),2));
    }
    public IfAutoKaputtTimer(playerid)
    {
    new Float:health;
    new string[256];
    new vehicleid = GetPlayerVehicleID(playerid);
    if(IsPlayerInAnyVehicle(playerid))
    {
    GetVehicleHealth(vehicleid, health);
    format(string, 256, "~n~~n~~n~~n~~n~~n~~g~Auto Schaden : ~w~%.0f",health);
    GameTextForPlayer(playerid, string, 2000, 5);
    }


    new VID, Float:h_vid;
    if(IsPlayerConnected(playerid) && IsPlayerInAnyVehicle(playerid))
    {
    VID = GetPlayerVehicleID(playerid);
    GetVehicleHealth(VID, h_vid);
    if(h_vid <= 185 && PlayerMessageMotorschaden[playerid] == false)
    {
    TogglePlayerControllable(playerid, 0);
    SendClientMessage(playerid, 0xFF6900AA, "Dieses Fahrzeug hat nun einen Motorschaden. Rufe die /112");
    PlayerMessageMotorschaden[playerid] = true;
    SetVehicleHealth(vehicleid, 185.0);
    SetPlayerHealth(playerid,100);
    } }
    }


    public OnPlayerCommandText(playerid, cmdtext[])
    {
    new sendername[MAX_PLAYER_NAME];
    new cmd[256];
    new idx;
    new string[256];
    cmd = strtok(cmdtext,idx);


    if(strcmp(cmd, "/befrei", true) == 0)
    {
    new tmp[256];
    new giveplayer[200];


    if(IsPlayerConnected(playerid))
    {
    tmp = strtok(cmdtext, idx);
    new otherplayer = strval(tmp);
    if(!strlen(tmp))
    {
    SendClientMessage(playerid, COLOR_WHITE, "[BENUTZUNG]: /befrei [SpielerID]");
    return 1;
    }
    if(!IsPlayerConnected(otherplayer)) return SendClientMessage(playerid, COLOR_WHITE, "Falsche SpielerID !");
    if(GetDistanceBetweenPlayers(playerid,otherplayer <= 5.0))
    {
    GetPlayerName(otherplayer, giveplayer, sizeof(giveplayer));
    GetPlayerName(playerid, sendername, sizeof(sendername));
    new Float:X;
    new Float:Y;
    new Float:Z;
    GetPlayerPos(playerid,X,Y,Z);
    SetPlayerPos(otherplayer,X,Y+1,Z);
    format(string, sizeof(string), "Du hast %s gerettet!!.", giveplayer);
    SendClientMessage(playerid,COLOR_WHITE, string);
    SendClientMessage(otherplayer, COLOR_WHITE, "Du wurdest gerettet");
    TogglePlayerControllable(playerid, 1);
    }
    else
    {
    SendClientMessage(playerid, COLOR_RED, "Der Spieler ist zu weit von dir entfernt !");
    }


    }
    return 1;
    }
    if(strcmp(cmdtext, "/112", true) == 0 || strcmp(cmdtext, "/feuerwehr", true) == 0)
    {
    new pname[30], str[100];
    GetPlayerName(playerid,pname,sizeof(pname));
    format(str,sizeof(str), "%s braucht die Feuwehr!",pname);
    SendClientMessageToAll(COLOR_RED,str);
    return 1;
    }
    return 0;
    }

    Edit: Ungetestet, müsste aber zu 99% funktionieren.

    Hallo, ich habe ein Problem. Und zwar habe ich folgenden Befehl gescriptet:

    public OnPlayerCommandText(playerid, cmdtext[])
    {
    if (strcmp("/stats", cmdtext, true, 10) == 0)
    {
    new gangname[100];
    new playername[100];
    new Float:kd = kills[playerid]/deaths[playerid];
    if (Gang[playerid] == 1) { gangname = "Grove Street"; }
    else { gangname = "Ballas"; }
    new stats[100];
    new stats2[100];
    GetPlayerName(playerid,playername,sizeof(playername));
    format(stats,sizeof(stats),"Du heißt %s und gehörst der Gang ""%s"" an.", playername, gangname);
    SendClientMessage(playerid,0xFF0000FF,stats);
    return 1;
    }
    return 0;
    }

    Dieser geht aber nicht. Ich bekomme die "Server: Unknown Command"-Warnung. Der eigentliche Befehl wird dann auch nicht ausgeführt; also so, als ob es den Befehl garnicht geben würde Oo

    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.

    Ich habe mal soetwas in der Art ausgetestet, aber als die "Bahn" bzw. das Objekt sich bewegt hat, hat sich mein Spieler nicht mitbewegt, d. h. er war die ganze Zeit an der gleichen Stelle. Ich würde einfach auf SAMP 0.3 warten und dann einfach einen Bot scripten, der auf einer selbstgemappten Strecke fährt oder wie auch immer.

    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.

    Bei einem normalen DM-Gamemode wären vielleicht verschiedene Spawns sinnvoll. Oder dass man auf andere Kopfgeld setzen kann. Sei doch kreativ o.o

    Hallo, ich habe mir die San Vice Beta 3 runtergeladen & installiert, aber wenn ich ein neues Spiel erstelle lädt er bis der Ladebalken voll ist und bleibt hängen <.< Ich habe die 1.0 Exe und habe auch den Mod mehrmals neu downgeloadet und installiert aber es klappt einfach nicht! Bei Google habe ich auch schon gesucht ...


    So ist es nun richtig. Danke an alle die mir geholfen haben.