<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://g1r-mp.com/wiki/index.php?action=history&amp;feed=atom&amp;title=Player_customization</id>
	<title>Player customization - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://g1r-mp.com/wiki/index.php?action=history&amp;feed=atom&amp;title=Player_customization"/>
	<link rel="alternate" type="text/html" href="https://g1r-mp.com/wiki/index.php?title=Player_customization&amp;action=history"/>
	<updated>2026-09-19T06:25:36Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.46.0</generator>
	<entry>
		<id>https://g1r-mp.com/wiki/index.php?title=Player_customization&amp;diff=835&amp;oldid=prev</id>
		<title>QCherry: Document skin color and tattoos available from 0.1.3; identity/armor improvements</title>
		<link rel="alternate" type="text/html" href="https://g1r-mp.com/wiki/index.php?title=Player_customization&amp;diff=835&amp;oldid=prev"/>
		<updated>2026-09-09T02:32:34Z</updated>

		<summary type="html">&lt;p&gt;Document skin color and tattoos available from 0.1.3; identity/armor improvements&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{DISPLAYTITLE:Player customization}}&lt;br /&gt;
&amp;lt;div style=&amp;quot;background:#fff5f5; border:1px solid #d13b3b; border-left:5px solid #d13b3b; color:#111; padding:0.85rem 1rem; margin:0.75rem 0 1rem;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;SKIN COLOR AND TATTOOS — AVAILABLE FROM UPDATE 0.1.3&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The seven skin-color and tattoo functions below are available in G1R:MP 0.1.3 and later. [[setPlayerIdentity]] existed earlier; its head and armor handling is &amp;#039;&amp;#039;&amp;#039;improved from update 0.1.3&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use these &amp;#039;&amp;#039;&amp;#039;server-side Lua&amp;#039;&amp;#039;&amp;#039; functions to combine a named head, a skin-color override and a tattoo preset. Cosmetic changes are independent of armor and gameplay statistics. They work with an equipped armor or an empty armor slot; clothing naturally covers the skin beneath it.&lt;br /&gt;
&lt;br /&gt;
== Function reference ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Function !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| [[setPlayerSkinColor]](&amp;lt;code&amp;gt;playerId, r, g, b&amp;lt;/code&amp;gt;) || Set the skin tint using integer sRGB channels from 0 to 255.&lt;br /&gt;
|-&lt;br /&gt;
| [[getPlayerSkinColor]](&amp;lt;code&amp;gt;playerId&amp;lt;/code&amp;gt;) || Read &amp;lt;code&amp;gt;{r = ..., g = ..., b = ...}&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; when unset or unavailable.&lt;br /&gt;
|-&lt;br /&gt;
| [[resetPlayerSkinColor]](&amp;lt;code&amp;gt;playerId&amp;lt;/code&amp;gt;) || Restore native skin color without changing the tattoo override.&lt;br /&gt;
|-&lt;br /&gt;
| [[setPlayerTattoo]](&amp;lt;code&amp;gt;playerId, presetKey&amp;lt;/code&amp;gt;) || Apply a validated tattoo preset, or &amp;lt;code&amp;gt;&amp;quot;none&amp;quot;&amp;lt;/code&amp;gt; to explicitly remove tattoos.&lt;br /&gt;
|-&lt;br /&gt;
| [[getPlayerTattoo]](&amp;lt;code&amp;gt;playerId&amp;lt;/code&amp;gt;) || Read the canonical preset key, or &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; when unset or unavailable.&lt;br /&gt;
|-&lt;br /&gt;
| [[resetPlayerTattoo]](&amp;lt;code&amp;gt;playerId&amp;lt;/code&amp;gt;) || Restore native tattoo defaults without changing the skin-color override.&lt;br /&gt;
|-&lt;br /&gt;
| [[getPlayerTattooNames]]() || Enumerate all 12 accepted keys; see [[Player tattoo catalog]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
All seven have equivalent PascalCase aliases, for example &amp;lt;code&amp;gt;SetPlayerSkinColor&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;GetPlayerTattooNames&amp;lt;/code&amp;gt;. These aliases are the same APIs, not separate functions in the catalog.&lt;br /&gt;
&lt;br /&gt;
=== Identity: existing API, improved in 0.1.3 ===&lt;br /&gt;
* [[setPlayerIdentity]](&amp;lt;code&amp;gt;playerId, &amp;quot;gorn&amp;quot;&amp;lt;/code&amp;gt;) selects a named identity. Use &amp;lt;code&amp;gt;&amp;quot;default&amp;quot;&amp;lt;/code&amp;gt; to restore the native Nameless Hero identity.&lt;br /&gt;
* [[getPlayerIdentity]](&amp;lt;code&amp;gt;playerId&amp;lt;/code&amp;gt;) reads the current key; [[getPlayerIdentityNames]]() lists supported identities.&lt;br /&gt;
* Identity changes preserve equipped armor and the independent skin-color/tattoo overrides.&lt;br /&gt;
* Named identities use a head-only visual layer while retaining the game-owned player body and equipment. This is &amp;#039;&amp;#039;&amp;#039;not&amp;#039;&amp;#039;&amp;#039; an NPC&amp;#039;s complete body/outfit replacement and is not a body-shape or morph API.&lt;br /&gt;
* Update 0.1.3 corrects head publication and material-mask restoration during identity/armor changes, including meshes with more than 64 material slots. The changes address overlapping heads and missing body parts during visual rebuilds.&lt;br /&gt;
&lt;br /&gt;
See [[Player identity catalog]] for accepted names. The deprecated [[setPlayerBody]], [[setPlayerFace]] and [[setPlayerHead]] are not substitutes for the supported identity API. The older [[setPlayerSkin]] channel is separate from these RGB and tattoo overrides.&lt;br /&gt;
&lt;br /&gt;
== Example ==&lt;br /&gt;
Run this inside an authorized server handler after the player is connected and ready. The API itself does not grant or check a gamemode-specific administrator permission.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot; line&amp;gt;&lt;br /&gt;
-- playerId is the validated target of your authorized handler.&lt;br /&gt;
if not setPlayerIdentity(playerId, &amp;quot;gorn&amp;quot;) then&lt;br /&gt;
    outputDebugString(&amp;quot;Identity was rejected&amp;quot;)&lt;br /&gt;
    return&lt;br /&gt;
end&lt;br /&gt;
if not setPlayerSkinColor(playerId, 180, 140, 110) then&lt;br /&gt;
    outputDebugString(&amp;quot;Skin color was rejected&amp;quot;)&lt;br /&gt;
    return&lt;br /&gt;
end&lt;br /&gt;
if not setPlayerTattoo(playerId, &amp;quot;lester&amp;quot;) then&lt;br /&gt;
    outputDebugString(&amp;quot;Tattoo was rejected&amp;quot;)&lt;br /&gt;
    return&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local color = getPlayerSkinColor(playerId)&lt;br /&gt;
if color then&lt;br /&gt;
    outputDebugString(&amp;quot;RGB: &amp;quot; .. color.r .. &amp;quot;, &amp;quot; .. color.g .. &amp;quot;, &amp;quot; .. color.b)&lt;br /&gt;
end&lt;br /&gt;
outputDebugString(&amp;quot;Tattoo: &amp;quot; .. tostring(getPlayerTattoo(playerId)))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each setter is independent; this sequence is not one atomic multi-function transaction. Handle a rejected operation according to the resource&amp;#039;s own policy.&lt;br /&gt;
&lt;br /&gt;
== Reset versus removal ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
-- Remove tattoos explicitly, even if the native model normally has them:&lt;br /&gt;
setPlayerTattoo(playerId, &amp;quot;none&amp;quot;)&lt;br /&gt;
-- getPlayerTattoo(playerId) now returns &amp;quot;none&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
-- Restore the model&amp;#039;s native tattoo defaults instead:&lt;br /&gt;
resetPlayerTattoo(playerId)&lt;br /&gt;
-- getPlayerTattoo(playerId) now returns false.&lt;br /&gt;
&lt;br /&gt;
-- Reset only skin color; this does not change tattoos or identity:&lt;br /&gt;
resetPlayerSkinColor(playerId)&lt;br /&gt;
&lt;br /&gt;
-- Reset only identity; this does not clear color/tattoo overrides:&lt;br /&gt;
setPlayerIdentity(playerId, &amp;quot;default&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Tattoo reset does not necessarily remove tattoos.&amp;#039;&amp;#039;&amp;#039; It disables the custom override and restores the native defaults. A color getter returning &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; is not black RGB; it means there is no active override, or the player is unavailable.&lt;br /&gt;
&lt;br /&gt;
== Validation and synchronization ==&lt;br /&gt;
* RGB values must be finite integers in the range 0–255. Invalid values are rejected rather than clamped. They are interpreted as sRGB and converted for the native material; final appearance also depends on skin textures, supported material regions and lighting.&lt;br /&gt;
* Tattoo keys are case-insensitive and returned in canonical lowercase. Use the exact catalog key without extra whitespace. Unknown keys and arbitrary texture paths are rejected. There is no custom texture upload API.&lt;br /&gt;
* Setters return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; when the server accepts the authoritative state, not when every client has finished rendering it. Getters read that authoritative state.&lt;br /&gt;
* State is reliably sent to the owner and relevant observers, replayed on late join/relevance entry, and reapplied after supported visual rebuilds. These cosmetic functions do not change armor, inventory, HP, mana or progression statistics.&lt;br /&gt;
* Color and tattoos are independent. Their resets do not change the other override. Test the exposed face, neck, arms, hands, torso and legs used by your character/armor combinations, including another client&amp;#039;s view.&lt;br /&gt;
* A custom resource must implement authorization and persistence. The bundled GothicRP resource persists both overrides in its existing &amp;lt;code&amp;gt;appearance_json&amp;lt;/code&amp;gt; data. This persistence is a GothicRP feature, not automatic database storage by each Lua API call.&lt;br /&gt;
&lt;br /&gt;
== Bundled GothicRP commands ==&lt;br /&gt;
These are resource commands, &amp;#039;&amp;#039;&amp;#039;not additional core Lua functions&amp;#039;&amp;#039;&amp;#039;. They require authentication, &amp;lt;code&amp;gt;admin.players&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;RP.Config.testTools.enabled = true&amp;lt;/code&amp;gt;. An omitted target means yourself.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Command !! Action&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/identity gorn [player name or ID]&amp;lt;/code&amp;gt; || Change identity; &amp;lt;code&amp;gt;/identity&amp;lt;/code&amp;gt; lists choices.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/skincolor 180 140 110 [player name or ID]&amp;lt;/code&amp;gt; || Set skin color.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/skincolor reset [player name or ID]&amp;lt;/code&amp;gt; || Restore native color.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/tattoo lester [player name or ID]&amp;lt;/code&amp;gt; || Set a tattoo preset.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/tattoo none [player name or ID]&amp;lt;/code&amp;gt; || Remove tattoos explicitly.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/tattoo reset [player name or ID]&amp;lt;/code&amp;gt; || Restore native tattoo defaults.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For optional manual QA, &amp;lt;code&amp;gt;/looktest start&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;/looktest all&amp;lt;/code&amp;gt; saves the cosmetic baseline and starts a sequence; &amp;lt;code&amp;gt;/looktest next&amp;lt;/code&amp;gt; advances, and &amp;lt;code&amp;gt;/looktest stop&amp;lt;/code&amp;gt; restores it. End an active test before making normal cosmetic edits. The test never equips armor or changes HP/mana; manual armor changes during it are not undone by stopping. &amp;lt;code&amp;gt;/looktest armor&amp;lt;/code&amp;gt; only reads live server equipment and resources.&lt;br /&gt;
&lt;br /&gt;
== Related pages ==&lt;br /&gt;
* [[Player tattoo catalog]]&lt;br /&gt;
* [[Player identity catalog]]&lt;br /&gt;
* [[:Category:Appearance Functions]]&lt;br /&gt;
* [[Lua API catalogs]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Lua Tutorials]]&lt;br /&gt;
[[Category:Appearance Functions]]&lt;/div&gt;</summary>
		<author><name>QCherry</name></author>
	</entry>
</feed>