Ich weiß gar nicht, ob es solch eine Funktion schon gibt, oder ob man die einfacher auslesen kann, aber hiermit kann man überprüfen, ob die jeweilige Waffen-ID überhaupt existiert.
stock IsValidWeaponID(weaponid)
{
switch(weaponid)
{
case 0..18:return 1;
case 22..46:return 1;
default:return 0;
}
return 0;
}
Beispiel:
if(!IsValidWeaponID(waffenid))return SendClientMessage(playerid,-1,"Waffen-ID existiert nicht!");
Viel Spaß damit!
Nützliche Codeschnipsel
- breadfish
- Geschlossen
Wichtiger Hinweis: Bitte ändert nicht manuell die Schriftfarbe auf schwarz sondern belasst es bei der Standardeinstellung. Somit tragt ihr dazu bei dass euer Text auch bei Verwendung unseren dunklen Forenstils noch lesbar ist!
Tipp: Ihr wollt längere Codeausschnitte oder Logfiles bereitstellen? Benutzt unseren eigenen PasteBin-Dienst Link
-
-
Ich hab hier auch mal wieder paar Sachen
SWAP
Als erstes die gute alte SWAP Funktion ohne Variablen (ich weiß ist schon alt, habe ich hier aber noch nicht gesehen):#define SWAP(%0,%1) (((%0)^=(%1)),((%1)^=(%0)),((%0)^=(%1)))
new a=5,b=10;
SWAP(a,b);
printf("a: %d | b: %d",a,b); //->Output: a: 10 | b: 5TotalBits
Als nächstes eine sehr nützliche Funktion, wenn man die Anzahl an 1nser Bits in einer Zahl bestimmen will:Beispiele:
1. 0xF = 15 = 0b1111 //Wir sehen hier 4x die 1
2. 0xA = 10 = 0b1010 //Hier sehen wir 2x die 1Ich denke jedem ist klar, was ich meine um dies zu ermitteln, ohne Schleife, kann man Bit-Shifting verwenden:
#include <a_samp>
main() {
printf("%d",GetTotalBits(0xF)); //-> 4
printf("%d",GetTotalBits(10)); //-> 2
}stock GetTotalBits(v) {
v -= ((v >> 1) & 0x55555555),v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
return (((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 0x18);
}Kleiner bzw Größer
Wenn man 2 Variablen hat, x = 13 und y = 14 und prüfen will welche kleiner bzw größer ist, kann man das so machen:#define min(%0,%1) (((%0)<(%1))?(%0):(%1))
#define max(%0,%1) (((%0)>(%1))?(%0):(%1))new x = 13, y = 14;
new r = min(x,y); //r = 13
new z = max(x,y); //z = 14/*
Man könnte das auch durch Bit-Shifting lösen (da das der Titel ist :D):
new x = 13, y = 14;
new r = y ^ ((x ^ y) & -(x < y)); //Das gibt das minimum zurück (13)
new z = x ^ ((x ^ y) & -(x < y)); //Das gibt das maximum zurück (14)Allerdings ist diese Variante wesentlich langsamer, als der ternary Operator :)
*/Viel Spaß damit
mfg.
-
Diese SWAP Methode ist zwar "schön" (wie man's nimmt), aber nicht wirklich robust. Wenn man die gleiche Variable zwei mal nimmt, kommt 0 raus (logischerweise).
Beispiel:
new a=5;
SWAP(a,a);
printf("a: %d",a); //Gibt "a: 0" aus.
Klar, wirklich Sinn macht das nicht, aber nehmen wir mal an, jemand hat einen ziemlich langen Code und irgendwann tritt sowas hier auf (natürlich stark vereinfacht dargestellt):
new gVar = 10;public OnFilterScriptInit()
{
EineFunktion(gVar);
return 1;
}stock EineFunktion(&lVar)
{
SWAP(lVar,gVar);
printf("lVar: %d | gVar: %d",lVar, gVar); //Gibt "lVar: 0 | gVar: 0" aus.
}
Hier sieht man es vielleicht noch, aber in komplexen Codes wird man das irgendwann nicht mehr sehen und dann passiert ein Fehler, den der Compiler nicht erkennt. Dann wird es bei der Fehlersuche aber extrem schwer.Besser wäre also (wenn man das Zeitliche nicht in Betracht zieht):
#define SWAP(%0,%1) (%0=(((%0)==(%1))?(%0=%0*1):(((%0)^=(%1)),((%1)^=(%0)),((%0)^=(%1)))))Außerdem wird auf sämtlichen Seiten über den Sinn dieser Funktion (mit den Binäroperatoren) diskutiert, da es bei heutigen Prozessoren eigentlich keinen Unterschied mehr macht, ob man es jetzt mit einer Variable macht, oder nicht, da im Endeffekt im Prozessor das gleiche geschieht, bzw. eine Mehrarbeit verrichtet werden muss. Hier ein paar mehr Informationen:
http://stackoverflow.com/quest…t-way-to-swap-values-in-c
http://en.wikipedia.org/wiki/X…for_avoidance_in_practiceAlleine der Satz trifft den Nagel auf den Kopf:
ZitatNumber 2 is often quoted as being the "clever" way of doing it. It is in fact most likely slower as it obscures the explicit aim of the programmer - swapping two variables. This means that a compiler can't optimize it to use the actual assembler ops to swap. It also assumes the ability to do a bitwise xor on the objects.
(Quelle: Stackoverflow Link)Jetzt kommt das angesprochene Zeitliche in Betracht. Hier ein Test:
#define SWAP_K(%0,%1) (((%0)^=(%1)),((%1)^=(%0)),((%0)^=(%1)))
#define SWAP_J(%0,%1) (%0=(((%0)==(%1))?(%0=%0*1):(((%0)^=(%1)),((%1)^=(%0)),((%0)^=(%1)))))
#define SWAP_V(%0,%1) (x = %0, %0 = %1, %1 = x)
new x;
new a, b, t;a = 10; b = 5; t = GetTickCount();
for(new i=0; i<10000000; i++)
{
SWAP_K(a, b);
}
printf("Kaliber: %dms", GetTickCount()-t);a = 10; b = 5; t = GetTickCount();
for(new i=0; i<10000000; i++)
{
SWAP_J(a, b);
}
printf("Jeffry: %dms", GetTickCount()-t);a = 10; b = 5; t = GetTickCount();
for(new i=0; i<10000000; i++)
{
SWAP_V(a, b);
}
printf("Variable: %dms", GetTickCount()-t);Ergebnis:
Zitat[19/02/2015 20:01:34] Kaliber: 637ms
[19/02/2015 20:01:35] Jeffry: 842ms
[19/02/2015 20:01:36] Variable: 371ms
Logisch, dass die robuste Variante von mir langsamer ist, allerdings ist die Variante mit Variable wesentlich schneller. Außerdem kann da der oben angesprochene Fehler mit Verwendung der gleichen Variable nicht passieren, und selbst wenn man es irgendwie hin bekommt wird die Variable nicht auf 0 gesetzt.=> Sinn macht es also nicht, keine Variable zu verwenden, da es fast doppelt so lange dauert.
-
Kleiner bzw Größer
Wenn man 2 Variablen hat, x = 13 und y = 14 und prüfen will welche kleiner bzw größer ist, kann man das so machen:#define min(%0,%1) (((%0)<(%1))?(%0):(%1))
#define max(%0,%1) (((%0)>(%1))?(%0):(%1))new x = 13, y = 14;
new r = min(x,y); //r = 13
new z = max(x,y); //z = 14
Musst natürlich das Rad neu erfinden:Zitatcore.inc
native min(value1, value2);
native max(value1, value2);Zitatstock GetTotalBits(v) {
v -= ((v >> 1) & 0x55555555),v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
return (((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 0x18);
}
Gib doch wenigstens den ursprünglichen Autoren an, zb den hier. Als ob es noch Niemandem aufgefallen wäre, dass hier ständig Sachen von sa-mp.com gepostet werden mit leichter Umstrukturierung (zB Änderungen der Variablennamen, mehrere Anweisungen in 1 Zeilen, Hex Schreibweise anstatt Dezimal).
Gleiches würde ich auch bei SWAP anmerken. -
Gib doch wenigstens den ursprünglichen Autoren an, zb den hier. Als ob es noch Niemandem aufgefallen wäre, dass hier ständig Sachen von sa-mp.com gepostet werden mit leichter Umstrukturierung (zB Änderungen der Variablennamen, mehrere Anweisungen in 1 Zeilen, Hex Schreibweise anstatt Dezimal).
Gleiches würde ich auch bei SWAP anmerken.
War mir gar nicht bekannt das das schon da gepostet wurde.Nein, ich hatte mich auf dieser Seite: https://graphics.stanford.edu/~seander/bithacks.html
Mal umgeschaut und da ist mir das aufgefallen...=> Sinn macht es also nicht, keine Variable zu verwenden, da es fast doppelt so lange dauert.
Das hier ist nicht der Code-Optimierungs Thread Bei meinen Beispielen ging es nicht um Speed (wie unten auch angemerkt) wollte lediglich das mal vorstellen, dass diesen "Swap" einige nicht kennen. -
Und was ist dann daran nützlich, wenns keine vorteile (wie z.b. speed) mit sich bringt?
-
wenns keine vorteile
Es hat ja einen Vorteil, man muss keine Variable erstellen. -
Das macht aber auch nur dann Sinn, wenn man wenig Arbeitsspeicher zur Verfügung hat, was bei SAMP nicht der Fall ist. Man kann für sowas auch eine globale Integer Variable erstellen, die für alle temporären Speichervorgänge verwendet wird, die sich niemals überschneiden, dann muss auch nicht explizit dafür eine Variable erstellt werden. Dann ist es, wie dargestellt, voll funktionsfähig und wesentlich schneller. Und der Code ist auch für Anfänger zu verstehen. Mit den Binäroperatoren fängt nämlich 99% hier nichts an.
Außerdem ist, wie gesagt, der Code (SWAP) den du gepostet hast fehlerhaft und daher alles andere als nützlich.
Um nicht unnötig zu posten:
maddin: (Post unten)
Nee, das wäre sogar noch besser, da es funktionsfähig und wenigstens gleich performant ist. -
Das ist dann ungefähr genau so vorteilhaft wie #define SCM SendClientMessage
-
ocmd:pn(playerid, params[])
{
new sender[MAX_PLAYER_NAME+1];
GetPlayerName(playerid, sender, sizeof(sender));
new pID, text[128];
if(sscanf(params, "us[128]", pID, text)) return SendClientMessage(playerid, COLOR_RED, "INFO: /PN [ID] [TEXT]");
format(text, 200, "[PN] Spieler %s sagt : '%s'", sender, text);
SendClientMessage(pID, COLOR_RED, text);
return 1;
}MfG
-
Naja...das geht aber besser.
ocmd:pn(playerid, params[])
{
new sender[MAX_PLAYER_NAME+1]; //Das +1 brauchst du nicht, da die Namen nur 24 Zeichen haben können und MAX_PLAYER_NAME 24 ist.
GetPlayerName(playerid, sender, sizeof(sender));new pID, text[128]; //Es können 144+1(EOS) Zeichen in SendClientMessage angezeigt werden.
if(sscanf(params, "us[128]", pID, text)) return SendClientMessage(playerid, COLOR_RED, "INFO: /PN [ID] [TEXT]");
format(text, 200, "[PN] Spieler %s sagt : '%s'", sender, text); //200 passt hier nicht, du hast es ja nur mit 128 deklariert.
SendClientMessage(pID, COLOR_RED, text);
return 1;
}
zu:
ocmd:pn(playerid, params[])
{
new sender[MAX_PLAYER_NAME], pID, text[145];
if(sscanf(params, "us[145]", pID, text)) return SendClientMessage(playerid, COLOR_RED, "INFO: /PN [ID/NAME] [TEXT]");
GetPlayerName(playerid, sender, sizeof(sender));
format(text, sizeof(text), "[PN] Spieler %s sagt : '%s'", sender, text);
return SendClientMessage(pID, COLOR_RED, text);
} -
Naja, Ich dachte es wäre so besser.
Aber danke für deine Rückmeldung !
Jetzt weis ich was ich besser machen kann. -
new sender[MAX_PLAYER_NAME+1]; //Das +1 brauchst du nicht, da die Namen nur 20 Zeichen haben können und MAX_PLAYER_NAME 24 ist.
Im Grunde hast du recht, ABER die Namen können auch 24 Zeichen lang werden, Grund ist hier SetPlayerName, welches erlaubt dem Namen 24 Zeichen zu geben.Nützlich ist sowas bspw. wenn man einen "Tag" beim Connecten davor setzt.
Player names can be up to 24 characters when using this function,
but when joining the server from the SA-MP server browser,
players' names must be no more than 20 and less than 3 characters (the server will deny entry).
This allows for 4 characters extra when using SetPlayerName. -
Im Grunde hast du recht, ABER die Namen können auch 24 Zeichen lang werden, Grund ist hier SetPlayerName, welches erlaubt dem Namen 24 Zeichen zu geben.
Oh, ja stimmt. Hatte ich verdrängt, Danke für den Hinweis.
Allerdings spielt das auch keine Rolle, da MAX_PLAYER_NAME 24 ist, und da passen die 24 Buchstaben vom Spieler-Name rein. Ein +1 ist also trotzdem nicht unbedingt notwendig.Habe dennoch meinen Kommentar natürlich angepasst.
-
Ich hab gerade mal einen Code geschrieben um einen String zu verschlüsseln und dann wieder zu entschlüsseln.
Im Prinzip nichts großartiges, doch wenn man in einer Datei z.B. etwas speichern will, was nicht jeder lesen soll und aber trotzdem wieder im Klartext haben will, ist es ganz praktisch:
static stock const c_v[] = { 0xFBCAE, 0xDFC, 0xA8D, 0xAFECB };
stock Crypt(string[]) {
for(new i,l=strlen(string),tmp[2]; i<l; i++) {
format(tmp,sizeof tmp,"%c",string[i]+c_v[0]+(c_v[1]*c_v[2])+c_v[3]+(l*i));
string[i] = tmp[0];
}
return 1;
}stock DeCrypt(string[]) {
for(new i,l=strlen(string),tmp[2]; i<l; i++) {
format(tmp,sizeof tmp,"%c",string[i]-c_v[0]-(c_v[1]*c_v[2])-c_v[3]-(l*i));
string[i] = tmp[0];
}
return 1;
}Hier ein Beispiel:
new string[] = "Hallo Welt";
Crypt(string);
print(string);
DeCrypt(string);
print(string);Das sieht dann so aus:
//Edit:
Hier nochmal ein paar mehr Beispiele:Also, viel Spaß damit
//Edit²: Rechtschreibfehler
mfg.
-
EmptyVehicle
Quellcode
stock EmptyVehicle(vID)
{
for(new i=0, yourvID; i < GetMaxPlayers(); i++)
{
if(IsPlayerConnected(i) && !IsPlayerNPC(i))
{
if(IsPlayerInAnyVehicle(i))
{
yourvID = GetPlayerVehicleID(i);
if(yourvID == vID)return 0;
}
}
}
return 1;
}Verwendung
if(EmtpyVehicle(vID)) //Fahrzeug ist leer.mfg
-
Und was ist wenn ein NPC in diesem Fahrzeug ist? Falls man es löschen will, dann hätte der NPC keins mehr.
Du kannst es viel einfacher so schreiben:
stock EmptyVehicle(vID)
{
for(new i=0, j=GetMaxPlayer(); i<j; i++) if(IsPlayerInVehicle(i, vID)) return 0;
return 1;
} -
Ich weiss ja nicht, aber haben wir so eine Funktion hier nicht schon zig mal gepostet bekommen ?
-
Eine Funktion um ein SendClientMessage mit "Variablen" ohne ihn neu formatieren zu müssen:
/* Stellen Wir uns vor dieser Teil steht in einer Include. */
#define SCME(%0,%1,%2,%3) format(string,sizeof string,%2,%3),SendClientMessage(%0,%1,string)stock GetName(playerid) {
new name[MAX_PLAYER_NAME];
GetPlayerName(playerid,name,MAX_PLAYER_NAME);
return name;
}
/*******************************************************************/
//Und dann die Nachricht senden:
new string[64];
SCME(playerid,-1, "Hallo, %s. Dein Level beträgt: %d",GetName(playerid),GetPlayerScore(playerid));Kaliber:
Ich hoffe das war O.K das ich das hier poste,
ist ne nützliche Funktion die der ein oder andere bestimmt gebrauchen kann. -
Ich hab gerade was interessantes herausgefunden.
Ihr kennt ja alle folgendes:
forward func();
public func()
{
print("hi");
return 1;
}Wenn man das aber abgrenzen will in einer Include z.B. und dort per Timer aufrufen will, aber nicht im Gamemode, kann man folgendes machen:
static func();
public func()
{
print("hi");
return 1;
}
So kann man also quasi static als forward nutzenÜbrigens für die, die es noch nicht wussten, in Pawn gibt es auch totale public Variablen:
public x = 5;
main()
{
printf("%d",x); //-> 5
}Das ist eigentlich nur für Plugins relevant und macht keinen unterschied zur normalen "new" Deklaration in diesem Sinne.
mfg.