Szerző Téma: Alap sscanf dolgok  (Megtekintve 2977 alkalommal)

Nem elérhető Szasza

  • 388
    • Profil megtekintése
Alap sscanf dolgok
« Dátum: 2013. november 18. - 13:18:52 »
+1 Show voters
Üdv.
Mivel a Segítségkérés topicban már számtalan ilyen témát láttam ezért most összefoglalóan megírtam az összes ilyen pont,pénz és skin adást... az admin tud felülírni vagy hozzáadni akárkinek pénz vagy pontot illetve az admin tud skint állítani akárkinek és a játékos is tud skint állítani magának... Remélem valakinek a segítségére leszek ezzel :)
Letöltés: http://www.solidfiles.com/d/c982c8447b/
 

//Alap sscanf dolgok
//Készítette:Szasza
#include
#include
#include
new mp,name1[MAX_PLAYER_NAME],name2[MAX_PLAYER_NAME];
#if defined FILTERSCRIPT
 
public OnFilterScriptInit()
{
print(\"\\n--------------------------------------\");
print(\" Alap sscanf parancsok betöltve. By:Szasza\");
print(\"--------------------------------------\\n\");
return 1;
}
public OnFilterScriptExit()
{
       print(\"\\n--------------------------------------\");
print(\" Alap sscanf parancsok kiiktatva. By:Szasza\");
print(\"--------------------------------------\\n\");
return 1;
}
#else
#endif
//adminnal akárkinek lehet skint állítani
CMD:setskin(playerid,params[])
{
       new skinid,string[128],string2[128];
       if(!IsPlayerAdmin(playerid)) return SendClientMessage(playerid,-1,\"Nem vagy bejelenetkezve az RCON adminba!\");//ezt átlehet írni a saját amdinrendszerünkre
if(sscanf(params,\"id\",mp,skinid)) return SendClientMessage(playerid,-1,\"Használat: /setskin \");
{
if(skinid <= 299 && skinid >= 0)
{
                   GetPlayerName(playerid,name1,sizeof(name1));
            GetPlayerName(mp,name2,sizeof(name2));
    format(string,sizeof(string),\"Admin:%s beállította a skined(SkinID:%d)\",name1,skinid);
    format(string2,sizeof(string2),\"Beállítottad %s skinét(SkinID:%d)\",name2,skinid);
    SendClientMessage(mp,-1,string);
    SendClientMessage(playerid,-1,string2);
    SetPlayerSkin(mp,skinid);
}
else   SendClientMessage(playerid,-1,\"A SkinID-nek 0 és 299 között kell lennie!\");
}
return 1;
}
//magadnak betudod állítani a skined
CMD:myskin(playerid,params[])
{
   new skinid,string[128];
   if(sscanf(params,\"i\",skinid)) return SendClientMessage(playerid,-1,\"Használat: /myskin  \");
   {
if(skinid <= 299 && skinid >= 0)
{
    format(string,sizeof(string),\"Beállítottad a skined(SkinID:%d)\",skinid);
    SendClientMessage(playerid,-1,string);
    SetPlayerSkin(playerid,skinid);
}
else   SendClientMessage(playerid,-1,\"A SkinID-nek 0 és 299 között kell lennie!\");
   }
   return 1;
}
//adminnal akárkinek átlehet állítani a pontjait(teljesen felülírja a pontjait)
CMD:setscore(playerid,params[])
{
       new score,string[128],string2[128];
       if(!IsPlayerAdmin(playerid)) return SendClientMessage(playerid,-1,\"Nem vagy bejelenetkezve az RCON adminba!\");//ezt átlehet írni a saját amdinrendszerünkre
if(sscanf(params,\"id\",mp,score)) return SendClientMessage(playerid,-1,\"Használat: /setscore \");
{
               GetPlayerName(playerid,name1,sizeof(name1));
        GetPlayerName(mp,name2,sizeof(name2));
format(string,sizeof(string),\"Admin:%s beállította a pontjaidat(Pontok:%d)\",name1,score);
       format(string2,sizeof(string2),\"Beállítottad %s pontjait.(Pontok:%d)\",name2,score);
              SendClientMessage(mp,-1,string);
        SendClientMessage(playerid,-1,string2);
              SetPlayerScore(mp,score);
}
return 1;
}
//adminnal pontot lehet adni akárkinek (hozzáadja a meglévõ pontjához)
CMD:givescore(playerid,params[])
{
       new score,string[128],string2[128];
       if(!IsPlayerAdmin(playerid)) return SendClientMessage(playerid,-1,\"Nem vagy bejelenetkezve az RCON adminba!\");//ezt átlehet írni a saját amdinrendszerünkre
if(sscanf(params,\"id\",mp,score)) return SendClientMessage(playerid,-1,\"Használat: /givescore \");
{
               GetPlayerName(playerid,name1,sizeof(name1));
        GetPlayerName(mp,name2,sizeof(name2));
format(string,sizeof(string),\"Admin:%s pontot adott (+pontod:%d,összes pontod: %d)\",name1,score,GetPlayerScore(mp)+score);
       format(string2,sizeof(string2),\"Pontot adtál %s -nak/nek.(+pont:%d,összes pontja: %d)\",name2,score,GetPlayerScore(mp)+score);
              SendClientMessage(mp,-1,string);
        SendClientMessage(playerid,-1,string2);
              SetPlayerScore(mp,score+GetPlayerScore(playerid));
}
return 1;
}
//adminnal akárkinek átlehet állítani a pénzét(teljesen felülírja a pénzét)
CMD:setmoney(playerid,params[])
{
       new money,string[128],string2[128];
       if(!IsPlayerAdmin(playerid)) return SendClientMessage(playerid,-1,\"Nem vagy bejelenetkezve az RCON adminba!\");//ezt átlehet írni a saját amdinrendszerünkre
if(sscanf(params,\"id\",mp,money)) return SendClientMessage(playerid,-1,\"Használat: /setmoney \");
{
               GetPlayerName(playerid,name1,sizeof(name1));
        GetPlayerName(mp,name2,sizeof(name2));
format(string,sizeof(string),\"Admin:%s beállította a pénzed(Pénzed:$%d)\",name1,money);
       format(string2,sizeof(string2),\"Beállítottad %s pénzét.(Pénze:$%d)\",name2,money);
              SendClientMessage(mp,-1,string);
        SendClientMessage(playerid,-1,string2);
               ResetPlayerMoney(mp);
              GivePlayerMoney(mp,money);
}
return 1;
}
//adminnal pénzt lehet adni akárkinek (hozzáadja a meglévõ pénzéhez)
CMD:givemoney(playerid,params[])
{
       new money,string[128],string2[128];
       if(!IsPlayerAdmin(playerid)) return SendClientMessage(playerid,-1,\"Nem vagy bejelenetkezve az RCON adminba!\");//ezt átlehet írni a saját amdinrendszerünkre
if(sscanf(params,\"id\",mp,money)) return SendClientMessage(playerid,-1,\"Használat: /givemoney \");
{
               GetPlayerName(playerid,name1,sizeof(name1));
        GetPlayerName(mp,name2,sizeof(name2));
format(string,sizeof(string),\"Admin:%s pénzt adott(+pénz:$%d,Összes pénzed: $%d)\",name1,money,GetPlayerMoney(mp)+money);
       format(string2,sizeof(string2),\"Pénzt adtál %s -nak/nek.(+pénz:$%d,Összes pénze: $%d)\",name2,money,GetPlayerMoney(mp)+money);
              SendClientMessage(mp,-1,string);
        SendClientMessage(playerid,-1,string2);
          GivePlayerMoney(mp,money);
}
return 1;
}
« Utoljára szerkesztve: 2013. november 18. - 22:17:14 írta Szasza »

Nem elérhető kurta999

  • 2759
  • Éllő fédisznó
    • Profil megtekintése
Alap sscanf dolgok
« Válasz #1 Dátum: 2013. november 18. - 18:17:41 »
0 Show voters
\"i,d\"
nemkell a vesszõ.

Nem elérhető Szasza

  • 388
    • Profil megtekintése
Alap sscanf dolgok
« Válasz #2 Dátum: 2013. november 18. - 18:30:29 »
0 Show voters

\"i,d\"
nemkell a vesszõ.
 
[/quote]
Így is mûködik de akkor javítom :) köszi h szoltál

Alap sscanf dolgok
« Válasz #3 Dátum: 2013. november 18. - 20:05:05 »
0 Show voters
@Szasza
Már nem elõször látom tõled az ilyen sorrendbeli kód írást.
 
        new skinid,string[128],string2[128];
       GetPlayerName(playerid,name1,sizeof(name1));
       GetPlayerName(mp,name2,sizeof(name2));
       if(!IsPlayerAdmin(playerid)) return SendClientMessage(playerid,-1,\"Nem vagy bejelenetkezve az RCON adminba!\");//ezt átlehet írni a saját amdinrendszerünkre
       if(sscanf(params,\"id\",mp,skinid)) return SendClientMessage(playerid,-1,\"Használat: /setskin \");

 
Ha a játékos nem Rcon admin ként írja be a jelszót (ugyanez a helyzet sscanf elõtt is) és megjelenik számára az üzenet hogy õ nem az, akkor a kód elõtt miért kéred le a játékos neveket? (hiszen nem kerül felhasználásra) és közben ahogy írom az egészet észre is vettem hogy mp (gondolom \"másikplayer\" rövidítés) nevét lekéred még mielõtt a sscanf egyáltalán eltárolná az mp változóban a beírt másik játékos azonosítószámát.

Nem elérhető Rexii

  • 471
    • Profil megtekintése
Alap sscanf dolgok
« Válasz #4 Dátum: 2013. november 18. - 21:15:30 »
0 Show voters
Ezek eléggé alap dolgok, de mondjuk engem az érdekelne, hogy
 
if(sscanf(params,\"id\",mp,money))

 
mi alapján kerül be az idézõjelek közötti szöveg? Mitõl függ hogy milyen betût írunk oda?
Mert láttam már \"id\" helyett \"ii\"-t, \"ud\"-t, de ezt sosem értettem

Alap sscanf dolgok
« Válasz #5 Dátum: 2013. november 18. - 21:22:31 »
+1 Show voters
Hasonlóképp mint a format funkció használataként.
Az i és d ugyanaz (integer ill decimal) rövidítése egész számot jelöl.
Az f (float) nem egész szám más nyelven lebegõ pontos szám (3.45).
Az s karakterláncokat jelöl.
De mindenhez van leírás a sscanf topikban.
http://forum.sa-mp.com/showpost.php?p=520110&postcount=1
Az u egy különleges jelölés olyan szempontból hogy játékos név(name) illetve azonosító szám (playerid) beírásra is mûködik.

Nem elérhető ZoleBB

  • 480
  • ZoleBB
    • Profil megtekintése
Alap sscanf dolgok
« Válasz #6 Dátum: 2013. november 18. - 21:26:12 »
0 Show voters
Szep

Nem elérhető Szasza

  • 388
    • Profil megtekintése
Alap sscanf dolgok
« Válasz #7 Dátum: 2013. november 18. - 21:28:13 »
0 Show voters
Köszönöm  ɐʞzssǝlosz :) Mihez is kezdenék nélküled :D nem lenen aki bele szólna minden egyes kommentembe... :) ... de hát persze kell a negatív komment is meg megmondod a hibáim.. de komolyan :D te sose látod meg azt h miért is készítem speciel én a témáim.. de m1.. nem veszekszem .. kell ilyen ember is ;)

Alap sscanf dolgok
« Válasz #8 Dátum: 2013. november 18. - 21:53:39 »
+3 Show voters
@Szasza
Elhiszem hogy segíteni szeretnél, egyes embereknek, de hibás példákkal pont az ellenkezõjét teszed, emiatt születnek a negatív illetve a kritika szerû hozzászólások.
Én nem **szogatásképp írom ezen hozzászólásokat hanem pont a segíteni akarás végett.  8)

Alap sscanf dolgok
« Válasz #9 Dátum: 2013. november 19. - 00:07:05 »
0 Show voters
Megnézni megnéztem de még mindig találok benne kivetni valót.  :angel:
A globálisan létrehozott változók játékos névnek nem igazán megfelelõek igaz úgy tûnik hogy memória területet spórol vele az ember de viszont sok admin esetén akik egy idõben használják a parancsot kis lassulást lehet tapasztalni a mûködésben (gép függõ).
Korábban írtam egy változatot valamiben amiben szépen leírtam valamilyen hasonló parancsban hogyan lehet egyetlen egy változóval lekérni játékos nevet ugyanazt a változót újból felhasználva megjeleníteni az üzenetet.
Most csak egy újabb példával próbálom szemléltetni hogyan célszerûbb írni ilyen parancs-ot/okat:
 
CMD:setskin2(playerid,params[])
{
new
mp,
skinid;
if(!IsPlayerAdmin(playerid)) SendClientMessage(playerid, -1, \"Nem vagy bejelenetkezve az RCON adminba!\");//ezt átlehet írni a saját amdinrendszerünkre
else if(isnull(params) || sscanf(params, \"ud\", mp, skinid)) SendClientMessage(playerid, -1, \"Használat: /setskin \");
else if(mp== INVALID_PLAYER_ID) SendClientMessage(playerid, -1, \"A játékos nincs csatlalkozva!\");
else if(!(0 <= skinid <= 299)) SendClientMessage(playerid, -1, \"A SkinID-nek 0 és 299 között kell lennie!\");
else
{
SetPlayerSkin(mp, skinid); // És mivel múlt idõben kerülnek a szövegek megjelenítésre akkor a kódban is legyen elõbb az egész skin változtatás :D
new
   str[128];
if(playerid != mp) // Ha a parancs használója saját magának állítja vele a skin-t akkor ne írja ki neki ezt az üzenetet.
{
   GetPlayerName(playerid, str, MAX_PLAYER_NAME);
   format(str, sizeof str, \"Admin:%s beállította a skined(SkinID:%d)\", str, skinid);
   SendClientMessage(mp, -1, str);
}
GetPlayerName(mp, str, MAX_PLAYER_NAME);
format(str, sizeof str, \"Beállítottad %s skinét(SkinID:%d)\", str, skinid);
SendClientMessage(playerid, -1, str);
}
return 1;
}

 
Ui.:
Ha van kérdés nyugodtan tedd fel, szívesen válaszolok hogy mit miért úgy írtam a példa parancsban. ;)
« Utoljára szerkesztve: 2013. november 19. - 16:12:43 írta ɐʞzssǝlosz »

Nem elérhető Flash

  • 5726
  • (っ◕‿◕)っ
    • Profil megtekintése
Alap sscanf dolgok
« Válasz #10 Dátum: 2013. november 19. - 13:14:42 »
+1 Show voters
Na tessék:
 
CMD:setskin(playerid, params[]) { // maga a parancs
if(!IsPlayerAdmin(playerid)) return SendClientMessage(playerid, -1, \"Nem vagy bejelenetkezve az RCON admin!\"); // Ha nincs RCON admin módban az illetõ
new mp, skinid, str[512], n1[MAX_PLAYER_NAME], n2[MAX_PLAYER_NAME]; // változók
if(sscanf(params, \"ui\", mp, skinid)) return SendClientMessage(playerid, -1, \"Használat: /setskin [playerid/név] [skinID]\");
if(!IsPlayerConnected(mp)) return SendClientMessage(playerid, -1, \"A játékos nem aktív!\");// ha a játékos nem tartózkodik a szerveren
if(!(-1 < skinid < 301)) return SendClientMessage(playerid, -1, \"Hibás SkinID: 0 - 300\"); // ha hibás szmot ír be skinid-ként
if(mp == playerid) { // Ha magadnak állítod be a skined
SetPlayerSkin(playerid, skinid);//beállítja a megadott skin-t
SendClientMessage(playerid, -1, \"Sikeresen beállítva a saját skined!\"); // elküldi az üzenetet - -1=fehér
return 1;//megállítja a parancsot
}
GetPlayerName(playerid, n1, sizeof(n1)); // Admin neve
GetPlayerName(mp, n2, sizeof(n2));//akin alkalmazod a skinmódosítást neve :o
SetPlayerSkin(mp, skinid);//beállítja a megadott skin-t
format(str, sizeof(str), \"Adminisztrátor, %s beállította a karakteredet %i-ra/re.\", n1, n2, skinid);
SendClientMessageToAll(-1, str); // elküldi mindenkinek az üzenetet ha nem magadnak állítottál skin-t
return 1;
}
« Utoljára szerkesztve: 2013. november 19. - 13:16:48 írta Flash »

Nem elérhető DrAkE

  • 2078
    • Profil megtekintése
Alap sscanf dolgok
« Válasz #11 Dátum: 2013. november 19. - 14:26:59 »
+1 Show voters

 

 

if(sscanf(params,\"id\",mp,skinid)) return SendClientMessage(playerid,-1,\"Használat: /setskin \");
{

 
Ez már az oszt igen!
 
[/quote]
?hm?
 
[/quote]
Akkor ahogy látom nem veszed észre, de paraszt módon elmagyarázom: általában ifhez szoktunk kapcsoszárójelet rakni, és nem utasítás lezárása után...

Alap sscanf dolgok
« Válasz #12 Dátum: 2013. november 19. - 17:00:12 »
0 Show voters
@Flash
Ez:



Na tessék:
 
CMD:setskin(playerid, params[]) { // maga a parancs
if(!IsPlayerAdmin(playerid)) return SendClientMessage(playerid, -1, \"Nem vagy bejelenetkezve az RCON admin!\"); // Ha nincs RCON admin módban az illetõ
new mp, skinid, str[512], n1[MAX_PLAYER_NAME], n2[MAX_PLAYER_NAME]; // változók
if(sscanf(params, \"ui\", mp, skinid)) return SendClientMessage(playerid, -1, \"Használat: /setskin [playerid/név] [skinID]\");
if(!IsPlayerConnected(mp)) return SendClientMessage(playerid, -1, \"A játékos nem aktív!\");// ha a játékos nem tartózkodik a szerveren
if(!(-1 < skinid < 301)) return SendClientMessage(playerid, -1, \"Hibás SkinID: 0 - 300\"); // ha hibás szmot ír be skinid-ként
if(mp == playerid) { // Ha magadnak állítod be a skined
SetPlayerSkin(playerid, skinid);//beállítja a megadott skin-t
SendClientMessage(playerid, -1, \"Sikeresen beállítva a saját skined!\"); // elküldi az üzenetet - -1=fehér
return 1;//megállítja a parancsot
}
GetPlayerName(playerid, n1, sizeof(n1)); // Admin neve
GetPlayerName(mp, n2, sizeof(n2));//akin alkalmazod a skinmódosítást neve :o
SetPlayerSkin(mp, skinid);//beállítja a megadott skin-t
format(str, sizeof(str), \"Adminisztrátor, %s beállította a karakteredet %i-ra/re.\", n1, n2, skinid);
SendClientMessageToAll(-1, str); // elküldi mindenkinek az üzenetet ha nem magadnak állítottál skin-t
return 1;
}

 

[/quote]
 
mitõl jobb ennél:



 
CMD:setskin2(playerid,params[])
{
new
mp,
skinid;
if(!IsPlayerAdmin(playerid)) SendClientMessage(playerid, -1, \"Nem vagy bejelenetkezve az RCON adminba!\");//ezt átlehet írni a saját amdinrendszerünkre
else if(isnull(params) || sscanf(params, \"ud\", mp, skinid)) SendClientMessage(playerid, -1, \"Használat: /setskin \");
else if(mp== INVALID_PLAYER_ID) SendClientMessage(playerid, -1, \"A játékos nincs csatlalkozva!\");
else if(!(0 <= skinid <= 299)) SendClientMessage(playerid, -1, \"A SkinID-nek 0 és 299 között kell lennie!\");
else
{
SetPlayerSkin(mp, skinid); // És mivel múlt idõben kerülnek a szövegek megjelenítésre akkor a kódban is legyen elõbb az egész skin változtatás :D
new
   str[128];
if(playerid != mp) // Ha a parancs használója saját magának állítja vele a skin-t akkor ne írja ki neki ezt az üzenetet.
{
   GetPlayerName(playerid, str, MAX_PLAYER_NAME);
   format(str, sizeof str, \"Admin:%s beállította a skined(SkinID:%d)\", str, skinid);
   SendClientMessage(mp, -1, str);
}
GetPlayerName(mp, str, MAX_PLAYER_NAME);
format(str, sizeof str, \"Beállítottad %s skinét(SkinID:%d)\", str, skinid);
SendClientMessage(playerid, -1, str);
}
return 1;
}

 

[/quote]
?

Nem elérhető Rexii

  • 471
    • Profil megtekintése
Alap sscanf dolgok
« Válasz #13 Dátum: 2013. november 19. - 17:36:14 »
0 Show voters

Hasonlóképp mint a format funkció használataként.
Az i és d ugyanaz (integer ill decimal) rövidítése egész számot jelöl.
Az f (float) nem egész szám más nyelven lebegõ pontos szám (3.45).
Az s karakterláncokat jelöl.
De mindenhez van leírás a sscanf topikban.
http://forum.sa-mp.com/showpost.php?p=520110&postcount=1
Az u egy különleges jelölés olyan szempontból hogy játékos név(name) illetve azonosító szám (playerid) beírásra is mûködik.
 
[/quote]
Köszi

Nem elérhető Flash

  • 5726
  • (っ◕‿◕)っ
    • Profil megtekintése
Alap sscanf dolgok
« Válasz #14 Dátum: 2013. november 25. - 15:09:08 »
0 Show voters

@Flash
Ez:



Na tessék:
 
CMD:setskin(playerid, params[]) { // maga a parancs
if(!IsPlayerAdmin(playerid)) return SendClientMessage(playerid, -1, \"Nem vagy bejelenetkezve az RCON admin!\"); // Ha nincs RCON admin módban az illetõ
new mp, skinid, str[512], n1[MAX_PLAYER_NAME], n2[MAX_PLAYER_NAME]; // változók
if(sscanf(params, \"ui\", mp, skinid)) return SendClientMessage(playerid, -1, \"Használat: /setskin [playerid/név] [skinID]\");
if(!IsPlayerConnected(mp)) return SendClientMessage(playerid, -1, \"A játékos nem aktív!\");// ha a játékos nem tartózkodik a szerveren
if(!(-1 < skinid < 301)) return SendClientMessage(playerid, -1, \"Hibás SkinID: 0 - 300\"); // ha hibás szmot ír be skinid-ként
if(mp == playerid) { // Ha magadnak állítod be a skined
SetPlayerSkin(playerid, skinid);//beállítja a megadott skin-t
SendClientMessage(playerid, -1, \"Sikeresen beállítva a saját skined!\"); // elküldi az üzenetet - -1=fehér
return 1;//megállítja a parancsot
}
GetPlayerName(playerid, n1, sizeof(n1)); // Admin neve
GetPlayerName(mp, n2, sizeof(n2));//akin alkalmazod a skinmódosítást neve :o
SetPlayerSkin(mp, skinid);//beállítja a megadott skin-t
format(str, sizeof(str), \"Adminisztrátor, %s beállította a karakteredet %i-ra/re.\", n1, n2, skinid);
SendClientMessageToAll(-1, str); // elküldi mindenkinek az üzenetet ha nem magadnak állítottál skin-t
return 1;
}

 

[/quote]
 
mitõl jobb ennél:



 
CMD:setskin2(playerid,params[])
{
new
mp,
skinid;
if(!IsPlayerAdmin(playerid)) SendClientMessage(playerid, -1, \"Nem vagy bejelenetkezve az RCON adminba!\");//ezt átlehet írni a saját amdinrendszerünkre
else if(isnull(params) || sscanf(params, \"ud\", mp, skinid)) SendClientMessage(playerid, -1, \"Használat: /setskin \");
else if(mp== INVALID_PLAYER_ID) SendClientMessage(playerid, -1, \"A játékos nincs csatlalkozva!\");
else if(!(0 <= skinid <= 299)) SendClientMessage(playerid, -1, \"A SkinID-nek 0 és 299 között kell lennie!\");
else
{
SetPlayerSkin(mp, skinid); // És mivel múlt idõben kerülnek a szövegek megjelenítésre akkor a kódban is legyen elõbb az egész skin változtatás :D
new
   str[128];
if(playerid != mp) // Ha a parancs használója saját magának állítja vele a skin-t akkor ne írja ki neki ezt az üzenetet.
{
   GetPlayerName(playerid, str, MAX_PLAYER_NAME);
   format(str, sizeof str, \"Admin:%s beállította a skined(SkinID:%d)\", str, skinid);
   SendClientMessage(mp, -1, str);
}
GetPlayerName(mp, str, MAX_PLAYER_NAME);
format(str, sizeof str, \"Beállítottad %s skinét(SkinID:%d)\", str, skinid);
SendClientMessage(playerid, -1, str);
}
return 1;
}

 

[/quote]
?
 
[/quote]
Áttekinthetõbb szerintem, azért, amúgy semmivel sem jobb, ugyan azt tudja..

 

SimplePortal 2.3.7 © 2008-2024, SimplePortal