[Include] >>> San Andreas Telecom - Create a phone system easily <<<
#1

San Andreas Telecom

>>> S.T.C <<<

>> v0.1 - Alpha <<



Here is a tutorial: https://sampforum.blast.hk/showthread.php?tid=494995


Please read it fully - don't scroll down quickly! It will take 5 minutes to read the full topic!
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^

Introduction
This a source which provides in-built functions for scripting a phone system. Using this will be a good idea for an average scriptwriter, or lower, or the one who demands this. This also provides a function for creating towers. There are two types of towers; one is a commercial tower, and other is a non commercial tower. Since its the very first version of this source, the towers don't have an in-built system - so, you will have to code systems for commercial towers yourself. But this source is also providing a function which gives the player recharge, and a function which gets the current balance of the player. You can use these functions for commercial towers as a medium for calling. Then, the total money taken by the player can be saved in a file. When the owner of the tower, enters the game, he can be given the money which he earned by his charges set for calling. This can also be called as "business". This also provides an in-built code for OnPlayerText; means that you wont need to code OnPlayerText for this calling system. If you want to code it in an other way, then you can remove the hooked function. Since this version is the very first version (Alpha release), it might be volatile to your server in one way; creating towers without a name - I'll explain this later, for now, keep reading... And I've tested this alone.

Functions
This source provides greater than 16 functions. Some are untested.

pawn Код:
native CreateCommercialTower(id,Float:posX,Float:posY,Float:posZ,Float:Range,TName[],Float:rotX=0.0,Float:rotY=0.0,Float:rotZ=0.0);
Creates a "commercial" tower. The only thing which makes it commercial is that it tells the server that "I am a commercial tower". It also gets created with a 3D text label by "TName[]", so if you set the label to "Zayan's commercial tower - In range!", it will appear as you expected. Its recommended that you set the "Float:Range" greater than 30. Note that the float set for "Float:Range" will be the same for the 3D text.

[!] Alert: If "TName[]" is empty, it will crash the server. This is caused because "TName[]" creates an empty 3D text on the coordinates of the tower (subtracted by 5.0).

[!] Warning: Keeping the ID Less than 1 or greater than 100 will cause the server to automatically destroy the tower, and you wont be able to see the tower in-game because its destroyed.

[!] Note: If you create the tower at a coordinates normally captured by /save, the tower might appear not tall because half of the tower is down the real ground. In easy words, its half might be underground. To fix this is simple, you will have to add little more numbers to "Float:posZ", like "Float:posZ + 3.0". Note that when the tower is created, 5.0 is automatically subtracted to the given Z coordinates.

Example:
pawn Код:
public OnGameModeInit()
{
    CreateCommercialTower(1,1877.7667,-2545.0544,13.5469 + 5, 30.0, "TEST C");
    return 1;
}
---------------------------------------------------------------------------

pawn Код:
native CreateNonCommercialTower(id,Float:posX,Float:posY,Float:posZ,Float:Range, TName[],Float:rotX=0.0,Float:rotY=0.0,Float:rotZ=0.0);
Creates a "Non Commercial" tower. The only thing which makes it non commercial is that it tells the server that "I am not a commercial tower". It also gets created with a 3D text label by "TName[]", so if you set the label to "Zayan's commercial tower - In range!", it will appear as you expected. Its recommended that you set the "Float:Range" greater than 30. Note that the float set for "Float:Range" will be the same for the 3D text.

[!] Alert: If "TName[]" is empty, it will crash the server. This is caused because "TName[]" creates an empty 3D text on the coordinates of the tower (subtracted by 5.0).

[!] Warning: Keeping the ID Less than 1 or greater than 100 will cause the server to automatically destroy the tower, and you wont be able to see the tower in-game because its destroyed.

[!] Note: If you create the tower at a coordinates normally captured by /save, the tower might appear not tall because half of the tower is below the real ground. In easy words, its half might be underground. To fix this is simple, you will have to add little more numbers to "Float:posZ", like "Float:posZ + 3.0". Note that when the tower is created, 5.0 is automatically subtracted to the given Z coordinates.

Example:
pawn Код:
public OnGameModeInit()
{
    CreateNonCommercialTower(1,1877.7667,-2545.0544,13.5469 + 5, 30.0, "TEST C");
    return 1;
}
---------------------------------------------------------------------------

