Page tree
Skip to end of metadata
Go to start of metadata

Tokens can be used to introduce different colours in almost any text element in the game.

See the nwnlexicon tutorial on custom tokens for more information.

Colour Custom Tokens

A subset of custom tokens - you can use <cRGB></c> where RGB is a RGB code but, of course since this isn't simple, it's not in number form but ASCII character reference...very odd (smile)

This means you can use a long ASCII string to find the right "number", eg;

const string COLOR_TOKEN = "                  ##################$%&'()*+,-./0123456789:;;==?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[[]^_`abcdefghijklmnopqrstuvwxyz{|}~~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ¡¡¢£¤¥¦§¨©ª«¬¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþþ";

string GetStringColoredRGB(string sString, int nRed=255, int nGreen=255, int nBlue=255)
    return "<c" + GetSubString(COLOR_TOKEN, nRed, 1) + GetSubString(COLOR_TOKEN, nGreen, 1) + GetSubString(COLOR_TOKEN, nBlue, 1) + ">" + sString + "</c>";

This function can make a complete string that then could be passed, say, to a custom token for inclusion in a conversation. It can also be used in other text locations (eg; SpeakString, SendMessageToPC, etc.)

A simpler version is available in x0_i0_string.nss

The game uses the <cRGB></c> format internally so it can be used by modders to create any coloured text.

If you want to add these tokens directly into a TLK file you can use webpages such as this:

For more information on colour tokens in general see:

You can find a more advanced set of scripts for color tokens here:

In the latest versions of NWN:EE you can now escape any ASCII character (except 0) with \x in NWScript, eg:

// COLOR_TOKEN originally by rdjparadis. Used to generate colors from RGB values. NEVER modify this string.
// This requires a later version of NWN:EE to use the \x escape character
// For more information:
// NB: First character is "nearest to 00" since we can't use \x00 itself (means you can't get completely black is all)
const string COLOR_TOKEN = "\x01\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF";
// Gets a suitable <cXXX> token to use at the start of a block of colored text. Must be terminated by </c>
// - nRed - Red amount (0-255)
// - nGreen - Green amount (0-255)
// - nBlue - Blue amount (0-255)
string GetColorCode(int nRed=255, int nGreen=255, int nBlue=255)
    return "<c" + GetSubString(COLOR_TOKEN, nRed, 1) + GetSubString(COLOR_TOKEN, nGreen, 1) + GetSubString(COLOR_TOKEN, nBlue, 1) + ">";
void main()
    SpeakString(GetColorCode(255, 20, 147) + "Speaking in Deep Pink!" + "</c>");

Having Custom Colour Tokens in Conversations, Journals, and Descriptions

To use <cXXX> code in a conversation/journal/description, you either need to add an additional "<" in from of each colour token when using the toolset editors (so that <c***>text</c> becomes <<c***>text<</c>), or alternatively, rely on <CUSTOMXXX> tokens set in scripts and reference those. The latter solution will give you more control of the colours since the various editors do not support all characters.

To use the custom token method, have a script like this in the OnModuleLoad:

const string COLOR_TOKEN = "                  ##################$%&'()*+,-./0123456789:;;==?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[[]^_`abcdefghijklmnopqrstuvwxyz{|}~~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ¡¡¢£¤¥¦§¨©ª«¬¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþþ";

string GetRGBCToken(int nRed=255, int nGreen=255, int nBlue=255)
    return "<c" + GetSubString(COLOR_TOKEN, nRed, 1) + GetSubString(COLOR_TOKEN, nGreen, 1) + GetSubString(COLOR_TOKEN, nBlue, 1) + ">";
void main()
    SetCustomToken(1000, "</c>");
    SetCustomToken(1001, GetRGBCToken(255, 0, 0));
    SetCustomToken(1002, GetRGBCToken(0, 255, 0));
    SetCustomToken(1003, GetRGBCToken(0, 0, 255));

Then in the conversation editor you can do this:

