14.04.2015, 20:30
Contents
y_text is the single most complex library in YSI 3.0, but using it is (hopefully) very simple. The library works on the idea from HTML/CSS/JavaScript of separation of content, style and logic. Most modes contain code like this:
That's all well and good, and VERY common. But if you have a typo you need to recompile your mode, if you want to change the colour you need to recompile your mode, and changing how the text displays (for example converting to text draws) is a lot more work. y_text on the other hand has just one display method:
The "HELLO_MESSAGE" text is defined in files, along with the style of the text, and can come in multiple languages, making this more equivalent to:
By default y_languages supports five languages at once, but this can be increased VERY easilly.
Text
There are three parts to displaying text: Creating the files, loading them, and displaying the text. Fortunately these are all quite simple.
These are both INI files with standard "KEY = Value" pairs. They also MUST contain sections (here "[all]" is a section), but the simplest way is to just have one.
You also need a third file called "mode_text_LANG_DATA.yml" in "scriptfiles/YSI", but I'll come to that later.
The "loadtext" line gives the current script file access to the items defined in the listed file and section. You can have up to about 5 items on one line and only one line (current code restriction) PER FILE:
The "Langs_Add" line tells the language system which languages to load and gives the name of that language in that language (hence "Dutch" is "Nederlands"). It also defines the two letter short code for that language, which is used to select the exact file to load. "English" is defined as "EN" and the file is "mode_text.EN", simillarly "Dutch" is defined as "NL" and the file is "mode_text.NL". Note that this is the ONLY function in YSI that will give a warning if it is not used because YSI needs to know what languages to load for internal text (even if you don't use the system yourself).
"Text_Send" is a VERY clever function:
As mentioned, text can be sent to any number of people, meaning you no longer need "Text_SendToPlayer", "Text_SendToGroup", "Text_SendToAdmins", "Text_SendToAll" etc. The first three methods are designed to mimic existing code methods and make for simple integration in to existing modes. When you send a message to mutliple people using one of the methods below every player will get the message in their own language. These calls are also optimised for many people and multiple languages so are better than simply calling "Text_Send" in a loop (there is text buffering to re-use calculated output instead of re-running processing).
The above code will send the message "$SOME_MESSAGE" to everyone for whom "gIsAdmin" is TRUE (you can't do it for everyone who is FALSE). Note that "gIsAdmin" is not a YSI array (just a nomal array) so you need "@" on the front to convert it (another restriction I've tried to make as low-impact as possible).
This code is very similar to the previous code, but instead of an array of true/false, this is a list of player IDs, with "INVALID_PLAYER_ID" (or the end of the array) denoting the end of the list. The code above will send the message to players 0, 42 and 45. 27 WILL NOT get a message as their ID appears AFTER "INVALID_PLAYER_ID", denoting the end of the list.
Often you will want to send a message to everyone for whom "E_PLAYER_DATA_ADMIN" is true. This is (in "y_text" speak) a "custom" array:
This specifies that "gPlayerData" is a 2d enum array and only the "E_PLAYER_DATA_ADMIN" slot should be used. It should be noted that this line MAY give a warning about index tag mismatches, I don't know how to avoid this so just ignore it.
The code above will, unsurprisingly, send the message to everyone in the "gAdmins" group. Groups in general have been documented before in another tutorial so will not be covered further here.
This behaves exactly like the first target, but with less memory and slightly more efficiently.
Styles
Obviously "Text_Send" has no included information as to HOW the text should be displayed - using "SendClientMessage", "GameText", "TextDraw" or anything else. This is all set in the "LANG_DATA" file:
[/list]
Format
"Text_Send" can take format parameters, and it has been extended with a greater number than the default "format" function.
- Contents
- Introduction
- Text
- Defining
- Loading
- Displaying
- Targets
- Boolean Arrays
- Player Lists
- Custom Arrays
- Groups
- Player Arrays
- Single Players
- y_playerset
- Styles
- Example
- XML
- style
- Style "client"
- Styles 0, 1, 2, 3, 4, 5, 6
- Stlye "draw"
- Style "3d" And Style "player"
- Format
- Specifiers
- Modifiers
- Colours
- X11
- Custom Colours
- Close
- Fades
- Languages
- Advanced
- Long Lines
- Codes
- GameText Formats
- Wrapping
y_text is the single most complex library in YSI 3.0, but using it is (hopefully) very simple. The library works on the idea from HTML/CSS/JavaScript of separation of content, style and logic. Most modes contain code like this:
PHP Code:
SendClientMessage(playerid, COLOUR_RED, "Hello there");
PHP Code:
Text_Send(playerid, $HELLO_MESSAGE);
PHP Code:
switch(PlayerLanguage(playerid))
{
case ENGLISH:
SendClientMessage(playerid, COLOUR_RED, "Hello there");
case FRANCAISES:
SendClientMessage(playerid, COLOUR_RED, "Bonjour il"); // Etc..
}
Text
There are three parts to displaying text: Creating the files, loading them, and displaying the text. Fortunately these are all quite simple.
- Defining
- mode_text.EN
Code:
[all] HELLO_MESSAGE = Hello there BYE_MESSAGE = Goodbye
- mode_text.NL
Code:
[all] HELLO_MESSAGE = Hallo daar BYE_MESSAGE = Tot ziens
You also need a third file called "mode_text_LANG_DATA.yml" in "scriptfiles/YSI", but I'll come to that later.
- Loading
PHP Code:
loadtext mode_text[all];
public OnGameModeInit()
{
Langs_Add("EN", "English");
Langs_Add("NL", "Nederlands");
}
PHP Code:
loadtext mode_text[section1], mode_text[section2], other_text[what], other_text[where];
- Displaying
PHP Code:
Text_Send(playerid, $HELLO_MESSAGE);
- The first paramter ("playerid" above) can be one of a number of things: A single playerid, an array of players, a YSI player array, an array of IDs, "ALL_PLAYERS", "ALL_BOTS", "ALL_CHARACTERS", or a YSI group.
- The second parameter is an identifier from a file (here "$HELLO_MESSAGE"). Note that the section with this message in MUST be loaded for the current file:
Good:
PHP Code:loadtext mode_text[all];
public OnPlayerConnect(playerid)
{
Text_Send(playerid, $HELLO_MESSAGE);
}
PHP Code://loadtext mode_text[all];
public OnPlayerConnect(playerid)
{
Text_Send(playerid, $HELLO_MESSAGE);
}
- "Text_Send" also takes EXTENDED format parameters (all the existing ones and then some):
PHP Code:[my_section]
SOME_NUMBER = Your number is %d
PHP Code:loadtext my_file[my_section];
stock Func(playerid, num)
{
Text_Send(playerid, $SOME_NUMBER, num);
}
As mentioned, text can be sent to any number of people, meaning you no longer need "Text_SendToPlayer", "Text_SendToGroup", "Text_SendToAdmins", "Text_SendToAll" etc. The first three methods are designed to mimic existing code methods and make for simple integration in to existing modes. When you send a message to mutliple people using one of the methods below every player will get the message in their own language. These calls are also optimised for many people and multiple languages so are better than simply calling "Text_Send" in a loop (there is text buffering to re-use calculated output instead of re-running processing).
- Boolean Arrays
PHP Code:
new
bool:gIsAdmin[MAX_PLAYERS];
// Notice that this is only on one line, unlike the declaration above! This is
// another system restriction but shouldn't be too bad.
loadtext some_file[some_section];
stock Func()
{
Text_Send(@ gIsAdmin, $SOME_MESSAGE);
}
- Player Lists
PHP Code:
new
gAdmins[MAX_PLAYERS] = {0, 42, 45, INVALID_PLAYER_ID, 27, ...};
// Notice that this is only on one line, unlike the declaration above! This is
// another system restriction but shouldn't be too bad.
loadtext some_file[some_section];
stock Func()
{
Text_Send(@ gAdmins, $SOME_MESSAGE);
}
- Custom Arrays
PHP Code:
enum E_PLAYER_DATA
{
E_PLAYER_DATA_SOMETHING,
E_PLAYER_DATA_OTHER,
bool:E_PLAYER_DATA_ADMIN
}
new
gPlayerData[MAX_PLAYERS][E_PLAYER_DATA];
PHP Code:
stock Func()
{
Text_Send(@ gPlayerData<E_PLAYER_DATA_ADMIN>, $SOME_MESSAGE);
}
- Groups
PHP Code:
new
Group:gAdmins;
public OnGameModeInit()
{
gAdmins = Group_Create("Admins");
}
stock Func()
{
// No "@" in front of the variable.
Text_Send(gAdmins, $SOME_MESSAGE);
}
- Player Arrays
PHP Code:
new
PlayerArray:gAdmins<MAX_PLAYERS> = {PA_INIT:false, ...};
stock Func()
{
// No "@" in front of the array.
Text_Send(gAdmins, $SOME_MESSAGE);
}
- Single Players
PHP Code:
Text_Send(playerid, $SOME_MESSAGE);
- y_playerset
PHP Code:
#define MyFunc(%0) PSF:_MyFunc(%0)
stock _MyFunc(@PlayerArray:players<MAX_PLAYERS>)
{
// "players" is now a YSI "PlayerArray" of all the players passed at once.
foreach (new playerid : PA(players))
{
// Uses "PA".
}
}
PHP Code:
#define MyFunc(%0) PSF:_MyFunc(%0)
stock _MyFunc(@PlayerVar:player)
{
// This function will be called multiple times automatically, once for every
// player passed in any array.
}
PHP Code:
#define MyFunc(%0) PSF:_MyFunc(%0)
stock _MyFunc(@PlayerSet:players)
{
// "players" is now a special compact representation of all the players
// passed and can be used in iterators. This is different to using
// "@PlayerArray" as it's just a single variable, not all players at once.
foreach (new playerid : PS(players))
{
// Uses "PS".
}
}
Obviously "Text_Send" has no included information as to HOW the text should be displayed - using "SendClientMessage", "GameText", "TextDraw" or anything else. This is all set in the "LANG_DATA" file:
- Example
- scriptfiles/YSI/text/mode_text.EN
Code:
[all] HELLO_MESSAGE = Hello there BYE_MESSAGE = Goodbye
- scriptfiles/YSI/text/mode_text.NL
Code:
[all] HELLO_MESSAGE = Hallo daar BYE_MESSAGE = Tot ziens
Code:
<YML> <group name="all"> <entry name="HELLO_MESSAGE" style="client" colour="X11_RED" /> <entry name="BYE_MESSAGE" style="3" time="4000" /> </group> </YML>
- XML
- style
- client - Use "SendClientMessage".
- 0 - 6 - Use "GameText" styles 0 - 6.
- draw - Use "TextDraw".
- 3d - Use 3d text (not fully supported yet).
- player - Use "SendPlayerMessage".
- Style "client"
- colour - AKA "color". The colour you want this text to start as. There are thousands of colours built in to the system that can be used by name, or you can specify a new colour and name it yourself for later use:
Code:<YML> <group name="all"> <entry name="HELLO_MESSAGE" style="client"> <colour name="My_Green" hex="00FE00" /> </entry> </group> </YML>
Code:<YML> <group name="all"> <entry name="HELLO_MESSAGE" style="client" colour="00FE00" /> </group> </YML>
- Styles 0, 1, 2, 3, 4, 5, 6
- time - The time to display this text for in milliseconds. Note that this may be ignored by certain game text styles.
- colour - This is the same as the "colour" option for "client" and the system will match the specified colour as closely as possible for the start of the game text.
- Style "draw"
- textdraw - This specifies a textdraw style by name from the "y_td" library. This will be better documented later, but as with "colour" it can use an existing one or define a new one inline:
Code:<YML> <group name="all"> <entry name="HELLO_MESSAGE" style="draw"> <textdraw box="YELLOW" background="0" color="green" y="134" x="132" texty="0" textx="637" alignment="1" outline="1" proportional="1" shadow="0" lettery="1" letterx="1" name="YSI_0003" time="10000"> </textdraw> </entry> </group> </YML>
- Style "3d" And Style "player"
Format
"Text_Send" can take format parameters, and it has been extended with a greater number than the default "format" function.
- Specifiers
- b - Boolean. This now works for negative numbers.
- c - Character.
- d, i - Integer (Decimal).
- f - Float.
- g - IEEE float (has "NAN" and "INFINITY").
- h, x - Hex (heX). This now works for negative numbers.
- l - Logical ("true" or "false"). Any number not 0 will be displayed as "true", 0 will be "false".
- n - commaNd. This was chosen as "%n" as it was the first new one added and at the time "%n" caused a crash in "format" (and "%c" was taken). In YSI commands can be renamed and different people can have different names for the same command. Using this will always give the correct name for the current player. The commands are specified using their "YCMD" syntax:
Code:[comms] COMM_MESSAGE = Command /%n
PHP Code:loadtext file[comms];
stock Func(playerid)
{
// Show the player what "YCMD:hi" is called for them.
Text_Send(playerid, $COMM_MESSAGE, YCMD:hi);
}
- q - player ("q" is near "p", and "p" is unavailable for historical reasons). Show a player's name (I was sick of writing "GetPlayerName"):
Code:[player] PLAYER_MESSAGE = Player %d is %q
PHP Code:loadtext file[player];
stock Func(playerid)
{
// Show the player their ID and what they are called.
Text_Send(playerid, $PLAYER_MESSAGE, playerid, playerid);
}
- s - String.
- Modifiers
- ! - Defines a list of elements:
Code:- INTS_MESSAGE = List %!d
PHP Code:loadtext file
- ;
{
// Show the player a list of numbers.
new
arr[4] = {5, 6, 7, 8};
Text_Send(playerid, $INTS_MESSAGE, arr, sizeof (arr));
}
- This will give an output of:
Code:List 5, 6, 7, 8
- ? - Get the data from a function. This is a work in progress, but will display data similar to "!".
[/pawn]
- X11
http://en.wikipedia.org/wiki/X11_color_names
The full list is here, but without the actual colour shown, just the RGB:
http://cvsweb.xfree86.org/cvsweb/*ch...gb.txt?rev=1.1
Note that YSI also supports British spellings (i.e. "grey" as well as "gray" (the list misses "SlateGrey1" for example), and "colour" as well as "color").
These are known as the "X11" colours (being based on those found in the "X11" windowing system). They are available for use in a range of manners through YSI:
Code:[some_text] MESSAGE1 = Hi {X11_ALICE_BLUE}there ; With "X11" and underscores. MESSAGE2 = Hi {X11 ALICE BLUE}there ; With "X11" and spaces. MESSAGE3 = Hi {X11ALICEBLUE}there ; With "X11". MESSAGE4 = Hi {x11_aLiCe BlUe}there ; Space and case mixture. MESSAGE5 = Hi {ALICE BLUE}there ; Space only. MESSAGE6 = Hi {ALICE_BLUE}there ; Underscore only. MESSAGE7 = Hi {ALICEBLUE}there ; Nothing. MESSAGE8 = Hi #ALICEBLUEthere ; Alternate style.
Code:// This is stand alone from y_text. #include <YSI\y_colours> #define COlOUR_ERROR_1 X11_SLATE_GREY #define COlOUR_ERROR_2 X11_SLATEGREY #define COlOUR_ERROR_3 X11_SLATE_GRAY #define COlOUR_ERROR_4 X11_SLATEGRAY
Code:[some_text] AMBIGUOUS = #GOLDenter
Code:[some_text] OBVIOUS = {GOLD}enter
- Custom Colours
PHP Code:SetColour("WARNING", 0xFE0101AA); // AKA "SetColor".
PHP Code:new colour = GetColour("WARNING"); // AKA "GetColor".
Code:[some_text] CUSTOM = {WARNING}Warning!
PHP Code:loadtext file[some_text];
public OnGameModeInit()
{
Langs_Add("EN", "English");
SetColour("WARNING", 0xFE0101AA); // AKA "SetColor".
return 1;
// Files are loaded after this.
}
- Close
https://sampforum.blast.hk/showthread.php?tid=194316
I have adopted this idea here too:
Code:[some_text] THREE = One{RED} Two{/} Three
Code:<YML> <group name="some_text"> <entry name="THREE" style="client" color="GREEN" /> </group> </YML>
- Fades
Code:[some_text] FADE_TO_BLACK = {>GREEN}Fade To Black{<BLACK} FADE_PARTIALLY = {>GREEN}Fade {</}Somewhere
Languages
A player's language is set using "Langs_SetPlayerLanguage(playerid, Language:l);" The language ID ("Language:l") is returned by "Language:Langs_AddLanguage(string:code[], string:name[]);":
PHP Code:new
Language:gLEnglish;
public OnGameModeInit()
{
gLEnglish = Langs_Add("EN", "English"); // AKA "Langs_AddLanguage".
return 1;
}
public OnPlayerConnect(playerid)
{
Langs_SetPlayerLanguage(playerid, gLEnglish);
}
Other functions:- Language:Langs_GetPlayerLanguage(playerid); - Get a player's current language.
- string:Langs_GetCode(Language:l); - Get the 2 letter code for the given language.
- string:Langs_GetName(Language:l); - Get the full name for the given language.
- Language:Langs_GetLanguageCount(); - Get the number of languages in the system.
- string:Langs_GetLanguageCodes(); - Get all the short codes sparated by "|".
- Language:Langs_GetLanguage(string:identifier[]); - Get the language ID from a string identifier (either 2 letter short code or full name).
- Langs_RemoveLanguage(Language:l); - Remove the given language. Can not currently be called while anyone is still using the language.
Advanced- Long Lines
- mode_text.EN
Code:[section] LONG_TEXT_1 = This is part of a long line of text. LONG_TEXT_2 = The text is linked by the "_1" and "_2" suffixes. LONG_TEXT3 = This is NOT part of the long text.
- mode_text_LANG_DATA.yml
Code:<YML> <group name="section"> <entry name="LONG_TEXT" style="client" colour="X11_RED" /> </group> </YML>
PHP Code:Text_Send(playerid, $LONG_TEXT);
- mode_text.EN
Code:[section] LONG_TEXT_42 = The text is linked by the "_1" and "_2" suffixes. LONG_TEXT_27 = This is part of a long line of text.
- Codes
- \n - Create a new line. For "ClientMessage" this will end the current line and start a new one, for "TextDraw" and "GameText" this will be translated in to "~n~". Note that in MOST circumstances colour fades can span new lines (I know that doesn't sound impressive, but it was HORRIBLE to code (took months)).
- \s - Add a space. In the above examples the two lines are joined right next to each other as extra leading and trailing spaces are stripped out. This escape code is used to bypass that behaviour.
- \t - Add a tab, and not just a tab character. This will actually work out the correct spacings and add relevant spaces in most cases (essentially this replicates the bahaviour of the tab character, as the real one is not supported in SA:MP text).
- \% - Does the same as "%%" (displays a percent sign instead of starting a format code).
- \\ - Displays a back slash.
- \" - Shows a double quote. Not actually needed as an unescaped double quote will also work when reading from files.
- \' - Single quote, see above.
- \x<HEX>; - Insert the character with the given HEX code (0 - 9, A - F).
- \<DEC>; - Insert the character with the given DECIMAL code (0 - 9).
- GameText Formats
PHP Code:MULTI_TEXT = ~r~Red, {00FF00}Green, #BLUEBlue.
Note also that the rendering is as smart as possible. For one thing the default "GameText" colour is not available through any "~X~" code, but the system will use it when it can. The system will also use the previous colour, so the following is a possible output:
PHP Code:~r~Some ~h~Colours
- Wrapping
Credits
This post was originally written by Y_Less. I'm merely reposting it for future scripters to develop their knowledge. I've also fixed a few dutch language mistakes, hehe.