"Modding rules[1] state that DLC assets should not be made available via mods to users not owning that DLC. Thus DLC assets can be referenced in a custom portraits*.gfx file, so that the DLC is required to use the mod. But the sprites themselves cannot be added directly to the mod." |
Portraits are built by superposing layers of basic elements: background, generic head, facial elements (cheeks, hair, nose, ...), clothes, headgear, etc.
Each of these basic elements come with multiple variations or frames.
The choice of frame is either based on:
Children are an exception as they are created using a single image, hence children look similar.
Characteristics
There are two kind of characteristics: DNA and properties. Both are strings of letters (and possibly zeros for properties). They can be seen in-game by using console command charinfo
.
DNA
DNA is a string of 11 letters inherited from the parents and doesn't change after birth.
For historical characters, their DNA string can be set in character history:
125501 = { name="Temujin" # AKA: Genghis Khan dynasty=11100 dna="bfimkolbecc" (...) }
Otherwise randomly generated characters will get random DNA strings, which are persisted in the game saves.
Index | Used for |
---|---|
d0 | Neck |
d1 | Chin |
d2 | Mouth |
d3 | Nose |
d4 | Cheeks |
d5 | Unused |
d6 | Eyes |
d7 | Ears |
d8 | Hair Color |
d9 | Eye Color |
d10 | Unused |
So Genghis Khan's dna = "bfimkolbecc"
means:
- Frame b for the neck (2nd frame in mongol_male_neck_1.dds)
- Frame f for the chin (6th frame in mongol_male_chin_1.dds)
- Frame i for the mouth (9th frame in mongol_male_mouth_1.dds)
- Frame m for the nose (13th frame in mongol_male_nose_1.dds)
- etc...
In case there are less frames than the index of the letter in alphabet, it wraps around. For instance, for chins there are usually 4 frames, so a = 1st frame and e = 1st frame as well.
Properties
Properties are a string of up to 14 letters (in vanilla). If the string is shorter, zeros will be added at the end.
Only hair (p1) and beards (p4) can be changed in-game via the Customization Pack, the other property values are derived from portrait_properties.txt
file.
- p0: Background
- p1: Hair
- p2: Base Head
- p3: Clothes
- p4: Beard
- p5: Headgear
- p6: Imprisoned
- p7: Scars tier I
- p8: Red Dots
- p9: Boils
- p10: Blinded
- p11: Player
- p12: Mask
- p13: Eyepatch
- p14: Chinese makeup
- p15: Chinese makeup 2
- p16: Chinese empress jewelry
- p17: Immortality
- p18: Special crowns behind
- p19: Special crowns
- p20: Freckles
- p21: Physique
- p22: Pale
- p23: Black eye
- p24: Harelip
- p25: Scars tier II
- p26: Scars tier III
- p27: Blood splatter
- p28: Tattoos
- p29: Warpaint
- p30: Demon Child
- p31: Frankish culture male overlayer
- p32: Frankish culture female overlayer
- p33: Frankish culture female underlayer and hair
It is possible to add new properties with the following:
- Define a sprite in a .gfx file, for instance GFX_custom
spriteType = { name = "GFX_custom" texturefile = "gfx\\characters\\shared\\new_property.dds" noOfFrames = 2 norefcount = yes can_be_lowres = yes }
- Configure p18 in portrait_properties.txt (the number of properties is determined dynamically from there):
# p18 18 = { 0 = { factor = 50 } 1 = { factor = 50 } }
- Add a layer in portraits.gfx:
"GFX_custom:p18"
Rendering
Based on player's experimentations, here is a description of how the rendering of portraits works in-game. Note that part of the logic has also been re-implemented in Portrait Builder tool, for an out-of-game rendering.
Children
For child portraits:
- Look directly for a spriteType entry in /interface/portraits/* with name PORTRAIT_<culturegfx>_child_<sex>, where:
- <culturegfx> is the graphical_culture defined for the character culture or culture group
- <sex> is either male or female
Feudal
The game renders feudal adult portraits as follows:
- Look for a portraitType entry in /interface/portraits/portrait.gfx (or any other portraitType under /interface/*) with name PORTRAIT_<culturegfx>_<sex><_period><age>, where:
- <culturegfx> is the graphical_culture defined for the character culture or culture group (common/cultures/00_cultures.txt)
- <sex> is either male or female
- <age> is an integer: 0 for young (16 <= age < 30), 1 for middle age (30 <= age < 50), 2 for old age (age >= 50)
- <_period> is either _early if year is before 950, _late if year is after 1250, or empty otherwise (note: actual dates are defines EARLY_PORTRAIT_AND_UNIT_BEFORE_YEAR and LATE_PORTRAIT_AND_UNIT_AFTER_YEAR)
- In case no portraitType entry matches, try some defaulting: no date, no age, fallback ethnicities in the graphical_cultures list, ethnicity from parent culture group, or westerngfx in last resort.
- If a portraitType entry matches, apply the layers in order. For each layer defined as GFX_TYPE:[d|p]INDEX:
- Look for GFX_TYPE in spriteTypes (/interface/portraits/portrait_sprites.gfx or any other spriteType under /interface/*) and read the number of frames N.
- Resolve the frame to use:
- If letter is d, look for the letter in character DNA at INDEX position, and convert the letter to a number (modulo N)
- If letter is p, resolve the property for value INDEX, defined in /interface/portrait_properties.txt. The choice is made based on a weighted random, but the first factor that evaluates to >= 100 will be automatically chosen.
- Define a skin tone for the ethnicity in common/graphicalculturetypes/graphicalculturetype.txt, so that it can "manage" mixed-race children.
Theocracy
The rendering is the same as feudal characters, except for headgear and clothing layers:
- Look for character religion definition and read the frame index directly there (portrait_properties.txt is not used):
- religious_clothing_head: index of the frame to use for the religious head
- religious_clothing_priest: index of the frame to use for other priests
- Use frame at index inside hardcoded sprites GFX_religious_male_clothes, GFX_religious_male_headgear, etc. instead of the sprites defined in portrait.gfx
Republic
The rendering is the same as feudal characters, except for headgear and clothing layers. It uses hardcoded sprites GFX_merchant_male_clothes, GFX_merchant_male_headgear, etc. instead of the sprites defined in portrait.gfx
Clothing override
With patch 2.7 a new mechanism was added to override the clothing layers based on rules.
The only examples in vanilla are from \interface\portraits\society_clothes.gfx
in dlc070.zip
The general structure is the following:
portraitType = { name = "PORTRAIT_<override_type>_clothing_male" weight = { additive_modifier = { value = 10000 # Conditions (in portrait scope) for modifier to apply } } layer = { # GFX_empty can be used to disable a layer "GFX_xxx_male_clothing_behind:c0" "GFX_xxx_male_headgear_behind:c1" "GFX_xxx_male_clothing_front:c2" "GFX_xxx_male_headgear_mid:c3" "GFX_xxx_male_clothing_infront:c4" "GFX_xxx_male_headgear_front:c5" } allow_property_values = { <property_index> = { <frame_index> = { # Conditions (in portrait scope) for frame to be used } } } }
Notes:
- c0 to c7 are the "culture indexes" that reference clothing layers (normally driven by properties p3 and p5) to be overridden from the base portraitType:
- c0 = clothes behind
- c1 = headgear behind
- c2 = clothes
- c3 = headgear mid
- c4 = clothes infront
- c5 = headgear
- c6 = headgear behind hairlayer
- c7 = headgear hairlayer
Note: extra culture index cannot be added dynamically by modders.
allow_property_values
block can be used in a similar way to portrait_properties.txt to select the frames for p3 (clothes) and p5 (headgear) in the overridden sprites of thelayer
block.
Portrait scope
A new scope is used, which is a sort of limited version of a character scope, with conditions prefixed with portrait_
.
Condition | Type | Used in vanilla | Description | Example |
---|---|---|---|---|
portrait_age | child/oldage | ✓ | Age of character compared to a portrait threshold (child, young, middle or old). As the thresholds are configurable, the numeric values are not directly hardcoded here. | portrait_age > child
|
portrait_is_female | bool | ✓ | Whether character is a female | portrait_is_female = yes
|
portrait_has_trait | trait | ✓ | Whether character has the trait | portrait_has_trait = vaishnavist_hindu
|
portrait_religion | religion | X | [Seen in the .exe - to be tested] | |
portrait_culture | culture | ✓ | Character culture | portrait_culture = greek
|
portrait_culture_group | culture_group | ✓ | portrait_culture_group = latin
| |
portrait_gfx_culture | ? | X | [Seen in the .exe - to be tested] | |
portrait_government | government | X | Whether character has the specified government. Seems to only work on landed characters. | |
portrait_tier | tier | ✓ | portrait_tier = king
| |
portrait_title_tier | ? | X | [Seen in the .exe - to be tested] | |
portrait_society | society | ✓ | portrait_society = monastic_order_benedictine
| |
portrait_society_rank | int | ✓ | Character rank if member of a society | portrait_society_rank = 1
|
portrait_clothing | bool | ✓ | Warning: portrait_clothing = no appears to be broken.
|
portrait_clothing = yes
|
portrait_offmap | offmap_power | ✓ | Whether the character rules the given offmap. | portrait_offmap = offmap_china
|
portrait_is_patrician | bool | X | Whether the character is in a merchant republic and their employer patrician or has a republic government form. | portrait_is_patrician = yes
|
portrait_in_command | bool | X | Whether the character is in command and leading any troops. | portrait_in_command = yes
|
Custom ethnicities
It is possible to create new ethnicities by creating new assets and/or mixing existing vanilla or DLC assets in portraitTypes layers.
For instance a customgfx ethnicity with norsegfx faces and byzantinegfx clothes.
New assets
- 主條目:Graphics modding
If creating image sprites from scratch, you need to:
- In folder gfx/characters/ create 2 folders (gothic_male & gothic_female) to store the sprites (ex: gothic_male_clothes.dds with 12 frames)
- In folder interface/ create a file portraits_gothic_spritetypes.gfx, with one entry per image sprite:
spriteTypes = { spriteType = { name = "GFX_gothic_male_clothes" texturefile = "gfx\\characters\\gothic_male\\gothic_male_clothes.dds" noOfFrames = 12 norefcount = yes can_be_lowres = yes } ... }
DLC assets
Reusing DLC assets is easier than creating new one, but because the DLC assets cannot themselves be bundled into the mod,[2] users who don't own the DLC(s) containing these assets (ex: the Norse Portraits DLC) will see gothicgfx portraits with clothes but no heads.
The reason is that, as soon as some portraitTypes entry for gothicgfx are defined, the game will render them, even if the layers refer to unknown assets and will not show up properly The fallback to another ethnicity in graphical_cultures list (or default westerngfx) only happens if no portraitType entry is found at all !
There are some solutions to this problem:
- Bundling the portraitTypes definitions for that ethnicity outside the main mod, in a sub-mod. This way players:
- can activate the sub-mod ONLY if they have the required DLC(s).
- will see the fallback ethnicities if they don't have the required DLC(s)
- Providing fallback portraitTypes for that ethnicities that do not use DLC assets. Players have to download those extra fallback portraitTypes and use the ones for which they don't have the required DLC.
New ethnicity
To define a new gothicgfx ethnicity, here are the steps:
- In main mod folder common/graphicalculturetypes/ add a new .txt file with the line:
gothicgfx = { skin_tone = 0 }
- In main mod common/cultures/00_cultures.txt file, modify or add a new gothic culture with the following lines
graphical_cultures = { gothicgfx occitangfx }
Note: if using sub-mods, it is important that the last culturegfx in the list be one of the vanilla base types (occitangfx, muslimgfx, byzantinegfx, westerngfx). In case it is westerngfx, it can be omitted as it is the default, or used as 3 layers of ethnicities. If using fallback portraitTypes, this is not required.
- In sub-mod (or main mod, depending on the solution chosen) folder interface/ add a new file portraits_gothic.gfx, with the following structure (copied from another vanilla portraits.gfx):
spriteTypes = { spriteType = { name = "PORTRAIT_gothicgfx_child_male" } spriteType = { name = "PORTRAIT_gothicgfx_child_female" } portraitType = { name = "PORTRAIT_gothicgfx_male" } portraitType = { name = "PORTRAIT_gothicgfx_male1" } portraitType = { name = "PORTRAIT_gothicgfx_male2" } portraitType = { name = "PORTRAIT_gothicgfx_female" } portraitType = { name = "PORTRAIT_gothicgfx_female1" } portraitType = { name = "PORTRAIT_gothicgfx_female2" } }
- For each portraitType, reference the correct spriteType for each layer (custom, vanilla or DLC spriteType):
portraitType = { name = "PORTRAIT_gothicgfx_female" effectFile = "gfx/FX/portrait.lua" layer = { # GFX_TYPE:[d|p]INDEX:COLOR_LINK:DONT_REFRESH_IF_VALID:CULTURE_INDEX "GFX_character_background:p0" "GFX_byzantine_female_clothes_behind:p3:c0" "GFX_byzantine_female_headgear_behind:p5:c1" "GFX_norse_female_hair_behind:p1:h:y" "GFX_norse_female_base:p2" "GFX_norse_female_neck:d0" "GFX_norse_female_mouth:d2" "GFX_norse_female_nose:d3" "GFX_norse_female_chin:d1" "GFX_norse_female_cheeks:d4" "GFX_norse_female_eyes:d6" "GFX_norse_female_eyes2:d6:e" "GFX_character_scars:p7:y" "GFX_character_reddots:p8" "GFX_character_boils:p9" "GFX_character_blinded_eyes:p10" "GFX_norse_female_ear:d7" "GFX_byzantine_female_clothes:p3:c2" "GFX_empty:p5:c3" "GFX_norse_female_hair:p1:h:y" "GFX_empty:p3:c4" "GFX_byzantine_female_headgear:p5:c5" "GFX_character_imprisoned:p6" "GFX_player_overlay:p11" }
Static portraits
To display static pre-rendered portraits, there are a few techniques:
Misc layer
This technique has become obsolete with patch 2.6, given that new properties layers can now be modded, rather than modifying an existing layer. |
Using a miscellaneous layer (for instance blinded_eyes) and add frames for pre-rendered portraits:[3]
- Move the layer to the end of layer list in portraits.gfx
- Increase the number of frames in portrait_sprites.gfx (ex: GFX_character_blinded_eyes)
- Edit sprite (ex: blinded_eyes.dds) to add the extra frame(s)
- Add an entry in portrait_properties.txt for each frame inside the property corresponding to the layer (ex: p10 blinded), with a trigger based on unique trait or character flag:
# p10 blinded 10 = { 0 = { factor = 100 modifier = { factor = 0 trait = blinded } modifier = { factor = 0 #Either a character flag or a unique trait. } } 1 = { factor = 100 modifier = { factor = 0 NOT = { trait = blinded } } modifier = { factor = 0 #Either a character flag or a unique trait. } } 2 = { factor = 100 modifier = { factor = 0 NOT = { #Either a character flag or a unique trait. } } } }
Occluded flag
Using occluded = yes in character history; this is used for Muhammad (The Prophet). Big limitation is that everyone with occluded = yes will have same portrait. It uses a single frame texture with hardcoded name Muhammad.tga:
spriteType = { name = "GFX_Muhammad" texturefile = "gfx\\characters\\Muhammad.tga" noOfFrames = 1 norefcount = yes }
Custom ethnicity
Using a custom ethnicity, and setting it in character history, or via event using set_graphical_culture
command.
Because the commands requires a culture as argument, a custom culture definition must be added too.
Also the ethnicity being randomly inherited from one of the parents at birth, some on_action events may be needed to control things.
The steps are:
- Create a custom culture in common/cultures/
special = { graphical_cultures = { specialgfx } ... }
- Define a portrait in interface/ for the custom ethnicity, with the fixed frame layer based on p2 property
spriteType = { name = "GFX_special" texturefile = "gfx\\characters\\special.tga" noOfFrames = 1 norefcount = yes } portraitType = { name = "PORTRAIT_specialgfx_male" effectFile = "gfx/FX/portrait.lua" layer = { # GFX_TYPE:[d|p]INDEX:COLOR_LINK:DONT_REFRESH_IF_VALID:CULTURE_INDEX "GFX_character_background:p0" "GFX_special:p2" "GFX_character_imprisoned:p6" } hair_color = { { 10 10 10 } { 50 50 50 } { 255 255 255 } } #Must be included. eye_color = { { 255 255 255} } # Leaving these out will crash the game. } portraitType = { name = "PORTRAIT_specialgfx_female" ... #The rest is same as above. Both *_male and *_female portraitType are required, even for static portraits. }
- Use
set_graphical_culture = special
command andgraphical_culture = specialgfx
condition in events.
External links
See also
References
歷史 | 角色 • 家族 • 省份 • 頭銜 • 劇本 |
腳本 | 指令 • 條件 • 作用域 • 修正 • 事件 • 決議 |
常規 | 定義 • 遊戲規則 • 另類開局 • 宗教 • 文化 • 政體 • 特質 • 血脈 • 科技 • 法律 • 建築 • 宣戰理由 • 朝貢國 • 單位 • 目標 • 疾病 • 死亡 • 榮譽頭銜 • 社團 • 寶物 • 地圖外政權 • 內閣成員 • 貿易路線 • 繼承 • 奇觀 • 稱號 |
圖像/音效/本地化 | 地圖 • 圖形 • 盾徽 • 肖像 • 介面 • 小地圖 • 音樂 • 本地化 |
其他 | 故障排除 • 驗證器 • 控制台指令 • 編輯遊戲存檔 • Steam創意工坊 • EU4轉檔器模組製作 |