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.
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
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: https://colortoken.nwn1.net/
For more information on colour tokens in general see: https://neverwintervault.org/project/nwn1/other/hitchhikers-guide-color-tokens
You can find a more advanced set of scripts for color tokens here: https://github.com/silm/silm/blob/master/mod/nss/includes/inc_colors.n
In the latest versions of NWN:EE you can now escape any ASCII character (except 0) with \x in NWScript:
// 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: https://nwn.wiki/display/NWN1/Colour+Tokens
// 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>");
} |
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>):
void main()
{
SetTlkOverride(5593, "<</c><<\x0B\x0C\x0D><CUSTOM0> Something Painful");
} |
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 = "\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";
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
} |
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.
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 Type | Hex RGB | Picture | Notes/Usage |
|---|---|---|---|
| Magical Damage | cc77ff | ||
| Acid Damage | 01ff01 | ||
| Cold Damage | 99ffff | ||
Divine Damage | ffff01 | ||
| Electrical Damage | 0166ff | ||
| Fire Damage | ff0101 | ||
| Negative Damage | 999999 | ||
| Positive Damage | ffffff | ||
| Sonic Damage | ff9901 | ||
| Feedback | ffff01 | Feedback messages | |
Combat | ff6601 | Combat messages | |
Magic | cc77ff | Magic related messages | |
Skills | 0166ff | Skill check messages | |
Saving | 66ccff | Saving throw messages | |
Save Status | 20ff20 | When saving the game | |
Pause State | ff0101 | When pausing or unpausing | |
Client Name | 99ffff |
| The players name |
Other Name | cc99cc |
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"