Liebe sa-mp.de Benutzer,
ich habe gerade mal die Suchfunktion im Tutorial-Bereich benutzt, um zu schauen, ob dieses Tutorial überhaupt notwendig ist.
Und ja es ist notwendig .
Es gibt hier viele Tutorials über eigene Ein und Ausgänge ohne CMD, aber irgendwie, zumindest kommt es so rüber, dass ich bei ca. 100 Ein und Ausgängen nachher mehr Code davon habe, als der Rest vom Script.
Daher finde ich es doch notwenig, mal zu zeigen wie Ich soetwas lösen würde, da es natürlich bestimmt noch andere Varianten gibt.
Um eigene Ein- und Ausgänge zu erstellen, müssen die alten erstmal raus.
Dafür gibt es eine leichte Methode, nämlich:
DisableInteriorEnterExits();
Das fügt ihr bei dem Callback: OnGameModeInIt hinein, sollte eigentlich bekannt sein.
Nunja, um Teleporter zu erstellen, brauchen wir erstmal etwas, was diese als solche kennzeichnet, kurz gesagt "PickUps".
Wie euch bekannt sein sollte, braucht die Funktion "CreatePickup" natürlich Übergabeparameter, nämlich Erscheinungsbild(model),Typ(type),Position(X,Y,Z) und Virtual-World.
So nun gibt es Leute unter uns, die fangen so an:
new pickup1;
new pickup2;
//usw.
Dann gibt es "schlauere" Leute, die fangen so an:
new pickups[100]; .
Doch alle machen dann den Fehler bei OnGameModeInit.
Sieht dann ungefähr so aus:
pickup1 = CreatePickup(...)
oder so
pickups[0] = CreatePickup(...)
Bei 100 Ein- und Ausgängen wünsche ich den Leuten an dieser Stelle viel Spaß.
So nun kommen wir zu meinem Vorschlag.
Ein 2-D(imensionales) Array + eine enum Struktur arbeiten viel effektiver.
Zur Erklärung:
By Goldkiller :
ZitatFü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)
Nunja in diesem Enum können wir also verschiedene Typen haben, was bei den Übergabeparametern ja ebenfalls der Fall ist. Zufall? Wer weiß?
Also das enum würde so aussehen:
enum picks{
Float:eX,
Float:eY,
Float:eZ,
interior,
bool:Rueck,
Virtualworld
}
Die X,Y,Z - Werte sind also Float-Werte, wer nicht weiß, was Float-Werte sind, sollte in einer neuen Registerkarte, das Wiki durchstöbern.
Wofür interior?
Um uns am Ende viel Code zu ersparen geben wir hier das Interior an, in welchem sich das Pickup befindet.
Rueck vom Typ bool(ean), gibt an, ob es ein Hin, oder Rück-Teleporter ist, in diesem Falle Im Gebäude, oder draussen.
Virtualworld ist ein Übergabeparameter für die Funktion CreatePickup(...).
Das ganze packen wir nun in ein 2-Dimensionales Array.
new PickUpsCoords[PICK_UPS][picks] = {};
Wir werden dem Array eine Größe durch etwas definiertes ausdrücken.
Nämlich:
#define PICK_UPS 2 // Die 2 steht für die Anzahl ALLER Teleporter (Hin und Rück - Differenziert)
So nun müssen wir ja aber auch die Werte im enum initialisieren.
Dies passiert so:
new PickUpsCoords[PICK_UPS][picks] = {
// Nach dem Schema: X,Y,Z,Interior des Pickups, Rück Porter - ja / nein, VW
{-316.1541,829.8519,14.2422,0,false,0}, // Amunation IN
{285.8248,-40.8825,1001.5156,1,true,0} // Amunation OUT
Wie schon erklärt: Der erste Wert stell eX des enum dar, der zweite eY, der dritte eZ, der vierte interior, der fünfte Rueck und der sechste Virtualworld.
Wichtig dabei ist, dass ihr Schemata/Schemas(xD, ja ist leider so) beibehalten: Ersten das, was ich einen Satz zuvor erklärt habe. Und zweitens, dass immer der Hin-Teleporter, in diesem Falle der draussen vor dem Gebäude ist immer als erstes kommt. Sprich wenn ich jetzt Vier Teleporter erzeugen möchte, sieht das Array so aus:
new PickUpsCoords[PICK_UPS][picks] = {
// Nach dem Schema: X,Y,Z,Interior des Pickups, Rück Porter - ja / nein, VW
{-316.1541,829.8519,14.2422,0,false,0}, // Amunation IN
{285.8248,-40.8825,1001.5156,1,true,0}, // Amunation OUT
172.9729,1177.1868,14.7578,0,false,0}, // Cluckin Bell IN
{365.0766,-11.8404,1001.8516,9,true,0} // Cluckin Bell OUT
};
Und so weiter.. Natürlich müssten wir jetzt bei 4 Teleportern folgendes ändern.
#define PICK_UPS 4
So nun müssen wir noch ein Array erstellen, was die Pickup-ID's also die return-Werte von der Funktion CreatePickup(...) speichert.
new PickUps[PICK_UPS];
Dass wir wieder mit "PICK_UPS" arbeiten, macht es einfach, denn so sind beide Arrays, also das 1D und 2D immer von der Größe gleich.
So nun erzeugen wir die Pickups mit der Funktion CreatePickup, und zwar unter OnGameModeInit.
Hier haben wir schon das erste Ziel meines Tutorials erreicht. Anstatt jetzt z.B 100 Pickups per Hand zu erstellen, übernimmt eine For-Schleife diese arbeit.
Das ganze sieht dann so aus bei OnGameModeInIt.
for(new i = 0; i <= sizeof(PickUps); i++)
{
PickUps[i] = CreatePickup(1318,23,PickUpsCoords[i][eX],PickUpsCoords[i][eY],PickUpsCoords[i][eZ],PickUpsCoords[i][Virtualworld]);
}
Damit sparen wir schonmal die erste "Handarbeit".
1318 ist das Pickup Model, in diesem Falle der Pfeil nach unten und 23 der Pickup Typ, in diesem Falle, pickupable(!) but dont disappear on pickup, glaube ich.
Also für uns der richtige Typ, denn es geht so weiter.
Wir betrachten das Callback: OnPlayerPickUpPickup, welches zwar klein, aber wichtig für uns ist.
Dort fügt ihr folgendes ein:
for(new i = 0; i <= sizeof PickUps; i++)
{
if(pickupid == PickUps[i])
{
StehtaufPickUp[playerid] = pickupid;
}
}
Warum brauchen wir das Spielerbezogene Array StehtaufPickUp?
Ganz einfach, wir könnten uns das jetzt sparen und mit einer Timer-Delay Struktur arbeiten, aber auf den modernen Servern benutzt man jetzt gerne die Enter Taste um Gebäude zu betreten, was ich hier jetzt auch umsetzen werde.
Da also pickupid uns ausserhalb des Callbacks nicht mehr zur Verfügung steht, speichern wir den Wert eben in das Array hinein.
Also brauchen wir oben im Script noch ein
new StehtaufPickUp[MAX_PLAYERS];
und bei OnPlayerConnect ein:
StehtaufPickUp[playerid] = -1
Soweit so gut, aber richtig viel ist uns noch nicht erspart geblieben, durch dieses Tutorial, aber das ändert sich jetzt.
Wir wollten uns ja mit dem "Entertaste-Teleporter" beschäftigen, also brauchen wir das Callback: OnPlayerKeyStateChange.
Dort fügen wir folgendes ein.
if(newkeys == KEY_SECONDARY_ATTACK)
{
if(PlayerIsNearToEnterExit(playerid))
{
for(new i = 0; i <= sizeof(PickUps); i++)
{
if(PickUps[i] == StehtaufPickUp[playerid])
{
if(PickUpsCoords[i][Rueck] == false)
{
SetPlayerPos(playerid,PickUpsCoords[i+1][eX],PickUpsCoords[i+1][eY],PickUpsCoords[i+1][eZ]);
SetPlayerInterior(playerid,PickUpsCoords[i+1][interior]);
SetPlayerVirtualWorld(playerid,PickUpsCoords[i+1][Virtualworld]);
StehtaufPickUp[playerid] = -1;
}
else if(PickUpsCoords[i][Rueck] == true)
{
SetPlayerPos(playerid,PickUpsCoords[i-1][eX],PickUpsCoords[i-1][eY],PickUpsCoords[i-1][eZ]);
SetPlayerInterior(playerid,PickUpsCoords[i-1][interior]);
SetPlayerVirtualWorld(playerid,PickUpsCoords[i-1][Virtualworld]);
StehtaufPickUp[playerid] = -1;
}
}
}
}
Erklärung:
if(newkeys == KEY_SECONDARY_ATTACK):
Fragt ab, ob der Spieler die Enter / F Taste gedrückt hat.
Wenn das zutrifft, dann:
if(PlayerIsNearToEnterExit(playerid))
Wird abgefragt, ob der Spieler sich an einem PickUp befindet. Diese Funktion müssen gleich noch implementieren.
Wenn das zutrifft, dann:
Erstellen wir eine For-Schleife die uns durch das Array PickUps begleitet:
Es wird dann abgefragt, ob wir auf einem Pickup gestanden haben, was einen Teleporter da stellt: