The phrase system allows AI scripts to send parameterized messages to players through the server's localization system. Instead of sending literal text, you reference a phrase identifier defined in the translation files (phrase_<lang>.txt), and push typed parameters that the translation system substitutes into the phrase template.
This is a multi-step pipeline using several functions together:
phraseBegin() - Clear the parameter stackphrasePushValue() / phrasePushString() - Push parameters onto the stack (one call per parameter, in order)phraseEndNpcMsg() / phraseEndSystemMsg() / phraseEndEmoteMsg() - Send the message with all pushed parameters// An NPC announces a bounty to nearby players
()phraseBegin();
()phrasePushString("player", $playerEid);
()phrasePushValue("integer", 500);
()phraseEndNpcMsg(0, "say", "BOUNTY_ANNOUNCEMENT");
This sends the phrase BOUNTY_ANNOUNCEMENT through bot index 0 (first bot in the group) in "say" mode. The phrase in phrase_en.txt might be defined as:
BOUNTY_ANNOUNCEMENT (player p, int amount)
{
[Attention! There is a bounty of $amount$ dappers on $p$!]
}
Always call phraseBegin() before building a new message. This clears the parameter stack. If you forget this and a previous phrase call didn't complete properly (e.g. due to an error), leftover parameters could corrupt your message.
()phraseBegin();
Parameters must be pushed in the same order as they are declared in the phrase definition. There are two push functions depending on whether the value is numeric or a string.
Use for numeric values. The type determines how the number is interpreted:
| Type | Description | Example |
|---|---|---|
integer |
Signed 32-bit integer | ()phrasePushValue("integer", 42); |
money |
Amount in dappers (unsigned 64-bit) | ()phrasePushValue("money", 1500); |
time |
Time in game ticks (unsigned 32-bit) | ()phrasePushValue("time", 200); |
Other types (skill, faction, power_type, race, damage_type, characteristic, score, body_part) also accept numeric values, but these must be the C++ enum values, not strings. Ask a programmer for the correct integer values if you need these.
Use for string-based values. The type determines how the string is interpreted:
| Type | Input format | Description |
|---|---|---|
literal |
Any text | Literal text inserted as-is |
player |
Entity ID string | A player, obtained from getCurrentPlayerEid() etc. |
bot |
Entity ID string | An NPC bot, obtained from getBotEid() etc. |
entity |
Entity ID string | Any entity (player or bot) |
item |
Sheet name | An item, e.g. "iccm1bm.sitem" |
sbrick |
Sheet name | A skill brick, e.g. "bfma01.sbrick" |
creature_model |
Sheet name | A creature, e.g. "ccdeb3.creature" |
sphrase |
Sheet name | A sabrina phrase sheet |
outpost |
Sheet name | An outpost sheet |
place |
Identifier | A place name identifier |
event_faction |
Identifier | An event faction identifier |
title |
Identifier | A title identifier |
integer |
Numeric string | Parsed as integer (alternative to phrasePushValue) |
money |
Numeric string | Parsed as money amount |
time |
Numeric string | Parsed as time value |
Entity IDs are obtained from functions like:
($eid)getCurrentPlayerEid() - the player clicking on a bot($eid)getBotEid(0) - bot by index in the group($eid)getAggroListElement(0, 0) - entity from aggro listThree functions send the completed message, each through a different channel:
Send through an NPC's chat bubble. The bot must be alive and spawned.
()phraseEndNpcMsg(0, "say", "MY_PHRASE_ID");
"say", "shout", "civilization", "territory", "universe", "arround", "system", "region"Send as a system message (appears in the system info channel). Same parameters as phraseEndNpcMsg.
()phraseEndSystemMsg(0, "say", "MY_SYSTEM_PHRASE");
Send as an emote message (appears in the emote channel). No say mode parameter.
()phraseEndEmoteMsg(0, "MY_EMOTE_PHRASE");
For one-off messages that don't need translation file entries, setSimplePhrase defines a phrase inline:
()setSimplePhrase("TEMP_PHRASE_1", "Hello, this is a test message!");
()phraseBegin();
()phraseEndNpcMsg(0, "say", "TEMP_PHRASE_1");
This creates a temporary phrase ID with literal text. Useful for debugging or dynamically generated messages.
// In a bot_target_killed event handler:
($playerEid)getCurrentPlayerEid();
($botEid)getBotEid(0);
()phraseBegin();
()phrasePushString("player", $playerEid);
()phrasePushString("bot", $botEid);
()phrasePushValue("integer", killCount);
()phraseEndNpcMsg(0, "shout", "BOSS_KILL_TAUNT");
With phrase definition:
BOSS_KILL_TAUNT (player p, bot b, int count)
{
(count = 1) [Hah! $p$ is my first victim today!]
(count > 1) [That makes $count$ victims! Who's next?]
}
Source: ryzom/server/src/ai_service/nf_grp.cpp (phraseBegin, phrasePush*, phraseEnd*)