[Tutorial] Things to do with OnPlayerText
#1

Things to do with OnPlayerText


First of all, as you may know, the callback OnPlayerText gets called every single time a player types something in the server chat.
There are many uses for it which could help in personalizing your server or even enhancing the way the gamemode itself is played, so I am going to show you some of the more basic uses.
NOTE: This tutorial assumes that you have at least a basic knowledge of the PAWN language and of the default SA-MP functions.
1. Introduction
OnPlayerText itself is easy to understand.
It has two parameters, 'playerid' and 'text[]'.
  • playerid is an integer (i.e a whole number) and it represents the ID of the player who has typed the message.
  • text[] is a string and it represents the text that the player has typed into the chat.
pawn Код:
public OnPlayerText(playerid, text[])
{
    return 1;
}
  • Returning 1 sends the default message, like: "Your name: Message"
  • Returning 0 doesn't send the default message, allowing you to... improvise.
By exploiting this function, we can do various things.

2. Uses
  • Changing the text that was supposed to show up
The messages you send by the chat usually show up in SA-MP as "Your name: Message". But what if you want to add the ID, and make it "Your name: [ID] Message"?

First of all we change 'return 1;' to 'return 0;'. If we do so, the original message will not be sent.
pawn Код:
public OnPlayerText(playerid, text[])
{
    return 0;
}
Then, we define a new string of size 128. Call it whatever you want, but in this tutorial I will call it 'msg'.
pawn Код:
public OnPlayerText(playerid, text[])
{
    new msg[128]; // The string. We do not need to have it larger than 128, because a message can't be larger than that.
    return 0;
}
Now, we'll have to format the string. As we wish to insert the player's ID (an integer) in the text, we will use the format function, to turn the string into '[%d] %s' as so:
%d means integer, and we will put the player ID in its place.
%s means string, and we will put the text in its place.
pawn Код:
public OnPlayerText(playerid, text[])
{
    new msg[128]; // The string. We do not need to have it larger than 128, because a message can't be larger than that.
    format(msg, sizeof(msg), "[%d] %s", playerid, text); // The formatted message. Remember, %d means integer (whole number) and %s is string - they are associated with playerid, respectively text.
    return 0;
}
It may look like we're done, but we are not. The message is formatted, but it hasn't been sent yet! Therefore, if you try to chat right now, no message will come out - and I don't think that helps much, if at all, so there's one last thing to do.
Call SendPlayerMessageToAll, with senderid as playerid and with the text as 'msg', as so:
pawn Код:
public OnPlayerText(playerid, text[])
{
    new msg[128]; // The string. We do not need to have it larger than 128, because a message can't be larger than that.
    format(msg, sizeof(msg), "[%d] %s", playerid, text); // The formatted message. Remember, %d means integer (whole number) and %s is string - they are associated with playerid, respectively text.
    SendPlayerMessageToAll(playerid, msg); // SendPlayerMessageToAll will send a message from the player to everyone, like what would happen normally when a player chats, but with the message we choose.
    return 0;
}
Now, the message will look like "Your name: [ID] Message"!