<CUSTOM1001>Hello in red.<CUSTOM1000> Normal text. <CUSTOM1002>Hello in green.<CUSTOM1000> Normal text. <CUSTOM1003>Hello in blue.<CUSTOM1000> Normal Text. <CUSTOM1004>Hello in black.<CUSTOM1000> Normal Text. <CUSTOM1005>Hello in white.<CUSTOM1000>

Ending up like this:

This can be some good code to use for manually doing it (to be updated with a better code when newer patch comes out + some idea about default colours is obtained):

// OnModuleLoad
void main()
    SetCustomToken(1000, "</c>"); // CLOSE tag
    SetCustomToken(1001, "<cþ  >"); // red
    SetCustomToken(1002, "<c þ >"); // green
    SetCustomToken(1003, "<c  þ>"); // blue
    SetCustomToken(1004, "<c þþ>"); // cyan
    SetCustomToken(1005, "<cþ þ>"); // magenta
    SetCustomToken(1006, "<cþþ >"); // yellow
    SetCustomToken(1007, "<c   >"); // black
    SetCustomToken(1008, "<c¥  >"); // dark red
    SetCustomToken(1009, "<c ¥ >"); // dark green
    SetCustomToken(1010, "<c  ¥>"); // dark blue
    SetCustomToken(1011, "<c ¥¥>"); // dark cyan
    SetCustomToken(1012, "<c¥ ¥>"); // dark magenta
    SetCustomToken(1013, "<c¥¥ >"); // dark yellow
    SetCustomToken(1014, "<c¥¥¥>"); // grey
    SetCustomToken(1017, "<cŒŒŒ>"); // dark grey
    SetCustomToken(1015, "<cþ¥ >"); // orange
    SetCustomToken(1016, "<cþŒ >"); // dark orange
    SetCustomToken(1017, "<cÚ¥#>"); // brown
    SetCustomToken(1018, "<c† >"); // dark brown

Custom Damage Example

You can use a mixture of SetTlkOverride and SetCustomToken to make something like custom damage, eg reusing "Divine" damage since it is generally unresisted can give this:

With this in an OnUsed event of a lever:

void main()
    SetCustomToken(100, "</c>");
    SetCustomToken(101, "<cÿ´ô>");
    SetTlkOverride(5593, "<CUSTOM100><CUSTOM101><CUSTOM0> Something Painful");
    ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(1, DAMAGE_TYPE_DIVINE), GetLastUsedBy());
    // Reset so usual divine damage looks ok (or go replace divine damage in all scripts with positive damage or something).
    SetTlkOverride(5593, "");

You might want Hardcoded TLK Lines to reference some of the games TLK references to override.

Default Colour References

A semi-complete list of the default colours Bioware use, so in case you want to replicate an existing thing like "You're damaged by magical damage!" in a conversation.

Use Hex RGB like so:

SetCustomToken(1001, GetRGBCToken(0xcc, 0x77, 0xff)); // Magical Damage

Colour TypeHex RGBPictureNotes/Usage
Magical Damagecc77ff

Acid Damage01ff01

Cold Damage99ffff

Divine Damage


Electrical Damage0166ff

Fire Damageff0101

Negative Damage999999

Positive Damageffffff

Sonic Damageff9901

Feedback messages


Combat messages


Magic related messages


Skill check messages


Saving throw messages

Save Status

When saving the game

Pause State

When pausing or unpausing

Client Name


The players name

Other Name


Ordering Lists

Anything that orders on the contents of a string - eg the feats or skills in a character sheet - can be made into a custom order using empty colour strings, eg:

<c000></c>Feat Section 1
<c001></c>Feat 1
<c001></c>Feat 4
<c001></c>Feat 6
<c002></c>Feat Section 2
<c003></c>Feat 2
<c003></c>Feat 3
<c003></c>Feat 5

Without the colour codes you will get the order "Feat 1, 2, 3, 4, 5, 6 Section 1, Section 2" but with them you get "Feat Section 1, 1, 4, 6, Section 2, 2, 3, 5"

  • No labels