Skip to content

phrase_system

Jan Boon edited this page Mar 13, 2026 · 1 revision

title: AI Script Phrase System description: How to send parameterized translated messages from AI scripts published: true date: 2026-03-14T00:00:00.000Z tags: editor: markdown dateCreated: 2026-03-14T00:00:00.000Z

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:

  1. phraseBegin() - Clear the parameter stack
  2. phrasePushValue() / phrasePushString() - Push parameters onto the stack (one call per parameter, in order)
  3. phraseEndNpcMsg() / phraseEndSystemMsg() / phraseEndEmoteMsg() - Send the message with all pushed parameters

Quick Example

// 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$!]
}

Step 1: phraseBegin

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();

Step 2: Push Parameters

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.

phrasePushValue(type, number)

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.

phrasePushString(type, string)

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 list

Step 3: Send the Message

Three functions send the completed message, each through a different channel:

phraseEndNpcMsg(botIndex, sayMode, phraseId)

Send through an NPC's chat bubble. The bot must be alive and spawned.

()phraseEndNpcMsg(0, "say", "MY_PHRASE_ID");
  • botIndex (float): Which bot in the group speaks (0 = first bot)
  • sayMode (string): "say", "shout", "civilization", "territory", "universe", "arround", "system", "region"
  • phraseId (string): The phrase identifier from the translation files

phraseEndSystemMsg(botIndex, sayMode, phraseId)

Send as a system message (appears in the system info channel). Same parameters as phraseEndNpcMsg.

()phraseEndSystemMsg(0, "say", "MY_SYSTEM_PHRASE");

phraseEndEmoteMsg(botIndex, phraseId)

Send as an emote message (appears in the emote channel). No say mode parameter.

()phraseEndEmoteMsg(0, "MY_EMOTE_PHRASE");

Alternative: setSimplePhrase

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.

Complete Example: Boss Announcing Kill

// 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?]
}

See also

Source: ryzom/server/src/ai_service/nf_grp.cpp (phraseBegin, phrasePush*, phraseEnd*)

Clone this wiki locally