pawn Код:
native DestroyTower(id);
Destroys the tower. If the ID of the tower is valid. And wipes out the whole data set for the tower.

Example:
pawn Код:
DestroyTower(1);
---------------------------------------------------------------------------

pawn Код:
native GetTotalTowers();
Gets the total number of towers currently present in the server. Note that DestroyTower() can effect this.

Example:
pawn Код:
main()
{
    printf("Total number towers active: %i", GetTotalTowers());
}
---------------------------------------------------------------------------

pawn Код:
native IsPlayerInRangeOfTower(playerid, id);
Checks if the player is in range of a tower. Note that this is called if the player is near the a specific tower. To check if the player is near a specific tower, you'll have to set the tower's ID. If the tower's ID matches with the player's nearest tower ID, its called then.

Example:
pawn Код:
if(IsPlayerInRangeOfTower(playerid, 1))
{
    SendClientMessage(playerid, -1, "You're near a tower - its ID is 1");
    return 1;
}
---------------------------------------------------------------------------

pawn Код:
native IsPlayerInRangeOfAnyTower(playerid);
Checks if the player is in range of ANY tower.

Example:
pawn Код:
if(IsPlayerInRangeOfAnyTower(playerid))
{
    SendClientMessage(playerid, -1, "You are in range of a tower!");
}
else SendClientMessage(playerid, -1, "You are not near a tower...");
---------------------------------------------------------------------------

pawn Код:
native CallPlayerForPlayer(playerid, toplayerid);
Just like real life. Connects the player to his target. There is also a in-built checks - but if you want to use that in-built checks, you can define:

pawn Код:
#define ASI_STC_INBUILT
If defined, you can this function like:
pawn Код:
SendClientMessage(playerid, -1, "Connected! Say Hello!");
CallPlayerForPlayer(playerid, target);
Instead of doing this:
pawn Код:
if(IsPlayerConnected(target))
{
    if(!IsPlayerCalling(target))
    {
        SendClientMessage(playerid, -1, "Connected! Say Hello!");
        CallPlayerForPlayer(playerid, target);
    }
    else SendClientMessage(playerid, -1, "Sorry, the player is busy.");
}
else SendClientMessage(playerid, -1, "Sorry, the player isn't avalible.");
---------------------------------------------------------------------------

pawn Код:
native DisconnectPlayer(playerid);
Disconnects the player if the player is in a conversation (calling).

Example:
pawn Код:
DisconnectPlayer(playerid); // Disconnects the player
DisconnectPlayer(target);    // Disconnects his target
---------------------------------------------------------------------------

pawn Код:
native IsPlayerCalling(playerid);
Checks if the player is calling.

Example:
pawn Код:
if(IsPlayerCalling(playerid)) SendClientMessage(playerid, -1, "You are calling someone..");
---------------------------------------------------------------------------

pawn Код:
native GivePlayerRecharge(playerid, money);
Recharges the player's balance. It's not similar as GivePlayerMoney - it's actually a script side money.

Example:
pawn Код:
GivePlayerRecharge(playerid, 10);
---------------------------------------------------------------------------

pawn Код:
native GetPlayerRecharge(playerid);
Gets the player's balance.

Example:
pawn Код:
new str[128];
format(str, 128, "Your balance is: $%d", GetPlayerRecharge(playerid));
SendClientMessage(playerid, -1, str);
---------------------------------------------------------------------------

pawn Код:
native IsTowerCommercial(towerid);
Checks if the tower is commercial, if not, returns 0.

Example:
pawn Код:
if(IsTowerCommercial(1))
{
    SendClientMessage(playerid, -1, "This tower is commercial");
}
else SendClientMessage(playerid, -1, "This tower is non commercial");
---------------------------------------------------------------------------

pawn Код:
native RingPhoneForPlayer(playerid, iscaller);
This is untested. This is just used to send a message. If the player is the caller, "iscaller" must be 0. If not, must be 1.

[!] Warning: This function wont work if "ASI_STC_UNTESTED" is not defined.

Alpha Testers & Beta Testers
Alpha Testers:
  • ACI
Developers
  • ACI
Bugs
- WE ARE STILL INVESTIGATING - WILL BE UPDATED -

