Beitrag von Akino Kiritani ()
Dieser Beitrag wurde gelöscht, Informationen über den Löschvorgang sind nicht verfügbar.
Ich hätte da auch noch paar interessante Tricks.
Eine Alternative für != -1
So kann man das ganze statt so zu schreiben
if(strfind("Hallo wie gehts", "wie") != -1) print("Gefunden");
auch einen Bitoperator nehmen
if(~strfind("Hallo wie gehts", "wie"))print("Gefunden");
Ebenfalls ist es möglich auf einen Index eines zurückgegebenen Arrays zuzugreifen.
enum tData {
a[10],
b[10],
c[10],
}
stock test() {
new str[2][tData] ={{"Hallo","wie","gehts"},{"Hallo","wie","gehts"}};
return str;
}
print((test())[0][a]);
Ausgabe "Hallo"
natürlich geht das auch mit einfachen strings
stock test() {
new str[40] ="Hallo wie gehts";
return str;
}
print((test())[5]);
Da ich hier auch immer wieder falsche oder komplizierte Funktionen dazu sehe, hier eine funktionierende und einfache Variante:
new stock g_days_m[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
stock GetPlayerAge(input[]) //©Jeffry
{
new date[12];
strcat(date, input);
if(date[1] == '.') strins(date, "0", 0, 12);
if(date[4] == '.') strins(date, "0", 3, 12);
if(!date[9] || date[10]) return -1;
new day = 10*(date[0]-48)+(date[1]-48);
new month = 10*(date[3]-48)+(date[4]-48);
new year = 1000*(date[6]-48)+100*(date[7]-48)+10*(date[8]-48)+(date[9]-48);
if(year < 1000 || year > 9999 || month < 1 || month > 12 || day < 1) return -1;
if(month == 2)
{
if(day > 28 && (year % 4 != 0 || (year % 100 == 0 && year % 400 != 0))) return -1;
}
else if(day > g_days_m[month-1]) return -1;
new d, m, y;
getdate(y, m, d);
new age = y - year;
if(m < month) age--;
else if(m == month && d < day) age--;
return (age < 0) ? (-1) : (age);
}
Beispiel zur Nutzung:
ZitatSpoiler anzeigen [12/03/2015 19:34:56] Du hast am 24.01.1993 Geburtstag, damit bist Du 22 Jahre alt! Sehr schön
Keywords: GetPlayerAge, GetSpielerAlter, SpielerJahre, Alter eines Spielers, CalculateAge, BerechneAlter, YearsSince, JahreSeit.
native __SetPlayerCameraLookAt(playerid, Float:x, Float:y, Float:z) = SetPlayerCameraLookAt;
native __InterpolateCameraLookAt(playerid, Float:FromX, Float:FromY, Float:FromZ, Float:ToX, Float:ToY, Float:ToZ, time, cut = CAMERA_CUT) = InterpolateCameraLookAt;
enum CAMERA_LOOKAT_INFO{
Float:_posX,
Float:_posY,
Float:_posZ
};
new cameraLookAt[MAX_PLAYERS][CAMERA_LOOKAT_INFO];
#define SetPlayerCameraLookAt _SetPlayerCameraLookAt
#define InterpolateCameraLookAt _InterpolateCameraLookAt
stock _InterpolateCameraLookAt(playerid, Float:FromX, Float:FromY, Float:FromZ, Float:ToX, Float:ToY, Float:ToZ, time, cut = CAMERA_CUT){
cameraLookAt[playerid][_posX] = ToX;
cameraLookAt[playerid][_posY] = ToY;
cameraLookAt[playerid][_posZ] = ToZ;
__InterpolateCameraLookAt(playerid, FromX, FromY, FromZ, ToX, ToY, ToZ, time, cut);
}
stock _SetPlayerCameraLookAt(playerid, Float:x, Float:y, Float:z){
cameraLookAt[playerid][_posX] = x;
cameraLookAt[playerid][_posY] = y;
cameraLookAt[playerid][_posZ] = z;
__SetPlayerCameraLookAt(playerid, x, y, z);
}
stock GetPlayerCameraLookAt(playerid, &Float:x, &Float:y, &Float:z){
x = cameraLookAt[playerid][_posX];
y = cameraLookAt[playerid][_posY];
z = cameraLookAt[playerid][_posZ];
return 1;
}
@Jack_Bauer:
Da bekommt man doch nur die Koordinaten wieder zurück, die man zuvor in SetPlayerCameraLookAt bzw. InterpolateCameraLookAt eingegeben hat, was macht das für einen praktikablen Sinn? Warum sollte man etwas abfragen, was man zuvor selbst gesetzt hat?
Wenn man die Kamera selbst bewegt dann funktioniert die Funktion nicht, man bekommt immer nur die Koordinaten zurück, die man irgendwann mal mit SetPlayerCameraLookAt bzw. InterpolateCameraLookAt gesetzt hat.
Macht man dann aber SetCameraBehindPlayer dann bekommt man trotzdem die Koordinaten, die man zuvor mit einer der beiden Funktionen gesetzt hat, zurück, und das sind dann falsche Koordinaten.
Das stimmt allerdings, allerdings hat es für mich einen durchaus praktikablen Sinn gemacht, daher habe ich die Funktion auch entwickelt.
Wer sie braucht, nimmt sie dann einfach.
@Jack_Bauer:
Klar, ich kann mir schon vorstellen was du damit angestellt hast, nur ist es vielleicht etwas verwirrend für Leute die es sich einfach raus-kopieren. Das wäre in etwa so, wie wenn man SendClientMessage hookt und dann eine Funktion GetLastSCMColor macht. Prinzipiell könnte man das mit jedem Funktionsparameter jeder Funktion machen.
Hier ein Beispiel wie die Funktion aussehen würde, wie ich davon ausgegangen bin:
stock GetPlayerCameraLookAt(playerid, Float:dist, &Float:x, &Float:y, &Float:z) {
new Float:cmrX, Float:cmrY, Float:cmrZ;
new Float:vctX, Float:vctY, Float:vctZ;
GetPlayerCameraPos(playerid, cmrX, cmrY, cmrZ);
GetPlayerCameraFrontVector(playerid, vctX, vctY, vctZ);
x = cmrX + dist * vctX;
y = cmrY + dist * vctY;
z = cmrZ + dist * vctZ;
return 1;
}
Quelle: https://github.com/MacMailler/…aster/include/r_utils.inc
In der Quelle finden sich auch noch sehr viele weitere nützliche Funktionen.
Natürlich
Die Länge der Vektoren. Also praktisch der Abstand zwischen Spieler und dem Punkt auf dem man schaut. Man kann ja nicht zwangsläufig einen Punkt fest machen, auf den die Kamera schaut, letztendlich ist es ja eine Gerade im Raum auf die man schaut, und darauf muss man den Punkt bestimmen. Dazu braucht man die Distanz.
Stell dir vor du bist in einem Würfel im unteren Eck und schaust auf das Eck diagonal oben auf der anderen Seite (gegenüberliegend). Die Gerade zwischen diesen beiden Punkten ist diese Gerade auf die du schaust, keiner kann sagen, wo genau auf der Gerade du hinschaust, da alle Punkte auf der Gerade die gleiche, nennen wir es Richtung, haben. Nur mit der Distanz kann man einen Punkt bestimmen.
Und wie soll man bitte die Distanz zu einem Punkt herbekommen, den man nicht kennt, weil man ihn ja mit genau dieser Funktion erst herausfinden soll?
Wenn du zum Beispiel abfragen willst ob der Spieler einen bestimmten Punkt anschaut, dann mit einer Schleife über die Distanz. So fragst du zum Beispiel 100 Punkte ab, und schaust ob einer der Punkte mit dem Punkt den du suchst übereinstimmt (in etwa natürlich, genau ist ja nicht möglich).
Dann ist es aber nicht mit der Funktion möglich, einen vollkommen unbekannten Punkt herauszufinden, oder?
Was heißt ein vollkommen unbekannter Punkt? Wie soll man einen Punkt finden den man nicht kennt?
Es ist nicht möglich einen Punkt zu bestimmen, sondern man bestimmt eine Gerade. Auf dieser Gerade befindet sich dann der Punkt auf den man schaut (man schaut auf alle Punkte der Gerade).
Keine Ahnung, dachte bis gerade, dass man das berechnen kann.
Genau das ist aber das, was ich damit bezwecken wollte.
Dann bringt mir deine Funktion leider doch nichts und ich werde weiterhin auf meine zurückgreifen.
Natürlich, in deinem Fall bringt dir die Funktion nicht direkt etwas, das ist klar. Da ist es effizienter so wie du es machst.
Ja, man kann einen Punkt auf einer Gerade berechnen, das geht schon, nur dazu muss man den Punkt ja kennen, um zu schauen ob er auf der Geraden liegt.
EDIT:
@Jack_Bauer:
Das dürfte das sein, was du benötigst bzw. meinst:
stock IsPlayerLookingAtPos(playerid, Float:x, Float:y, Float:z, Float:radius = 3.0, Float:maxdist = 100.0)
{
new Float:cx, Float:cy, Float:cz, Float:vx, Float:vy, Float:vz, Float:dist;
GetPlayerCameraPos(playerid, cx, cy, cz);
GetPlayerCameraFrontVector(playerid, vx, vy, vz);
dist = floatsqroot((cx-x)*(cx-x) + (cy-y)*(cy-y) + (cz-z)*(cz-z));
if(dist > maxdist) return 0;
vx = vx * dist + cx;
vy = vy * dist + cy;
vz = vz * dist + cz;
dist = floatsqroot((vx-x)*(vx-x) + (vy-y)*(vy-y) + (vz-z)*(vz-z));
if(dist > radius) return 0;
return 1;
}
Bei x, y, z gibst du die Position ein, die du abfragen willst, ob der Spieler diese anschaut, bei radius gibst du die erlaubte Abweichung ein (man schaut ja nie direkt auf genau einen Punkt, es kann ja auch ein paar Zentimeter daneben sein) und bei maxdist gibst du die maximale Distanz zu dem Punkt ein (rein theoretisch kann man von jedem Punkt aus jeden Punkt anschauen, aber das macht ja keinen Sinn, wenn man in LV irgendwo steht, dass man dann einen Punkt in LS anschaut, theoretisch schaut man ihn zwar an, praktisch sieht man ihn aber gar nicht, das ist eben weil Geraden ja in beide Richtungen unendlich lang sind).
Somit könnte man auch abfragen, ob man ein Fahrzeug oder ein Objekt anschaut, oder gegebenenfalls sogar einen anderen Spieler.
Beispiele zur Nutzung:
Keywords: IsPlayerLookingAtPos, IsPlayerLookingAtObject, IsPlayerLookingAtVehicle, IsPlayerLookingAtPlayer, LookAtPos, PlayerFacePlayer, PlayerLookAtObject, SpielerSchautAufPos, SpielerSchautAufSpieler, SpielerSchautAufObjekt, SpielerSchautAufFahrzeug
Mit der Funktion VectorSize kannst du das schneller berechnen, quasi anstatt:
dist = floatsqroot((cx-x)*(cx-x) + (cy-y)*(cy-y) + (cz-z)*(cz-z));
Kannst du einfach folgendes schreiben:
dist = VectorSize(cx-x, cy-y, cz-z);
if(dist > radius) return 0;
return 1;
Ein
return (dist <= radius);
reicht
Nette Funktion, gab es aber glaube ich schonmal hier :3
Mit der Funktion VectorSize kannst du das schneller berechnen
Quelle: https://wiki.sa-mp.com/wiki/VectorSize
Ich habe die Funktion absichtlich nicht verwendet, da sie nicht mit den früheren Versionen kompatibel ist, in denen die Camera-Funktionen schon existieren.
Zwecks dem return sagte ich ja bereits, dass ich meine Codes lieber übersichtlich und verständlich halte, sofern es nur ein paar Nanosekunden ausmacht, aber wenn du es so willst, an mir soll es nicht liegen.
Bzw, wer will, mit VectorSize:
Nur versteht den Code wohl kaum einer noch.
Das hier ist nicht der Code-Optimierungs Thread
Ich habe die Funktion absichtlich nicht verwendet, da sie nicht mit den früheren Versionen kompatibel ist
Wieso entwirfst du denn Funktionen für alte SA:MP Versionen. Macht irgendwie keinen Sinn...da bald eh alle 0.3.7 nutzen werden...oder ~95% aller Server eh 0.3z momentan nutzen.
Zitat von »Kaliber«
Das hier ist nicht der Code-Optimierungs Thread
Das war ja auch weniger Optimiert, eher hätte es die schreibweise vereinfacht bzw den Code übersichtlicher und kürzer gemacht (Das schneller wäre nur ein positiver Nebeneffekt.)
Wenn wir schon dabei sind:
mfg.
//Edit: Da war n TAG Mismatch drinnen..
den Code übersichtlicher
Also übersichtlicher ist das so ganz sicher nicht.
Übersichtlicher wäre es wenn untereinander und nicht alles hintereinander gequescht.
Übersichtlicher wäre es wenn untereinander und nicht alles hintereinander gequescht.
Ich habe von meinem Beitrag davor gesprochen und natürlich ist dist = VectorSize(cx-x, cy-y, cz-z); übersichtlicher als dist = floatsqroot((cx-x)*(cx-x) + (cy-y)*(cy-y) + (cz-z)*(cz-z));