Eredeti témát Slice írta a hivatalos fórumon.A további napok folyamán frissíteni fogom, mert még nincs benne minden, de a fõ rész az benne van.
Fordítási hibák szerintem lehetnek, ezért elnézést!
Több dolog egy statmentben
Néhány helyen szükségünk van arra, hogy egy sorba több dolgot is lefuttassunk.
Visszatérni több értékkel, stb. Ha visszatértsz több értékkel, akkor a return mindig az utolsó értékét fogja visszaadni.
Ezt a következõ képpen tudjuk elvégezni:
[pawn]
stock KickEx( playerid, reason[ ] )
SendClientMessage( playerid, 0xC00000FF, \"Kickelve lettél!! Indok:\" ), SendClientMessage( playerid, 0xC00000FF, reason ), Kick( playerid );
// Két üzenet elküldése, azátn a játékos kirúgása
stock DoStuff( playerid )
return DoFirstThing( playerid ), DoSecondThing( playerid ), DoThirdThing( playerid ), DoLastThing( playerid );
// DoStuff a DoLastThing értékével fog visszzatérni
public OnPlayerRequestSpawn( playerid )
{
if ( !IsPlayerLoggedIn( playerid ) )
return SendClientMessage( playerid, 0xC00000FF, \"Nem vagy bejelentkezve!\" ), 0;
// Elküldjük az üzenetet és 0-val térünk vissza.
return 1;
}
[/pawn]
Egyszerû szám -> bool-ra konvertálása
Néha vannak olyan helyzetek, hogy bool-ra kell konvertálni egy megadott számot.
Ezt a következõ képpen teheted meg a legegyszerûbben:
[pawn]
new myInt = 50;
new bool:myBool = !!myInt;
[/pawn]
Vagy akár mûködik egy funkcióval is:
[pawn]
new
bool:bResult = !!mysql_query_ex(query),
iCount;
if(!bResult) return SendClientMessage(playerid, COLOR_RED, \"HIBA: Hibás lekérdezés!\");
[/pawn]
De így is:
[pawn]
#define IsValidVehicle(%1) \\
(!!GetVehicleModel(%1))
[/pawn]
Változó tag figyelmeztetés kiküszöbölése
Ha egy elõtagos funckiónak/változónak akarod az értékét kiírni egy olyan funkcióban, ami nem támogatja azt a tagot, akkor a fordító figyelmeztetni fog, hogy itt valami nincs rendben. Itt nem csináltunk semmit se rosszul, csak ez így nem helyes.
Ilyen esetben kell letörölni a tagot a funkció elõl, és minden jól fog mûködni!
Példa:
[pawn]
new Text3D:t3dTest = Create3DTextLabel( .. ), Text:txTest = TextDrawCreate( .. );
printf( \"DEBUG: %d, %d\", _:t3dTest, _:txTest );
[/pawn]
Egyébként ez a dolog szerintem nagyon is hasznos, fõleg a bit flagoknál.
Vegyük azt, hogy van két változónk, két enum taggal. Ha az elsõ váltózónál valamit próbálunk állítani a második enumból, akkor figyelmeztetni fog, mivel az a másodikhoz tartozik és nem pedig az elsõhöz. Persze ha lehagyjuk a tagokat, akkor nemfog. De ilyenkor a bit flagnál nagy keveredések lehetnek, ezért érdemes ott az elõtagokat használni.
\"Char-tömbök\"
PAWN-ban van egy olyan lehetõség, hogy minden cellának egy bájtot foglal le. Ez a csomagolt string. A legtobb SA-MP függvények sajnos nem támogatják ezt és nagyon sokan még nem is hallottak róla. Egy 4bájtos tömbnek az értékei -2,147,483,648 és 2,147,483,647 között lehetnek.
De ha neked nincs szükséged negatív értékekre és a megadott érték kisebb, mint 255, akkor miért is ne spóroljunk memóriát?
Csomagolt stringekkel 0 és 255 között tárolhatunk számokat. ( Nincsenek negatív számok )
Itt is van róla egy példa:
[pawn]
new bool:g_IsPlayerSomething[MAX_PLAYERS]; // 500 cella * 4 bájt cellánként = 2000 bájt! <4 bájtos tömb>
new bool:g_IsPlayerSomething[MAX_PLAYERS char]; // 500 bájt = .. 500 bytes! <Csomagolt string, itt egy cella egy bájt>
[/pawn]
Ha ezt a megoldást használod 50x a normál 4 bájtos tömbök helyett, akkor
megspórolsz 75,000 bájtot (~73 kb).Vigyázz!Ezekhez a tömbökhöz kapcsos zárójeleket (
{ } ) kell használnod a szögletes helyett. (
[ ] ),
Példa:
[pawn]
public OnPlayerConnect( playerid )
{
g_IsPlayerSomething{ playerid } = false;
// ^ ^
}
public OnPlayerSpawn( playerid )
{
// v v
if ( g_IsPlayerSomething{ playerid } )
{
// ..
}
}
[/pawn]
Bitmûveletek (Bit-flag)
Tudtad, hogy lehet 32 igaz/hamis értéket tárolni egy változóban? Ezzel nem csak memóriát takarítasz meg, hanem sokkal átláthatóbb lesz a kód.
Ehhez egyáltalán nem kell megértened, hogy hogyan mûködik a kettes számrendszer, de ajánlott.
Ha van 100 hamis/igaz (bool) változód játékosonként, akkor az 195KB memóriát foglal. Bár, ha 4 tömböt használsz ezzel a megoldással, akkor csak 8KB-ot fog használni. Az eredmény ugyanaz lesz, mintha rendes bool tömbökkel csinálnád, csak megspóroltál 187KB-ot.
// BitFlag Makrók
#define BitFlag_Get(%0,%1) ((%0) & (%1)) // Megnézzük, hogy a flag be-e van kapcsolva. Ha igen, akkor visszatér az értékével*, ha nem, akkor 0-val tér vissza.
#define BitFlag_On(%0,%1) ((%0) |= (%1)) // Bekapcsoljuk a flagot
#define BitFlag_Off(%0,%1) ((%0) &= ~(%1)) // Kikapcsoljuk a flagot.
#define BitFlag_Toggle(%0,%1) ((%0) ^= (%1)) // Kicseréljük a flag értékét. Ha igaz volt, akkor hamis lesz, ha hamis, akkor igaz.
// * A flag értéke nem 1 lesz, hanem az, ami itt ez enumban van.
// Ha PLAYER_BLABLA_3-t beállítottuk neki, akkor g_PlayerFlags[playerid] & PLAYER_BLABLA_3 értéke 00000000000000000000000000100000 (32) lesz.
enum PlayerFlags:(<<= 1) // Ez itt azt jelenti, hogy mennyivel növekedjenek az értékek az enum-ban {
// Ügyelj arra, hogy ezt (<<<=1) semmi képp ne felejtsd el, külömben minden flagod hamis lesz.
// Az kezdõ érték az enum-ban 1 és ezt eltoja mindig eggyel alrébb balra.
// A következõ képpen fognak mindig növekedni:
PLAYER_IS_LOGGED_IN = 1, // 0b00000000000000000000000000000001 | 1
PLAYER_HAS_GANG, // 0b00000000000000000000000000000010 | 2
PLAYER_CAN_BUY_PROPERTIES, // 0b00000000000000000000000000000100 | 4
PLAYER_BLABLA_1, // 0b00000000000000000000000000001000 | 8
PLAYER_BLABLA_2, // 0b00000000000000000000000000010000 | 16
PLAYER_BLABLA_3, // 0b00000000000000000000000000100000 | 32
PLAYER_BLABLA_4, // 0b00000000000000000000000001000000 | 64
PLAYER_BLABLA_5, // 0b00000000000000000000000010000000 | 128
PLAYER_BLABLA_6, // 0b00000000000000000000000100000000 | 256
PLAYER_BLABLA_7, // 0b00000000000000000000001000000000 | 512
PLAYER_BLABLA_8, // 0b00000000000000000000010000000000 | 1024
PLAYER_BLABLA_9, // 0b00000000000000000000100000000000 | 2048
PLAYER_BLABLA_10, // 0b00000000000000000001000000000000 | 4096
PLAYER_BLABLA_11, // 0b00000000000000000010000000000000 | 8192
PLAYER_BLABLA_12, // 0b00000000000000000100000000000000 | stb..
PLAYER_BLABLA_13, // 0b00000000000000001000000000000000
PLAYER_BLABLA_14, // 0b00000000000000010000000000000000
PLAYER_BLABLA_15, // 0b00000000000000100000000000000000
PLAYER_BLABLA_16, // 0b00000000000001000000000000000000
PLAYER_BLABLA_17, // 0b00000000000010000000000000000000
PLAYER_BLABLA_18, // 0b00000000000100000000000000000000
PLAYER_BLABLA_19, // 0b00000000001000000000000000000000
PLAYER_BLABLA_20, // 0b00000000010000000000000000000000
PLAYER_BLABLA_21, // 0b00000000100000000000000000000000
PLAYER_BLABLA_22 // 0b00000001000000000000000000000000
};
new
// Létrehozink egy tömböt ugyanazzal a taggal, mint ami az enum.
PlayerFlags:g_PlayerFlags[MAX_PLAYERS]
;
public OnPlayerConnect(playerid) {
// 0 - Minden flag kikapcsolva (hamis). A PlayerFlags tag kell, miven nélküle warningozni fog a fordító.
g_PlayerFlags[playerid] = PlayerFlags:0;
}
public OnPlayerLogIn(playerid) {
BitFlag_On(g_PlayerFlags[playerid], PLAYER_IS_LOGGED_IN);
// Makró nélkül:
// g_PlayerFlags[playerid] |= PLAYER_IS_LOGGED_IN;
}
public OnPlayerJoinGang(playerid) {
BitFlag_On(g_PlayerFlags[playerid], PLAYER_HAS_GANG);
// Makró nélkül:
// g_PlayerFlags[playerid] |= PLAYER_HAS_GANG;
}
public OnPlayerLeaveGang(playerid) {
BitFlag_Off(g_PlayerFlags[playerid], PLAYER_HAS_GANG);
// Makró nélkül:
// g_PlayerFlags[playerid] &= ~PLAYER_HAS_GANG;
}
public OnPlayerUpdate(playerid) {
// Felcseréljük minden frissítésnél a bit flag értékét
BitFlag_Toggle(g_PlayerFlags[playerid], PLAYER_BLABLA_19);
if (BitFlag_Get(g_PlayerFlags[playerid], PLAYER_BLABLA_19)) {
DoSomething();
}
// Makró nélkül:
// g_PlayerFlags[playerid] ^= PLAYER_BLABLA_19;
//
// if (g_PlayerFlags[playerid] & PLAYER_BLABLA_19) {
// DoSomething();
// }
}