Source
pawn Код:
/*
    AUTHOR  :   Zayan Imran     >>> 0bzayan@gmail.com <<<
    SOURCE  :   sa_telecom.inc
    VERSION :   v0.1 - Alpha
    PURPOSE :   Serving the world,
                giving users comfort with this,
                Expanding ASI (Pre-Alpha version v0.1),
                Useful for all server owners who wants it,
                Useful as a server addon,
                Serving functions for easily scripting a phone system.
    LICENSE :
        <> LEGAL USAGE:
            The usage of this source can only be legal by agreeing with the
            "USER/USAGE AGGREMENT".
                <> USER/USAGE AGGREMENT:
                    * If you are using/including this source in a public downloa
                    -d then the credits must go the author.
                    * Copying this source and claming this as your own written s
                    -ource is not legal.
            Note: Using this source in anyway means you agree with the
                  "USER/USAGE AGGREMENT".
                <>
        <>
    LOG:
        <v0.1> 09/02/2014 - Developed the first alpha version.

    COMMING FEATURES IN NEXT VERSIONS:
        <> Web browsing feature will be added in a unknown update. And a WDK wil
           -l released seperately for ASI.  (MAYBE)
           WDK can be called as: Website development kit,
                                 Webpage development kit,
                                 W.W.W   development kit.
        <> The next version maybe improved by making it faster via using bits.
        <> GetTowerInfo(..) will be added in an unknown version.
        <> DisconnectPlayerAndTarget(..) will be added n an unknown version.
        <> OnPlayerCall(..) will be added n an unknown version.
        <> A PDT, phone development textdraws, might be added for GUI interface
           between the player and the phone. For example: creating a 2D tablet
           on the screen.
        <> More upcomming features regarding this can be also seen through the f
           -orum. It's because the topic may get constantly updated.

    REGISTERED FUNCTIONS:
native CreateCommercialTower(id,Float:posX,Float:posY,Float:posZ,Float:Range, TName[],Float:rotX=0.0,Float:rotY=0.0,Float:rotZ=0.0);
native CreateNonCommercialTower(id,Float:posX,Float:posY,Float:posZ,Float:Range, TName[],Float:rotX=0.0,Float:rotY=0.0,Float:rotZ=0.0);
native DestroyTower(id);
native GetTotalTowers();
native IsPlayerInRangeOfTower(playerid, id);
native CallPlayerForPlayer(playerid, toplayerid);
native DisconnectPlayer(playerid);
native IsPlayerCalling(playerid);
native GivePlayerRecharge(playerid, money);
native GetPlayerRecharge(playerid);
native IsTowerCommercial(towerid);
native IsPlayerInRangeOfAnyTower(playerid);
*/

#if defined _sa_telecom_included
    #endinput
#endif
#define _sa_telecom_included

#define SA_TELE_COLOR -1
#define _TOWERS_@d 101 //Which means '100' in this state when its used in.
#define MAX_TOWERS _TOWERS_@d
#define STC(%0, %1, %2); SendClientMessage(%0, %1, %2);

forward ASI_OnPlayerText(playerid, text[]);
forward ASI_OnPlayerDisconnect(playerid, reason);
forward OnPlayerCallPlayer(playerid, target);

enum _TOWER_DAT_@f@f@f@f@f@f@i@d@d //Problem?
{
    Float:X,
    Float:Y,
    Float:Z,
    Float:rX,
    Float:rY,
    Float:rZ,
    Float:RG,
    INTD,
    ISC,
    ADDC,
    Text3D:tName,
    _ID_@d
}
new ASI_TOWER_@a_@a[_TOWERS_@d][_TOWER_DAT_@f@f@f@f@f@f@i@d@d],
    gPTD[MAX_PLAYERS],
    gPCT[MAX_PLAYERS],
    gIPC[MAX_PLAYERS],
    gPTI[MAX_PLAYERS],
    gPRC[MAX_PLAYERS],
    Cell_@i;