You could potentially adjust this so you can see anything you want - if you have a function in your gamemode that returns something like the team name or the rank of the player as a string (i.e as a (group of) word(s), not as a number), we could use it and show it in the message.
pawn Код:
public OnPlayerText(playerid, text[])
{
    new msg[128]; // The string. We do not need to have it larger than 128, because a message can't be larger than that.
    format(msg, sizeof(msg), "[%s] %s", GetPlayerTeamName(playerid), text); // The formatted message. Remember, %s means string - the strings are associated with GetPlayerTeamName(playerid), respectively text.
    SendPlayerMessageToAll(playerid, msg); // SendPlayerMessageToAll will send a message from the player to everyone, like what would happen normally when a player chats, but with the message we choose.
    return 0;
}
(There is no function like that, and nor have we defined it. This is just an example. Say, if your team name is 'Red' then in place of the ID you will see [Red]. You could've also done this by changing the player colour, and therefore you would have no need for the such, but this is just an example.)
  • Making an admin chat
Say, you want to discuss things with your admins in private on the server, but without PMing each of them - that's why you need an admin chat! You could also make it with a command, but why not simplify it:
If the admin makes a message that starts with #, it will automatically be shown to other admins!
We will once again start from the 'default' OnPlayerText, but you can continue on the 'old' one as well.
pawn Код:
public OnPlayerText(playerid, text[])
{
    return 1;
}
First, add a check to see if the player is an admin. We will use IsPlayerAdmin, which is used to check if a player is logged in RCON, but you can change it with any other function/variable which shows the player's admin level.
pawn Код:
public OnPlayerText(playerid, text[])
{
    if(IsPlayerAdmin(playerid))
    {
         // our code will be here
    }
    return 1;
}
To the if statement we have just created, we will add "&& text[0] == '#'" to check if the first character in the text is #. You can change it to whatever other character you'd choose for admin chat.
pawn Код:
public OnPlayerText(playerid, text[])
{
    if(IsPlayerAdmin(playerid) && text[0] == '#')
    {
         // our code will be here
    }
    return 1;
}
Then, we will create a new string, with the size of 128 (like in the previous parts, name it whatever you'd like), and format it as so:
pawn Код:
public OnPlayerText(playerid, text[])
{
    if(IsPlayerAdmin(playerid) && text[0] == '#')
    {
         new msg[128];
         format(msg, sizeof(msg), "[ADMIN CHAT] %s: %s", pName, text[1]);
    }
    return 1;
}
But wait! We don't have any 'pName' variable. Create it as a string with the size of MAX_PLAYER_NAME, and use the GetPlayerName function to get the player's name. In this tutorial we assume that you know how to use the basic functions, so we won't explain the usage of GetPlayerName in detail - however, there's not much to explain at all.
pawn Код:
public OnPlayerText(playerid, text[])
{
    if(IsPlayerAdmin(playerid) && text[0] == '#')
    {
         new msg[128], pName[MAX_PLAYER_NAME];
         GetPlayerName(playerid, pName, MAX_PLAYER_NAME);
         format(msg, sizeof(msg), "[ADMIN CHAT] %s: %s", pName, text[1]);
    }
    return 1;
}
Perfect! Now we need to show it to all admins.
Add this to the end of your gamemode:
pawn Код:
stock SendMessageToAdmins(text[])
{
    for(new i = 0, i < MAX_PLAYERS, i++)
    {
        if(IsPlayerAdmin(i))
        {
            SendClientMessage(i, -1, text);
        }
    }
}
Change IsPlayerAdmin(i) with any other function or variable containing your admin level, such as PlayerInfo[i][pAdmin]. If you have multiple levels, you can do it like "if(GetPlayerAdmin(playerid) >= 1)" (assuming you have such a function).

Now, add it as so into OnPlayerText:
pawn Код:
public OnPlayerText(playerid, text[])
{
    if(IsPlayerAdmin(playerid) && text[0] == '#')
    {
         new msg[128], pName[MAX_PLAYER_NAME];
         GetPlayerName(playerid, pName, MAX_PLAYER_NAME);
         format(msg, sizeof(msg), "[ADMIN CHAT] %s: %s", pName, text[1]);
         SendMessageToAdmins(msg);
    }
    return 1;
}
You could also add the ID as in the previous example, like so:
pawn Код:
public OnPlayerText(playerid, text[])
{
    if(IsPlayerAdmin(playerid) && text[0] == '#')
    {
         new msg[128], pName[MAX_PLAYER_NAME];
         GetPlayerName(playerid, pName, MAX_PLAYER_NAME);
         format(msg, sizeof(msg), "[ADMIN CHAT] %s (ID %d): %s", pName, playerid, text[1]);
         SendMessageToAdmins(msg);
    }
    return 1;
}
And our admin chat is done!
Strfind will look in the string for a certain word.
This can be used for various things, and I will give an example.
Once again, we start with the 'base' OnPlayerText.
pawn Код:
public OnPlayerText(playerid, text[])
{
    return 1;
}
We will first add an if statement which checks for two 'words' in the text: 'how' and 'get car'.
pawn Код:
public OnPlayerText(playerid, text[])
{
    if(strfind(text, "how", true) != -1 && strfind(text, "get car", true) != -1) {
        // our code goes here
    }
    return 1;
}
Then, we return 0, so the message doesn't get sent, and we send the player this message: "To get a car, please use the /v command.".
pawn Код:
public OnPlayerText(playerid, text[])
{
    if(strfind(text, "how", true) != -1 && strfind(text, "get car", true) != -1) {
        SendClientMessage(playerid, -1, "To get a car, please use the /v command.");
        return 0;
    }
    return 1;
}
You can use this with various other strings in order to make your fun/stunt server more awesome, for example if the player says 'help me up', you can set his position 10 meters higher.
pawn Код:
public OnPlayerText(playerid, text[])
{
    if(strfind(text, "help me up", true)) {
        new Float:X, Float:Y, Float:Z;
        GetPlayerPos(playerid, X, Y, Z);
        SetPlayerPos(playerid, X, Y, Z + 10);
        SendClientMessage(playerid, -1, "I've set your position 10 meters higher - I hope you aren't stuck anymore!");
        return 0;
    }
    return 1;
}
(Yes, the very same thing can also be done with a simple command, but why not?)


  • Answering questions
For example, you can ask a question to the player, such as 'How old are you?', and you want the player to answer to this question directly by writing it into the chat.
Once again, we start with the base OnPlayerText function.
pawn Код:
public OnPlayerText(playerid, text[])
{
    return 1;
}
First of all, we will have to create some variables, but before that, please do the following if you haven't already:
At the top of your gamemode, put this:
pawn Код:
#undef MAX_PLAYERS
#define MAX_PLAYERS 200
Replace the '200' with your max player count. If it's less than 500, it will help, because it will use less space.

Now, we can create the variables! Make IsAnswering and pAge, with the size of MAX_PLAYERS, and define QUESTION_AGE as 1 and QUESTION_NONE as 0, like so:
pawn Код:
new IsAnswering[MAX_PLAYERS];
new pAge[MAX_PLAYERS];
#define QUESTION_NONE 0
#define QUESTION_AGE  1
Now, where shall we ask the question? Let's do it in OnPlayerSpawn.
pawn Код:
public OnPlayerSpawn(playerid)
{
    SendClientMessage(playerid, -1, "QUESTION: How old are you? (please answer the question in the chat.)");
    IsAnswering[playerid] = QUESTION_AGE;    
    return 1;
}
We have asked the player the question, and we have set IsAnswering to QUESTION_AGE so that we know what he will be answering in OnPlayerText.

Now, let's add an if statement which checks whether the player is answering QUESTION_AGE.
pawn Код:
public OnPlayerText(playerid, text[])
{
    if(IsAnswering[playerid] == QUESTION_AGE)
    {
        // our code will be here!
    }
    return 1;
}
Now, let's think. What should we do? We should return 0 so the players don't see it, but how do we get the value as an integer, given that the text is a string?
Here's where we get saved by a very magic function - strval! We will declare a new variable and store the value of the string in it.
pawn Код:
public OnPlayerText(playerid, text[])
{
    if(IsAnswering[playerid] == QUESTION_AGE)
    {
        new age; // Declare the age variable.
        age = strval(text); // Set it to the value of the text.
        pAge[playerid] = age; // Set the Age variable to the typed age, which can be saved with the system of your choice.
        IsAnswering[playerid] = QUESTION_NONE; // You can add multiple questions and change it to the ID of the next question, then put the next question below as a ClientMessage.
        return 0;
    }
    return 1;
}
Of course, we might want to keep players from lying about their age or to keep 'kids' off our servers...
pawn Код:
public OnPlayerText(playerid, text[])
{
    if(IsAnswering[playerid] == QUESTION_AGE)
    {
        new age;
        age = strval(text);
        if(age >= 18 && age <= 100) // If you're old enough to play San Andreas and in realistic boundaries of age
        {
            pAge[playerid] = age; // Set the Age variable to the typed age, which can be saved with the system of your choice.
        }
        else if(age <= 18)
        {
                SendClientMessage(playerid, -1, "You're not old enough to play San Andreas!");
            Kick(playerid);
        }
        else if(age >= 100)
        {
            SendClientMessage(playerid, -1, "You can't be that old, and if you are, why are you playing San Andreas?");
            Kick(playerid);
        }
        return 0;
    }
    return 1;
}
.... Just kidding; I am underage person myself! This is just an example of what can be done.

This tutorial might be updated soon with more examples!
(EDIT: as of the 17th of August, 2013, I have not yet managed to do this; however, expect an update soon!)
3. Challenges for beginners
  1. Make a VIP chat, alongside the admin chat! If you understood anything of what was going on, it should be a piece of cake for you. Otherwise, do read the tutorial again. (Extremely Easy)
  2. Show a chat bubble above the player with the text that he has typed! (tip: make use of SetPlayerChatBubble) (Extremely Easy)
  3. Make a mute system! If the player is muted, his message doesn't get sent and he gets a message like 'You are muted. You cannot talk.' (Easy)
  4. Make a full tutorial! This shouldn't be hard, and only requires you to add more defines and if statements. (Easy)
  5. Make chat channels! If the player is in channel 1, he can only get messages from channel 1, if he's in channel 2, only from channel 2 and so on. (Medium)
  6. Make a censorship script: if the player says something like 'hi, <bad word here> you' change it into 'hi, **** you' WITHOUT removing the entire message. (tip: make use of strfind) (Medium/Hard)
P.S: If you actually read the whole tutorial and you have found mistakes in the text, please tell me. Thank you in advance!
Reply
#2

Good tutorial
Reply
#3

This is one of the very few tutorials that I liked. I like how you challenge the reader at the end. You should make more.
Reply
#4

Updated! I've added a section on 'Question answering', plus one new Easy challenge! Enjoy!

Quote:
Originally Posted by Hoss
Посмотреть сообщение
Good tutorial
Quote:
Originally Posted by VincentDunn
Посмотреть сообщение
This is one of the very few tutorials that I liked. I like how you challenge the reader at the end. You should make more.
Thanks a lot, guys! I appreciate that you like the tutorial. I'm still in the Easter vacation, so I have some time to make more tutorials.
Reply
#5

Nice tutorial. You can also format the text argument so you don't have to create an additional array. Not a big improvement but worth mentioning. This is assuming that it doesn't matter if "text[]" is altered.

Removed code that can cause possible bugs.
Reply
#6

Good Tutorial
Reply
#7

Nice tutorial useful for all
Reply
#8

Quote:
Originally Posted by ******
Посмотреть сообщение
If they are not connected then they are not an admin.
Oops! I always used to check if the player is connected in all loops. (I mostly use foreach now, though! Thank you so much! Your contributions to the SA-MP community have helped me very much.)

Quote:
Originally Posted by AlExAlExAlEx
Посмотреть сообщение
pawn Код:
stock SendMessageToAdmins(text[]) {
    for(new i = 0, i < MAX_PLAYERS, i++) {
        if(IsPlayerConnected(i)) {
            if(IsPlayerAdmin(i)) {
                SendClientMessage(playerid, -1, text);
            }
        }
    }
}
undefined symbol "playerid"
Oops! Change playerid to i, and remove IsPlayerConnected, like ****** has said.
i.e turn it into:
pawn Код:
stock SendMessageToAdmins(text[]) {
    for(new i = 0, i < MAX_PLAYERS, i++) {
        if(IsPlayerAdmin(i)) {
            SendClientMessage(i, -1, text);
        }
    }
}
Also, you can change -1 to whatever colour you'd like. I just use it because it's white and I usually start my messages with, uhm, intext colour coding (if I named it right).

Quote:
Originally Posted by Wickeed
Посмотреть сообщение
Good Tutorial
Thanks a lot!
Reply
#9

Reply
#10

good one
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)