Custom Hair Colours Guide
The client ships nine hair colours and will crash if you ask it for one that has no palette. This patch stops the crash, keeps the picker honest, and lets you add more colours behind a pager. For hair styles, see the Custom Hairstyles guide; styles and colours are separate jobs.
.pal files per style, gender and colour; three swatch bitmaps per colour; max_hair_color on the server9 to 90 colours in total, stock nine included; 9 is the default and changes nothingWhat it does
1. Stops a crash
Pick a colour for a hairstyle that ships no matching .pal file and the client does not fall back. It shows an error and then dies:
CPaletteRes :: Cannot find File : palette\¸Ó¸®\¸Ó¸®47_³²_8.pal
-> OK -> Gravity(tm) Error Handler, Exception Type 0xc0000005
The crash happens because the code that recolours the sprite uses the palette pointer without checking that it loaded. It cannot be caught after the fact: the client's palette loader has no failing return, so the only fix is to never ask for a palette that is not there. The patch checks first and discards the click, exactly as the client does for a button you did not hit.
The same check runs when you change style, because a colour you already picked can be stranded by the new style.
2. Keeps the picker honest
When that style check fires, your colour is forced back to none. The highlighted square used to stay lit on the colour you had picked, so the panel disagreed with the character. The row is now repainted to match.
3. Adds colours past nine
Tick the patch and it asks how many colours the picker should offer. Leave it at 9 and nothing about the layout changes. Above nine, the row keeps its size and gains a tenth cell that pages to the next nine and wraps at the end, the same way the hair style grid does.
Adding a colour, end to end
A colour is not one file. Four things have to agree: the palette that recolours the hair, the swatch art in the picker, the total you give the patch, and the server's own cap. Miss any one and the symptom looks like a different problem.
1 Palettes: what actually recolours the hair
A hair sprite stores no colour at all. Its pixels are numbers, and the .pal file is the lookup table that turns each number into a colour. Same sprite, different palette, different hair.
They live in the client's hair palette folder. Its name is Korean, and the client stores it as raw code page bytes, so on a Western-locale machine it reads as ¸Ó¸®. The gender part of each filename is the same kind of name: ³² for male, ¿© for female. These are the literal names on disk, not placeholders to fill in:
¸Ó¸®10_³²_12.pal hairstyle 10, male, colour 12
¸Ó¸®10_¿©_12.pal hairstyle 10, female, colour 12
So one new colour needs one file per hairstyle, per gender. kRO's 45 styles come as 90 style-and-gender pairs, so 72 new colours would be 6,480 files. Only 77 of those pairs ship a complete set of nine stock colours; the other 13 are missing the file for colour 0, the "no colour" swatch, so anything that works from a complete set skips them and leaves those pairs on the stock nine. There is one shortcut, shared palettes, and it works alongside this patch: read the shared palette section before you generate anything, then pick a route and stay on it.
2 Swatch art: the little square in the picker
Each colour needs three bitmaps under the client's UI texture folder. Like the palette folder, its name is Korean stored as code page bytes and reads as À¯ÀúÀÎÅÍÆäÀ̽º. WARP ships that same folder, with the hairstyle thumbnails in it, at Inputs\HairThumbnails\data\texture\À¯ÀúÀÎÅÍÆäÀ̽º\make_character_ver2\, so copy the path out of there rather than typing it:
color<NN>_off.bmp color<NN>_over.bmp color<NN>_on.bmp
22 by 22 pixels, 24-bit, uncompressed. Colours count from 0, so the nine the client ships are 0 to 8. <NN> is the colour number plus one, written as two digits: colour 0 is color01_*.bmp, colour 9 is color10_*.bmp. A colour with no color<NN>_off.bmp falls back to the first swatch's face rather than failing. That check reads _off alone, so ship all three: a colour that has _off but no _over or _on passes the check and leaves the client with no art for that state, which is the missing bitmap the fallback exists to catch.
data\ folder or be packed into a GRF listed in DATA.INI. It checks both. Keep one copy of each file: a stale duplicate in the other place is the usual reason an edit appears to do nothing.
3 The patch setting
Tick the patch and answer the Hair Colours prompt with the total the picker should offer, stock nine included, anywhere from 9 to 90. It is a total, not a count of new ones: nine stock plus 72 generated is 81.
Pick a multiple of nine. Each page holds nine colours, and a cell past your total is refused: it falls back to the first swatch's face and does nothing when clicked. That worked example, 81, fills nine pages exactly.
Build, launch, and open character creation. At 9 you should see the same nine squares in the same place as before. Above 9 you should see nine squares and a tenth cell, and clicking that cell should turn the row over to the next nine and wrap back to the first page at the end. If the row still shows nine and nothing pages, the patch is applied but still set to 9.
4 The server limit
rAthena clamps hair colour independently of the client, and it clamps by index, not by total. Colours count from 0, so the stock nine are 0 to 8 and rAthena ships the cap at 8. Set it to one below the total you gave the patch: the nine stock colours plus the 72 above make 81 in total, numbered 0 to 80. Raise it in conf/import/battle_conf.txt, never in the main conf:
max_hair_color: 80
Without this a character can pick the colour at creation and then revert to colour 8 the moment they log in, because the map server caps the value on load.
Restart the map server once the line is in. Battle conf is read at startup, so the old cap stays live until you do, and every character logging in keeps getting clamped.
Traps worth knowing
color99_off.bmp, color99_over.bmp and color99_on.bmp. Colour 99 is reserved for it, because its natural number would collide with the first colour on page two.
@haircolor). A replaced stock palette that looks unchanged in creation is not proof it failed: log in and look.
Troubleshooting
¸Ó¸®<style>_<gender>_<colour>.pal (or the shared name, if a shared-palette patch is on), and check that exact file is in the palette folder. Nothing is logged: the guard drops the click silently, so no error names the file for you. If you generated your palettes from kRO's complete sets, the 13 style-and-gender pairs that ship without a colour 0 file are the usual gap.color<NN>_off.bmp for that colour.color<NN>_off/_over/_on.bmp for it, 22 by 22 pixels, 24-bit.max_hair_color on the server is lower than the colour you picked.conf/import/battle_conf.txt and restart the map server.head_<gender>_<colour>.pal (Male & Female) or head<colour>.pal (Unisex) to the palette folder. See shared palettes.Checklist
Check off items as you complete them. Progress is saved in your browser.
Client side
.palfiles for every style, gender and colour you are adding, in the mojibake folder namecolor<NN>_off/_over/_on.bmpfor each colour, 22x22, 24-bit, matching the palettecolor99_*.bmpif you want a proper arrow on the pager cell- The patch ticked, with your total in the Hair Colours prompt
- Tested at 9 first, so you have a control to compare against
Server side
max_hair_colorraised inconf/import/battle_conf.txt- Map server restarted