stock CreateCommercialTower(id,Float:posX,Float:posY,Float:posZ,Float:Range, TName[],Float:rotX=0.0,Float:rotY=0.0,Float:rotZ=0.0)
{
    if(id < 0) return printf("ASI fatal error (1): Attempted to create a tower with given a negative number ID, the ID for the tower was set to %i", id);
    if(id > _TOWERS_@d - 1) return printf("Created a tower with ID greater than %d, the ID for the tower was set to %d", _TOWERS_@d - 1, id);
    if(TName[0] == '\0' || TName[0] == ' ') return printf("ASI fatal error (7): Attempted to create a tower without a name! This can crash the server! The ID of the tower was set to %d", id);
    if(!ASI_TOWER_@a_@a[id][INTD] && ASI_TOWER_@a_@a[id][ADDC] == 0)
    {
        Cell_@i++;
        ASI_TOWER_@a_@a[id][INTD]  = CreateObject(3763, posX,posY,posZ,rotX,rotY,rotZ, 500.0);
        ASI_TOWER_@a_@a[id][X]     = posX;
        ASI_TOWER_@a_@a[id][Y]     = posY;
        ASI_TOWER_@a_@a[id][Z]     = posZ;
        ASI_TOWER_@a_@a[id][rX]    = rotX;
        ASI_TOWER_@a_@a[id][rY]    = rotY;
        ASI_TOWER_@a_@a[id][rZ]    = rotZ;
        ASI_TOWER_@a_@a[id][RG]    = Range;
        ASI_TOWER_@a_@a[id][_ID_@d]    = id;
        ASI_TOWER_@a_@a[id][ISC]   = 1;
        ASI_TOWER_@a_@a[id][ADDC]  = 1;
        ASI_TOWER_@a_@a[id][tName] = Create3DTextLabel(TName, 0x008080FF, posX, posY, posZ - 5.0, Range, 0, 0);
        printf("ASI debug: Created a tower with ID: %d", id);
    }
    else printf("ASI debug: Tower ID %d has not been created because a tower with ID %d already exists");
    return 0;
}

stock CreateNonCommercialTower(id,Float:posX,Float:posY,Float:posZ,Float:Range, TName[],Float:rotX=0.0,Float:rotY=0.0,Float:rotZ=0.0)
{
    if(id < 0) return printf("ASI fatal error (1): Attempted to create a tower with given a negative number ID, the ID for the tower was set to %i", id);
    if(id > _TOWERS_@d - 1) return printf("ASI fatal error (2): Created a tower with ID greater than %d, the ID for the tower was set to %d", _TOWERS_@d - 1, id);
    if(!ASI_TOWER_@a_@a[id][INTD] && ASI_TOWER_@a_@a[id][ADDC] == 0)
    {
        Cell_@i++;
        ASI_TOWER_@a_@a[id][INTD]  = CreateObject(3763, posX,posY,posZ,rotX,rotY,rotZ, 500.0);
        ASI_TOWER_@a_@a[id][X]     = posX;
        ASI_TOWER_@a_@a[id][Y]     = posY;
        ASI_TOWER_@a_@a[id][Z]     = posZ;
        ASI_TOWER_@a_@a[id][rX]    = rotX;
        ASI_TOWER_@a_@a[id][rY]    = rotY;
        ASI_TOWER_@a_@a[id][rZ]    = rotZ;
        ASI_TOWER_@a_@a[id][RG]    = Range;
        ASI_TOWER_@a_@a[id][_ID_@d]= id;
        ASI_TOWER_@a_@a[id][ISC]   = 0;
        ASI_TOWER_@a_@a[id][ADDC]  = 1;
        ASI_TOWER_@a_@a[id][tName] = Create3DTextLabel(TName, 0x008080FF, posX, posY, posZ - 5, Range, 0, 0);
        printf("ASI debug: Created a tower with ID: %d", id);
    }
    else printf("ASI debug: Tower ID %d has not been created because a tower with ID %d already exists", id);
    return 0;
}

