Beitrag von JustMe.77 ()
Dieser Beitrag wurde vom Autor gelöscht ().
Du startest in dem Befehl einen Timer, in dem du das "i" mit gibst (d steht für Integer).
SetTimerEx("CreateGiftAgain", 30000, false, "d", i);
Das Callback zu dem Timer sieht dann so aus:
forward CreateGiftAgain(i);
public CreateGiftAgain(i)
{
GiftBox[i][e_oID] = CreateDynamicObject(19054, GiftBox[i][e_x], GiftBox[i][e_y], GiftBox[i][e_z], 0.0, 0.0, GiftBox[i][e_a]);
GiftBox[i][e_label] = CreateDynamic3DTextLabel("/takegift\nTo get your gift.",0x10F441AA,GiftBox[i][e_x], GiftBox[i][e_y], GiftBox[i][e_z]+0.25,8.0);
new str[16];
format(str, sizeof(str), "ID: %i.", i);
GiftBox[i][e_GiftID] = CreateDynamic3DTextLabel(str,0xFF0000FF, GiftBox[i][e_x], GiftBox[i][e_y], GiftBox[i][e_z]+1.10,8.0);
return 1;
}
Gegegebenfalls musst du das Objekt und die Labels wieder anpassen, ich habe das von der Laden-Funktion auf der Seite zuvor genommen.
Wie schaut es mit der Performance aus wenn sagen wir mal 50 Leute zur selben Zeit ein Geschenk aufheben. Heißt doch es werden 50 Timer gestartet oder?
Das stimmt, aber das wird mit ziemlicher Sicherheit kein Problem darstellen.
Das Objekt wird gelöscht und später wieder erstellt, aber man erhält immer noch ein Geschenk wenn man an der selben Position den Befehl zum aufheben eingibt.
Stimmt! Im Befehl muss noch eine Abfrage hinzugefügt werden, also so:
CMD:takegift(playerid)
{
for(new i = 0; i < MaxGifts; i++)
{
if(GiftBox[i][e_x] == 0.0 && GiftBox[i][e_y] == 0.0 && GiftBox[i][e_z] == 0.0) continue;
if(GiftBox[i][e_oID] == -1) continue;
if(IsPlayerInRangeOfPoint(playerid, 2.0, GiftBox[i][e_x], GiftBox[i][e_y], GiftBox[i][e_z]))
{
RandomGift(playerid);
DestroyDynamicObject(GiftBox[i][e_oID]);
DestroyDynamic3DTextLabel (GiftBox[i][e_label] );
GiftBox[i][e_oID] = -1;
return 1;
}
}
return 1;
}
Könntest du, aber das wird wie gesagt, mit ziemlicher Sicherheit kein Problem verursachen, solange du den Server nicht auf einem Rechner von 1995 laufen hast.
CMD:takegift(playerid)
{
if(SpielerInfo[playerid][canPickAgain] > gettime()) return SendClientMessage(playerid, 0xFF0000FF, "Error: Du kannst nur alle 60 Sekunden ein Geschenk aufnehmen.");
for(new i = 0; i < MaxGifts; i++)
{
if(GiftBox[i][e_x] == 0.0 && GiftBox[i][e_y] == 0.0 && GiftBox[i][e_z] == 0.0) continue;
if(GiftBox[i][e_oID] == -1) continue;
if(IsPlayerInRangeOfPoint(playerid, 2.0, GiftBox[i][e_x], GiftBox[i][e_y], GiftBox[i][e_z]))
{
RandomGift(playerid);
DestroyDynamicObject(GiftBox[i][e_oID]);
DestroyDynamic3DTextLabel (GiftBox[i][e_label] );
PlayerPlaySound(playerid,4202, 0.0, 0.0, 0.0);
SetTimerEx("CreateGiftAgain", 30000, false, "d", i);
GiftBox[i][e_oID] = -1;
SpielerInfo[playerid][canPickAgain] = gettime() + 60; //60 Sekunden zu warten
return 1;
}
}
return 1;
}
Das SpielerInfo[playerid][canPickAgain] musst du so umbenennen wie das Stats-System bei dir heißt, und canPickAgain muss ins enum eingefügt werden.
Dann kannst du das SpielerInfo[playerid][canPickAgain] zum Laden und Speichern der Spieler-Statistiken (wie Geld oder so) hinzufügen.
Dann müsstest du es in Dateien abspeichern, sprich Textdateien oder einer SQLite Datenbankbank.
Jeweils natürlich nur, wenn es nach dem Logout -> Login auch wieder überprüft werden soll.
Bei den kleinen Abfragen spielt es so gut wie keine Rolle, sofern du bei den Textdateien für jeden Spieler eine eigene Datei erstellst.
Eine SQLite Datenbank wäre etwas übersichtlicher im Ordner (nur eine Datei), aber dafür komplizierter zu verwenden im Code, als zum Beispiel dini.
Für Dateien musst du erst ein Verzeichnis erstellen, genau.
Dann kannst du ja mal versuchen, ob du selbst mit dini klar kommst, falls du das nutzt. Alle entsprechenden Änderungen müssten dort nur in dem Befehl gemacht werden.
Wenn du nicht weiter kommst, dann poste was du bis dahin hast.
Ok, kein Problem.
Ich habe es dir hier in den Kommentaren jeweils kurz erklärt.
Versuche es dann so:
CMD:takegift(playerid)
{
//Variablen:
new pname[MAX_PLAYER_NAME], path[64];
//Spielername abfragen:
GetPlayerName(playerid, pname, MAX_PLAYER_NAME);
//Pfad einlesen: (Ordner heißt GiftsGenommen)
format(path, sizeof(path), "/GiftsGenommen/%s.ini", pname);
//Prüfen ob Datei existiert, wenn nicht, erstellen.
if(!fexist(path)) dini_Create(path);
//Abfrage direkt aus der Datei:
if(dini_Int(path, "canPickAgain") > gettime()) return SendClientMessage(playerid, 0xFF0000FF, "Error: Du kannst nur alle 60 Sekunden ein Geschenk aufnehmen.");
for(new i = 0; i < MaxGifts; i++)
{
if(GiftBox[i][e_x] == 0.0 && GiftBox[i][e_y] == 0.0 && GiftBox[i][e_z] == 0.0) continue;
if(GiftBox[i][e_oID] == -1) continue;
if(IsPlayerInRangeOfPoint(playerid, 2.0, GiftBox[i][e_x], GiftBox[i][e_y], GiftBox[i][e_z]))
{
RandomGift(playerid);
DestroyDynamicObject(GiftBox[i][e_oID]);
DestroyDynamic3DTextLabel (GiftBox[i][e_label] );
PlayerPlaySound(playerid,4202, 0.0, 0.0, 0.0);
SetTimerEx("CreateGiftAgain", 30000, false, "d", i);
GiftBox[i][e_oID] = -1;
//Neuen Wert direkt in die Datei schreiben.
dini_IntSet(path, "canPickAgain", gettime() + 60); //60 Sekunden zu warten
return 1;
}
}
return 1;
}
Die bleibt bestehen, da ja kein Timer gestartet wird, die mit der Spieler ID verbunden ist. Das geht ja nicht, denn wenn der Spieler offline ist, dann besteht da ja keine Verbindung mehr, oder wenn der Server neu gestartet wird.
An sich kann man sich das auch zum Vorteil machen, indem man zum Beispiel dort auch Statistiken über die Geschenke speichert, zum Beispiel wie viele Geschenke der User aufgenommen hat, und wie viel Geld er damit verdient hat. Muss man aber nicht.
Ändert die Art des Geschenks nur das Objekt, also die Model ID des Objektes?
Das kannst du dann relativ einfach so machen:
CMD:giftcreate(playerid, params[])
{
if(isnull(params)) return SendClientMessage(playerid,RED, "/giftboxcreate [1-5]");
new item = strval(params);
if(item < 1 || item > 5) return SendClientMessage(playerid,RED, "/giftboxcreate [1-5]");
if(!CheckAdminName(playerid)) return SendClientMessage(playerid, RED, "{FF1717}ERROR:{FFFFFF} You have no acces to use this command.");
for(new i=0; i<MaxGifts; i++)
{
if(GiftBox[i][e_x] == 0.0 && GiftBox[i][e_y] == 0.0 && GiftBox[i][e_z] == 0.0)
{
switch(item)
{
case 1: GiftBox[i][e_modelID] = 19054;
case 2: GiftBox[i][e_modelID] = 19055;
//...
}
//Daten werden übergeben
new Float:x, Float:y, Float:z, Float:a;
new pID;
GetPlayerPos(playerid, x, y, z);
GetPlayerFacingAngle(playerid, a);
GiftBox[i][e_x] = x;
GiftBox[i][e_y] = y;
GiftBox[i][e_z] = z - 0.4;
GiftBox[i][e_a] = a;
GiftBox[i][e_oID] = CreateDynamicObject(GiftBox[i][e_modelID],x, y, z+0.05 - 0.4, 0.0, 0.0,a);
GiftBox[i][e_label] = CreateDynamic3DTextLabel("/takegift",0x10F441AA,GiftBox[i][e_x], GiftBox[i][e_y], GiftBox[i][e_z]+0.25,8.0);
GetPlayerPos(pID, x,y,z);
SetPlayerPos(pID, x, y, z+2);
//Zuletzt wird die Datei angelegt und das Giftbox gespeichert.
new path[64];
format(path, sizeof(path), "/GiftBoxes/%d.ini", i);
dini_Create(path);
SaveGiftBoxCheck(i);
new string[100];
format(string, sizeof(string), "{00FFFF}Giftbox {FFFF00}(%i) {00FF00}created.",i);
return SendClientMessage(playerid,WHITE, string);
}
}
return SendClientMessage(playerid, WHITE, "{FF1717}ERROR:{FFFFFF} You reached the Limit of the GiftBoxes");
}
Im Enum zu den GiftBox'es musst du dann noch e_modelID, einfügen, und das auch beim Laden und Speichern einbauen, damit die richtige Objekt Model ID geladen wird.