Guten Morgen,
Wie ich immer wieder merke gibt es noch sehr viele Leute die nicht wissen wie man ein Script erstellt bei denen Checkpoints
abgefahren werden (Die roten Kreise falls jemand nicht genau weiss was das ist ;] ), sei es nun für Jobs oder Rennen.
Für alle anderen die meinen sie wissen wie man so etwas erstellt,schaut euch das Tutorial trotzdem an.Denn am Beispiel von diesem Post hier des Müllabfuhrscript ist wieder mal deutlich gezeigt wie man es eigentlich nicht machen sollte.
Es ist unglaublich unübersichtlich mit dem extrem langen Code unter OnPlayerCheckpoint,außerdem sehr schlecht zu
bearbeiten falls man irgendwo in der Mitte einen neuen Checkpoint hinzufügen möchte oder sonst wo.
Wer soll sich denn bitte bei diesem Code zurecht finden:
public OnPlayerEnterCheckpoint(playerid) {
new trinkgeld = random(85); // Betrag für das Trinkgeld, lässt sich beliebig ändern! ( Zufalls Betrag )
new string[256];
if(Checkpoint[playerid] == 1)
{
SendClientMessage(playerid, COLOR_RED, "Muell aufgeladen, weiter!");
GivePlayerMoney(playerid, trinkgeld);
format(string, sizeof(string), "** Du hast %d$ Trinkgeld bekommen!",trinkgeld);
SendClientMessage(playerid, COLOR_GREEN, string);
DisablePlayerCheckpoint(playerid);
SetPlayerCheckpoint(playerid, -89.2432,-1189.7782,2.3241, 5.0);
Checkpoint[playerid] = 2;
}
else if(Checkpoint[playerid] == 2)
{
SendClientMessage(playerid, COLOR_RED, "Muell aufgeladen, weiter!");
GivePlayerMoney(playerid, trinkgeld);
format(string, sizeof(string), "** Du hast %d$ Trinkgeld bekommen!",trinkgeld);
SendClientMessage(playerid, COLOR_GREEN, string);
DisablePlayerCheckpoint(playerid);
SetPlayerCheckpoint(playerid, -63.3734,-1588.5732,3.1782, 5.0);
Checkpoint[playerid] = 3;
}
else if(Checkpoint[playerid] == 3)
{
SendClientMessage(playerid, COLOR_RED, "Muell aufgeladen, weiter!");
GivePlayerMoney(playerid, trinkgeld);
format(string, sizeof(string), "** Du hast %d$ Trinkgeld bekommen!",trinkgeld);
SendClientMessage(playerid, COLOR_GREEN, string);
DisablePlayerCheckpoint(playerid);
SetPlayerCheckpoint(playerid, 220.8943,-1393.5308,52.1264, 5.0);
Checkpoint[playerid] = 4;
}
else if(Checkpoint[playerid] == 4)
{
...
}
Ich zeig euch mal wie Ich es besser machen würde.Gibt wahrscheinlich noch andere Varianten,aber so hab ich
es für mich persöhnlich eingepräkt.
Als erstes einmal hab ich mir alle Checkpoint Koordinaten aus dem Script rausgeschrieben:
Zitat
-74.2252,-1128.7936,1.6359, 5.0
-89.2432,-1189.7782,2.3241, 5.0
-63.3734,-1588.5732,3.1782, 5.0
220.8943,-1393.5308,52.1264, 5.0
169.0361,-1356.8065,69.8208, 5.0
263.5524,-1341.0842,53.7643, 5.0
871.9646,-864.5255,77.2742, 5.0
935.7687,-835.7352,94.4455, 5.0
1496.5879,-698.0237,94.5207, 5.0
1001.1724,-935.0218,41.9509, 5.0
-546.9002,-488.6077,25.2961, 5.0
Alles anzeigen
Wunderbar oder nicht?
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)
Nun gut,das enum brauch X,Y,Z und die Größe des Checkpoints als Float Daten,deshalb sieht es bei mir so aus:
enum e_Muell {
Float:M_fX,
Float:M_fY,
Float:M_fZ,
Float:M_fRad
}
Ich kennzeichnen ein enum immer mit e_ vor dem eigentlichen Namen.
Float:M_fX,
M_ = steht bei mir für e_Müll,um zu wissen von welchem enum und um verwechselungen auzuschließen falls ein Variablenname doppelt vergeben wird.
f = steht bei mir für Float,um zu wissen welcher Typ es ist
Jetzt müssen wir das enum noch mit Daten füllen,wieso also nicht mit den Checkpoints die wir aufgeschrieben haben.
Das ganze sieht dann also so aus:
enum e_Muell {
Float:M_fX,
Float:M_fY,
Float:M_fZ,
Float:M_fRad
}
new
Muellabfuhr_Stationen[][e_Muell] = {
{-74.2252, -1128.7936, 1.6359, 5.0},
{-89.2432, -1189.7782, 2.3241, 5.0},
{-63.3734, -1588.5732, 3.1782, 5.0},
{220.8943, -1393.5308, 52.1264, 5.0},
{169.0361, -1356.8065, 69.8208, 5.0},
{263.5524, -1341.0842, 53.7643, 5.0},
{871.9646, -864.5255, 77.2742, 5.0},
{935.7687, -835.7352, 94.4455, 5.0},
{1496.5879, -698.0237, 94.5207, 5.0},
{1001.1724, -935.0218, 41.9509, 5.0},
{-546.9002, -488.6077, 25.2961, 5.0}
};
Jetzt brauchen wir noch Variablen die Speichern, ob der Spieler gerade der Muellfahrer ist und
bei welchem Checkpoint er sich zur Zeit befindet.
enum e_PlayerMuellInfo {
bool:pmi_bAktiv,
pmi_Checkpoint
}
new Muellmann[MAX_PLAYERS][e_PlayerMuellInfo];
Gut,den Grundstein haben wir jetzt gelegt.Jetzt folgt der eigentliche Code.
Zuerst brauchen wir einen Start,ich nehme einen Command.
public OnPlayerCommandText(playerid, cmdtext[]) {
if (strcmp("/starten", cmdtext, true, 8) == 0) {
if(!Muellmann[playerid][pmi_bAktiv]) {
new
vehicleid = GetPlayerVehicleID(playerid),
model = GetVehicleModel(vehicleid);
if(model == 408) { // Text ab hier!
Muellmann[playerid][pmi_Checkpoint]=0;
Muellmann[playerid][pmi_bAktiv]=true;
SendClientMessage(playerid, COLOR_LIGHTGREEN, "Muellabfuhr gestartet, fahre nun zu den einzelnen Haeusern!");
SetPlayerCheckpoint(playerid,Muellabfuhr_Stationen[0][M_fX],Muellabfuhr_Stationen[0][M_fY],Muellabfuhr_Stationen[0][M_fZ],Muellabfuhr_Stationen[0][M_fRad]);
}
else {
SendClientMessage(playerid, COLOR_RED, "Du bist nicht im Muellwagen!");
}
}
else {
SendClientMessage(playerid, COLOR_RED, "Es laeuft schon eine Mission!");
}
return 1;
}
return 0;
}
Zuerst müssen wir den aktuellen Checkpoint des Spielers auf 0 setzten,denn man startet ja ganz von vorne und nicht irgendwo
Anders (pmi_Checkpoint).Danach wird die Variable auf true / 1 gesetzt,die sagt ob ein Spieler gerade Muellmann ist (pmi_bAktiv) .
Die Nachricht danach ist eher unwichtig.Doch danach wird es wieder interessant.
Wir setzten den Checkpoint des Spielers.
Der Checkpoint wird für den Spieler auf die Koordinaten gesetzt des ersten Eintrages (Ist allerdings der Index 0,deshalb [0] im Muellabfuhr_Stationen Enum )
Muellabfuhr_Stationen[0][M_fX],Muellabfuhr_Stationen[0][M_fY],Muellabfuhr_Stationen[0][M_fZ],Muellabfuhr_Stationen[0][M_fRad]
Jetzt haben wir den ersten Checkpoint.Doch wie geht es weiter?Bewegen wir uns nun zum OnPlayerEnterCheckpoint() Callback.
Der bisherige Code sieht übrigens so aus:
#include <a_samp>
#define COLOR_LIGHTGREEN 0x86FF59FF
#define COLOR_RED 0xFF0000FF
#define COLOR_GREEN 0x00CA00FF
enum e_PlayerMuellInfo {
bool:pmi_bAktiv,
pmi_Checkpoint
}
new Muellmann[MAX_PLAYERS][e_PlayerMuellInfo];
enum e_Muell {
Float:M_fX,
Float:M_fY,
Float:M_fZ,
Float:M_fRad
}
new
Muellabfuhr_Stationen[][e_Muell] = {
{-74.2252, -1128.7936, 1.6359, 6.0},
{-89.2432, -1189.7782, 2.3241, 6.0},
{-63.3734, -1588.5732, 3.1782, 6.0},
{220.8943, -1393.5308, 52.1264, 6.0},
{169.0361, -1356.8065, 69.8208, 6.0},
{263.5524, -1341.0842, 53.7643, 6.0},
{871.9646, -864.5255, 77.2742, 6.0},
{935.7687, -835.7352, 94.4455, 6.0},
{1496.5879, -698.0237, 94.5207, 6.0},
{1001.1724, -935.0218, 41.9509, 6.0},
{-546.9002, -488.6077, 25.2961, 6.0}
};
public OnFilterScriptInit()
{
print("-] Tutorial - Checkpoints abfahren [-");
CreateVehicle(408,-535.8450,-502.6665,26.0667,358.0911,1,1,-1);
return 1;
}
public OnPlayerCommandText(playerid, cmdtext[]) {
if (strcmp("/starten", cmdtext, true, 8) == 0) {
if(!Muellmann[playerid][pmi_bAktiv]) {
new
vehicleid = GetPlayerVehicleID(playerid),
model = GetVehicleModel(vehicleid);
if(model == 408) {
Muellmann[playerid][pmi_Checkpoint]=0;
Muellmann[playerid][pmi_bAktiv]=true;
SendClientMessage(playerid, COLOR_LIGHTGREEN, "Muellabfuhr gestartet, fahre nun zu den einzelnen Haeusern!");
SetPlayerCheckpoint(playerid,Muellabfuhr_Stationen[0][M_fX],Muellabfuhr_Stationen[0][M_fY],Muellabfuhr_Stationen[0][M_fZ],Muellabfuhr_Stationen[0][M_fRad]);
}
else {
SendClientMessage(playerid, COLOR_RED, "Du bist nicht im Muellwagen!");
}
}
else {
SendClientMessage(playerid, COLOR_RED, "Es laeuft schon eine Mission!");
}
return 1;
}
return 0;
}
public OnPlayerEnterCheckpoint(playerid) {
// Hier haben wir noch nix eingefügt vom Tutorial,das kommt erst ;)
return 1;
}
Jetzt sollten wir als erstes einen Check einfügen in OnPlayerEnterCheckpoint,der überprüft ob wir einen Muellmann haben
der durch den Checkpoint gelaufen/gefahren ist.Dafür haben wir ja unsere Variable pmi_bAktiv.
public OnPlayerEnterCheckpoint(playerid) {
if(Muellmann[playerid][pmi_bAktiv]) {
}
return 1;
}
Wunderbar!
Jetzt kann es direkt weiter gehen.Wir wissen jetzt,dass der Spieler durch einen Checkpoint gelaufen ist und Müllmann ist.
Er hat also einen Checkpoint betreten,von daher müssen wir seine Variable erhöhen die weiss bei welchem Checkpoint er sich befindet,dafür nehmen wir :
Muellmann[playerid][pmi_Checkpoint]++;
Außerdem müssen wir den aktuellen Checkpoint verschwinden lassen,das machen wir mit Hilfe der Funktion DisablePlayerCheckpoint().
public OnPlayerEnterCheckpoint(playerid) {
if(Muellmann[playerid][pmi_bAktiv]) {
Muellmann[playerid][pmi_Checkpoint]++; // ++ ist das gleiche wie +1
DisablePlayerCheckpoint(playerid);
}
return 1;
}
Doch jetzt passiert nix beim durchfahren einen Checkpoints außer,dass der Checkpoint verschwindet durch den man gefahren ist.Aber noch wird kein neuer herbei gezaubert.Jetzt brauchen wir den Wert der sich hinter Muellmann[playerid][pmi_Checkpoint] verbirgt und den Vorteil ausmacht hinter dieser Variante des Scripts.
Um das ganze jetzt leichter für die meisten darzustellen,benutzte ich eine Hilfsvariable,die den Wert enthält des Checkpoints den der Spieler erreicht hat.
new playercp = Muellmann[playerid][pmi_Checkpoint];
Jetzt brauchen wir nur noch bei SetPlayerCheckpoint();anstatt wie vorher bei /starten als Index nicht 0 nehmen ,sondern playercp.
Denn wir brauchen ja den nächsten Eintrag aus den Muellabfuhr_Stationen.
public OnPlayerEnterCheckpoint(playerid) {
if(Muellmann[playerid][pmi_bAktiv]) {
Muellmann[playerid][pmi_Checkpoint]++;
DisablePlayerCheckpoint(playerid);
new
playercp = Muellmann[playerid][pmi_Checkpoint];
SetPlayerCheckpoint(playerid,Muellabfuhr_Stationen[playercp][M_fX],Muellabfuhr_Stationen[playercp][M_fY],Muellabfuhr_Stationen[playercp][M_fZ],Muellabfuhr_Stationen[playercp][M_fRad]);
return 1;
}
return 1;
}
Dieser kleine Code macht schon die meiste Arbeit,die wie im Beispiel oben durch 100 von Zeilen gemacht wird.
Das einzige was noch fehlt,ist zu prüfen ob der Spieler den letzten Checkpoint erreicht hat.
Das sollte aber kein Problem sein für jemand den die Grundlagen beherrscht.
public OnPlayerEnterCheckpoint(playerid) {
if(Muellmann[playerid][pmi_bAktiv]) {
Muellmann[playerid][pmi_Checkpoint]++;
DisablePlayerCheckpoint(playerid);
new
playercp = Muellmann[playerid][pmi_Checkpoint];
if(playercp == sizeof(Muellabfuhr_Stationen)) {
Muellmann[playerid][pmi_bAktiv]=false;
}
else {
SetPlayerCheckpoint(playerid,Muellabfuhr_Stationen[playercp][M_fX],Muellabfuhr_Stationen[playercp][M_fY],Muellabfuhr_Stationen[playercp][M_fZ],Muellabfuhr_Stationen[playercp][M_fRad]);
}
return 1;
}
return 1;
}
Wenn also der Spieler den Checkpoint erreicht,der gleich dem Wert der Größe bzw der Anzahl von Checkpoints von Muellabfuhr_Stationen ist,wissen wir,dass der
letzte Checkpoint erreicht ist.Ist der letzte Checkpoint erreicht,können / sollten und brauchen wir keinen neuen Checkpoint setzten.
Wir müssen nur noch die Variable auf false / 0 setzten,die darüber Info gibt ob der Spieler Muellmann ist.
Jetzt fehlt nur noch ein feinschliff mit Fahrzeug-Check,Sound,Geld,usw. ,denn die ganze Arbeit ist mit dem winzigem Code bereits getan.
Natürlich sollte man noch einen Check einfügen der prüft,ob der Spieler sich immernoch in einem Müllwagen befindet.Doch soviel Eigeninziative sollte wohl noch vorhanden sein.
public OnPlayerEnterCheckpoint(playerid) {
if(Muellmann[playerid][pmi_bAktiv]) {
Muellmann[playerid][pmi_Checkpoint]++;
DisablePlayerCheckpoint(playerid);
new
playercp = Muellmann[playerid][pmi_Checkpoint];
if(playercp == sizeof(Muellabfuhr_Stationen)) {
Muellmann[playerid][pmi_bAktiv]=false;
// Extra code
SendClientMessage(playerid, COLOR_GREEN, "Super Arbeit,du hast die Stadt hervorragend gesäubert");
GivePlayerMoney(playerid, 2000);
}
else {
new
String[128];
PlayerPlaySound(playerid,1056,0.0,0.0,0.0);
format(String,sizeof(String),"Weiter so,du hast es fasst geschafft ! (%d / %d)",playercp,sizeof(Muellabfuhr_Stationen));
SendClientMessage(playerid,COLOR_LIGHTGREEN,String);
SetPlayerCheckpoint(playerid,Muellabfuhr_Stationen[playercp][M_fX],Muellabfuhr_Stationen[playercp][M_fY],Muellabfuhr_Stationen[playercp][M_fZ],Muellabfuhr_Stationen[playercp][M_fRad]);
}
return 1;
}
return 1;
}
Wer trotzdem bei der Anderen Methode bleiben möchte,nur zu.
Abschließen lässt sich nicht viel sagen,
Hab das Tutorial jetzt fix herrunter geschrieben ohne großartig auf Wortwahl usw. zu achten.Sollte etwas unverständlich sein oder Fehler enthalten (Was natürlich möglich ist) könnt ihr das gerne posten.
//Edit 27-03-2015: Download entfernt (Code ist weg :[ )