stock DestroyTower(id)
{
    if(id < 0) return printf("ASI fatal error (3): Attempted to destroy a tower with given a negative number ID, the ID for the tower was set to %i", id);
    if(id > _TOWERS_@d - 1) return printf("ASI fatal error (4): Attempted to destroy a tower with ID greater than %d, the ID for the tower was set to %d", _TOWERS_@d, id);
    if(ASI_TOWER_@a_@a[id][ISC] && ASI_TOWER_@a_@a[id][ADDC] == 1)
    {
        Cell_@i--;
        DestroyObject(ASI_TOWER_@a_@a[id][INTD]);
        ASI_TOWER_@a_@a[id][X]     = 0.0;
        ASI_TOWER_@a_@a[id][Y]     = 0.0;
        ASI_TOWER_@a_@a[id][Z]     = 0.0;
        ASI_TOWER_@a_@a[id][rX]    = 0.0;
        ASI_TOWER_@a_@a[id][rY]    = 0.0;
        ASI_TOWER_@a_@a[id][rZ]    = 0.0;
        ASI_TOWER_@a_@a[id][_ID_@d]= id;
        ASI_TOWER_@a_@a[id][ISC]   = -1;
        ASI_TOWER_@a_@a[id][ADDC]  = 0;
        Delete3DTextLabel(ASI_TOWER_@a_@a[id][tName]);
        printf("ASI debug: Destroying tower ID %d - Destroying the object, destroying the information set for the tower", id);
    }
    else printf("ASI fatal error (5): Destroying ID %d failed because it isn't created", id);
    return 0;
}

stock GetTotalTowers() return Cell_@i;

stock IsPlayerInRangeOfTower(playerid, id)
{
    if(IsPlayerInRangeOfPoint(playerid, ASI_TOWER_@a_@a[id][RG],
                                        ASI_TOWER_@a_@a[id][X],
                                        ASI_TOWER_@a_@a[id][Y],
                                        ASI_TOWER_@a_@a[id][Z]))
    {
        return 1;
    }
    return 0;
}

stock CallPlayerForPlayer(playerid, toplayerid)
{
    #if defined ASI_STC_INBUILT
    //OR USE: if((gIPC[tplayerid] == 1)) return SendClientMessage(playerid, SA_TELE_COLOR, "[SA TELECOM][SYSTEM ERROR]: The player you're trying to call is busy, please try later!");
    if(!IsPlayerConnected(toplayerid))
        return STC(playerid, _SA_TELE_COLOR, "[SA TELECOM][SYSTEM ERROR]: The player you're trying to call, is not avalible. Please try after sometime. You have been disconnected."), 1;
    if(IsPlayerCalling(toplayerid))
        return SendClientMessage(playerid, SA_TELE_COLOR, "[SA TELECOM][SYSTEM ERROR]: The player you're trying to call is busy, please try later!"),
        DisconnectPlayer(playerid), 1;
    #endif
    if(playerid == toplayerid)
        return SendClientMessage(playerid, SA_TELE_COLOR, "[SA TELECOM][SYSTEM ERROR]: The player you are trying to call, is busy. Please try later! You've been disconnected."), DisconnectPlayer(playerid), 0;
    gIPC[playerid]   = 1;
    gIPC[toplayerid] = 1;
    gPTI[playerid]   = (toplayerid);
    printf("ASI debug: Connecting player %d to %d", playerid, toplayerid);
    return 1;
}

stock DisconnectPlayer(playerid)
{
    if(gIPC[playerid] == 1)
    {
        gIPC[playerid] = 0;
        printf("ASI debug: Disconnecting %d's phone", playerid);
        return 1;
    }
    else return printf("ASI error (6): %d wasn't disconnected because they arent in connected to a tower", playerid), 0;
}

stock IsPlayerCalling(playerid)
{
    if(gIPC[playerid] == 1) return printf("ASI debug: IsPlayerCalling was called <playerid = %d>", playerid), 1;
    else return 0;
}

stock GivePlayerRecharge(playerid, money)
{
    gPRC[playerid] = money;
    printf("ASI debug: Recharging the phone of %d with money $%i", playerid, money);
    return 1;
}

stock GetPlayerRecharge(playerid)
{
    printf("ASI debug: GetPlayerRecharge was called  <playerid = %d> <Returned: %i>", playerid, gPRC[playerid]);
    return gPRC[playerid];
}

stock IsTowerCommercial(towerid)
{
    if(ASI_TOWER_@a_@a[towerid][ISC] == 1) return printf("ASI debug: IsTowerCommercial was called  <towerid = %i>  <returned: 1>", towerid, towerid), 1;
    else return 0;
}

stock IsPlayerInRangeOfAnyTower(playerid)
{
    for(new i = 0; i < _TOWERS_@d; i++)
    {
        if(IsPlayerInRangeOfTower(playerid, i))
        {
            printf("ASI debug: IsPlayerInRangeOfAnyTower was called <playerid = %d>", playerid);
            return 1;

        }
    }
    return 0;
}

#if defined ASI_STC_UNTESTED
/*
native RingPhoneForPlayer(playerid, iscaller);
*/

stock RingPhoneForPlayer(playerid, iscaller)
{
    switch(iscaller)
    {
        case  0: SendClientMessage(playerid, -1, "[SA TELECOM]: Please wait until he/she picks up the phone");
        case  1: SendClientMessage(playerid, -1, "[SA TELECOM]: Your phone is being trolled. Pick up to answer the troller.");
        default: printf("ASI error (8): Unknown 'iscaller' value. The value was set to %i", iscaller);
    }
    return 1;
}
#endif

public OnPlayerText(playerid, text[])
{
    if(gIPC[playerid] == 1)
    {
        if(!IsPlayerConnected(gPTI[playerid]))
        {
            return SendClientMessage(playerid, SA_TELE_COLOR, "[SA TELECOM][SYSTEM ERROR]: The player you're trying to call, is not avalible. Please try after sometime. You have been disconnected."),
            DisconnectPlayer(playerid), 0;
        }
        new cstr[128], ocs[128], sn[37], rsn[37];
        GetPlayerName(playerid, sn, 37);
        GetPlayerName(gPTI[playerid], rsn, 37);
        format(ocs, sizeof(ocs), "[SA TELECOM][TO %s]: %s", rsn, text);
        SendClientMessage(playerid, SA_TELE_COLOR, ocs);
        format(cstr, sizeof(cstr), "[SA TELECOM][FROM %s]: %s", sn, text);
        SendClientMessage(gPTI[playerid], SA_TELE_COLOR, cstr);
        return 0;
    }
    else return 1;
}

public OnPlayerDisconnect(playerid, reason)
{
    #define ASIp playerid
    gPTD[ASIp] = 0;
    gPCT[ASIp] = 0;
    gIPC[ASIp] = 0;
    gPTI[ASIp] = 0;
    return 1;
}

#if defined _ALS_OnPlayerText
  #undef OnPlayerText
#else
  #define _ALS_OnPlayerText
#endif
#define OnPlayerText ASI_OnPlayerText
#if defined _ALS_OnPlayerDisconnect
  #undef OnPlayerDisconnect
#else
  #define _ALS_OnPlayerDisconnect
#endif
#define OnPlayerDisconnect ASI_OnPlayerDisconnect
#undef ASIp
Development LOG
Код:
<v0.1> 09/02/2014 - Developed the first alpha version.
Suggestions
* Web browsing feature will be added in a unknown update. And a WDK will released seperately for ASI. (MAYBE)
* WDK can be called as: Website development kit, Webpage development kit, W.W.W development kit.
* The next version maybe improved by making it faster via using bits.
* GetTowerInfo(..) will be added in an unknown version.
* DisconnectPlayerAndTarget(..) will be added n an unknown version.
* OnPlayerCall(..) will be added n an unknown version.
* A PDT, phone development textdraws, might be added for GUI interface between the player and the phone. For example: creating a 2D tablet on the screen. (MAYBE)
Reply
#2

This is really useful and although I have yet to use it. The features of it look awesome. Can you elaborate on the WDK seems interesting?
Reply
#3

Thanks for your support. There is a lot to planfor the future versions.

I will be off to sleep in some time, anyone can leave a reply if he wants.
Reply
#4

It looks cool, good job
Reply
#5

Quote:
Originally Posted by ACI
Посмотреть сообщение
Thanks for your support. There is a lot to planfor the future versions.

I will be off to sleep in some time, anyone can leave a reply if he wants.
So could you elaborate on the WDK, seems really interesting.
Reply
#6

I have goto admit i would have never made a system in anyway like this.. but thank you for putting all the work in for something that someone would like to use if they don't have the time to do it themselves, me on the other hand.... I'll be doing something for MySQL and around my script like this. (Thanks for the idea too :P)
Reply
#7

good job mate!
Reply
#8

Thanks everyone.

@ Newrth - I will be today looking on WDK
Reply
#9

nice job ACI
Reply
#10

Thanks
Reply
#11

A quick short update - fixed the problems caused by registering natives.

A short tutorial has been added: https://sampforum.blast.hk/showthread.php?tid=494995
Reply
#12

useful for RP +rep
Reply
#13

Thanks for your support.
Reply


Forum Jump:


Users browsing this thread: 3 Guest(s)