lockeslylcrit Posted October 7, 2019 Posted October 7, 2019 First and foremost, you need the right tools to make a static portrait. You will need: Notepad++ (or any other plain text editor that isn't trash) paint.net (or any other graphic editing program that supports the DDS file format) A portrait template (Dark World Fantasy includes two templates for you to use) Step 1: Making the graphical portrait For making the actual portrait using paint.net, I have already written a step-by-step tutorial on this. You can view it here. Step 2: Making the interface file Now let's get into the meat and bones of static portraits. First, you need to define your graphic file so the code engine will properly recognize it. If you don't do this, then the game will think the graphic file is missing. Open up your text editor and create a new file. If using Notepad++, go to Encoding and select Encode as ANSI. No other encoding is accepted by CK2's coding engine. Save this blank file in your mod's interface folder (e.g.: My Documents/Crusader Kings II/mod/[yourmodnamehere]/interface/) as a plain text file with the .gfx extension. (e.g.: portraitfile.gfx). Now paste in this: spriteTypes = { spriteType = { name = "XXX" texturefile = "gfx/static_portraits/XXX" noOfFrames = XXX } } name = "XXX" is going to be any unique name you want to give the file. For this tutorial, we're going to go with the Dark World Fantasy kitsunes. The line will be name = "GFX_portrait_dwf_kitsune" texturefile = "XXX" is where your graphic file resides. As long as it is in the /gfx/ folder, it can be named anything or put anywhere. For this example, we're going to assume you created a /static_portrait/ subfolder and put your dds file in there. The line will be texturefile = "gfx/static_portraits/DWF_Races_Kitsune.dds" noOfFrames = XXX is how many 152x152 frames you have in the graphic file. Take your portrait width and divide by 152, and that's the number you should put in. If you divide by 152 and get something that isn't a whole number, you need to redo your graphic file until you have pixel-perfect 152x152 frames. For this example, we're going with 27, so the line will be noOfFrames = 27. I don't know the maximum you can have, but the standard on LL is 27 maximum frames per file, but you can certainly go lower than this to a minimum of a single portrait. Step 3: Making the traits Portraits wont show up unless they are tied to a condition. For these portraits, we're going to tie them to traits. Create a new plain text file, ANSI coding, and save it into your /common/traits/ folder with the standard .txt file format. (e.g.: My Documents/Crusader Kings II/mod/[yourmodnamehere]/common/traits/portraitfiles.txt ) Next, paste these lines in: dwf_kitsune_portrait1 = { hidden_from_others = yes random = no customizer = no } dwf_kitsune_portrait1 is the code's name of the trait. You can change this to whatever you want, as long as it is unique. For this tutorial, we're going to continue using DWF kitsunes as the example. hidden_from_others = yes makes the trait hidden from view when someone else views that character, but it will be visible when that character views themselves. Change to hidden = yes if you want the portrait trait to be completely hidden from view. Note that if you use hidden_from_others, then you will need to make a trait graphic and then define said graphic in an interface file similar to Step 2, but that's a tutorial for another time. random = no prevents the trait from appearing on randomly generated characters in the game, to allow full control over who gets the portrait. customizer = no prevents the trait from being selected in the Ruler Designer. If you have multiple portraits, you will need to copy and paste (and edit) the above multiple times, once for each portrait. Step 4: Making the interface file, part deux Now we come to the part of the tutorial everyone hates: How to properly set up the portraits in an interface file. You've defined the graphic file, but now you need to tell the code when to use that graphic file and exactly which portrait you want to use. Once again, make a new plain text file, ANSI encoding, and save it somewhere in your /interface/ folder with the .gfx file format. For this tutorial, we'll be making a /portraits/ subfolder and putting it there. Now paste in the following: spriteTypes = { portraitType = { name = "PORTRAIT_dwf_kitsune" effectFile = "gfx/FX/portrait.lua" weight = { additive_modifier = { value = 1000000 portrait_clothing = yes OR = { portrait_has_trait = dwf_kitsune_portrait1 portrait_has_trait = dwf_kitsune_portrait2 portrait_has_trait = dwf_kitsune_portrait3 portrait_has_trait = dwf_kitsune_portrait4 portrait_has_trait = dwf_kitsune_portrait5 portrait_has_trait = dwf_kitsune_portrait6 portrait_has_trait = dwf_kitsune_portrait7 portrait_has_trait = dwf_kitsune_portrait8 portrait_has_trait = dwf_kitsune_portrait9 portrait_has_trait = dwf_kitsune_portrait10 portrait_has_trait = dwf_kitsune_portrait11 portrait_has_trait = dwf_kitsune_portrait12 portrait_has_trait = dwf_kitsune_portrait13 portrait_has_trait = dwf_kitsune_portrait14 portrait_has_trait = dwf_kitsune_portrait15 portrait_has_trait = dwf_kitsune_portrait16 portrait_has_trait = dwf_kitsune_portrait17 portrait_has_trait = dwf_kitsune_portrait18 portrait_has_trait = dwf_kitsune_portrait19 portrait_has_trait = dwf_kitsune_portrait20 portrait_has_trait = dwf_kitsune_portrait21 portrait_has_trait = dwf_kitsune_portrait22 portrait_has_trait = dwf_kitsune_portrait23 portrait_has_trait = dwf_kitsune_portrait24 portrait_has_trait = dwf_kitsune_portrait25 portrait_has_trait = dwf_kitsune_portrait26 } } } layer = { "GFX_empty:c0" "GFX_empty:c2" "GFX_empty:c3" "GFX_empty:c1" "GFX_empty:c4" "GFX_empty:c6" "GFX_empty:c7" "GFX_empty:p1:h:y" "GFX_empty:p6" "GFX_portrait_dwf_kitsune:c5" } allow_property_values = { 1 = { 0 = { always = yes } } 19 = { 0 = { always = yes } } 33 = { 0 = { always = yes } } 34 = { 0 = { always = yes } } 35 = { 0 = { always = yes } } 36 = { 0 = { always = yes } } 6 = { 0 = { always = yes } } 5 = { 0 = { always = no } 1 = { portrait_has_trait = dwf_kitsune_portrait1 } 2 = { portrait_has_trait = dwf_kitsune_portrait2 } 3 = { portrait_has_trait = dwf_kitsune_portrait3 } 4 = { portrait_has_trait = dwf_kitsune_portrait4 } 5 = { portrait_has_trait = dwf_kitsune_portrait5 } 6 = { portrait_has_trait = dwf_kitsune_portrait6 } 7 = { portrait_has_trait = dwf_kitsune_portrait7 } 8 = { portrait_has_trait = dwf_kitsune_portrait8 } 9 = { portrait_has_trait = dwf_kitsune_portrait9 } 10 = { portrait_has_trait = dwf_kitsune_portrait10 } 11 = { portrait_has_trait = dwf_kitsune_portrait11 } 12 = { portrait_has_trait = dwf_kitsune_portrait12 } 13 = { portrait_has_trait = dwf_kitsune_portrait13 } 14 = { portrait_has_trait = dwf_kitsune_portrait14 } 15 = { portrait_has_trait = dwf_kitsune_portrait15 } 16 = { portrait_has_trait = dwf_kitsune_portrait16 } 17 = { portrait_has_trait = dwf_kitsune_portrait17 } 18 = { portrait_has_trait = dwf_kitsune_portrait18 } 19 = { portrait_has_trait = dwf_kitsune_portrait19 } 20 = { portrait_has_trait = dwf_kitsune_portrait20 } 21 = { portrait_has_trait = dwf_kitsune_portrait21 } 22 = { portrait_has_trait = dwf_kitsune_portrait22 } 23 = { portrait_has_trait = dwf_kitsune_portrait23 } 24 = { portrait_has_trait = dwf_kitsune_portrait24 } 25 = { portrait_has_trait = dwf_kitsune_portrait25 } 26 = { portrait_has_trait = dwf_kitsune_portrait26 } } } } } This is a big one, so sit back while I break it all down for you. name = "PORTRAIT_dwf_kitsune" effectFile = "gfx/FX/portrait.lua" name is a unique name you give to this block of code. It can be anything as long as it doesn't conflict with any other unique names you've given already. effectFile is telling the game to use the portrait code instead of something like a trait or event picture. weight = { additive_modifier = { value = 1000000 portrait_clothing = yes OR = { portrait_has_trait = dwf_kitsune_portrait1 portrait_has_trait = dwf_kitsune_portrait2 portrait_has_trait = dwf_kitsune_portrait3 portrait_has_trait = dwf_kitsune_portrait4 portrait_has_trait = dwf_kitsune_portrait5 portrait_has_trait = dwf_kitsune_portrait6 portrait_has_trait = dwf_kitsune_portrait7 portrait_has_trait = dwf_kitsune_portrait8 portrait_has_trait = dwf_kitsune_portrait9 portrait_has_trait = dwf_kitsune_portrait10 portrait_has_trait = dwf_kitsune_portrait11 portrait_has_trait = dwf_kitsune_portrait12 portrait_has_trait = dwf_kitsune_portrait13 portrait_has_trait = dwf_kitsune_portrait14 portrait_has_trait = dwf_kitsune_portrait15 portrait_has_trait = dwf_kitsune_portrait16 portrait_has_trait = dwf_kitsune_portrait17 portrait_has_trait = dwf_kitsune_portrait18 portrait_has_trait = dwf_kitsune_portrait19 portrait_has_trait = dwf_kitsune_portrait20 portrait_has_trait = dwf_kitsune_portrait21 portrait_has_trait = dwf_kitsune_portrait22 portrait_has_trait = dwf_kitsune_portrait23 portrait_has_trait = dwf_kitsune_portrait24 portrait_has_trait = dwf_kitsune_portrait25 portrait_has_trait = dwf_kitsune_portrait26 } } } Every portrait needs a weight. If A is weighed heavier than B, A will always be chosen above B. additive_modifier is set to 100000 to ensure that nothing in the vanilla code will ever have a higher priority than this portrait block. portrait_clothing ensures that this weight is applied if the portraits are clothing (we'll get into this later). portrait_has_trait are every single trait you made that correspond to the graphic file. Breaking this down, this portrait block will have a priority of 100000 if it's clothing and the character has at least one of the traits you made. layer = { "GFX_empty:c0" "GFX_empty:c2" "GFX_empty:c3" "GFX_empty:c1" "GFX_empty:c4" "GFX_empty:c6" "GFX_empty:c7" "GFX_empty:p1:h:y" "GFX_empty:p6" "GFX_portrait_dwf_kitsune:c5" } A portrait is broken down into layers. Hair, clothing, base figure, ears, etc. A vanilla dynamic portrait will have this block all filled up, and the position of the lines are vital. Layers that go into the background (base figure, ears, etc) will be higher up in the block, while the layers that belong in the foreground (facial hair, clothes, etc) are lower down the list. Anything that is defined as GFX_empty will not appear. The c0/c2/c3/etc parts? The c represents clothing, and we only want the clothing layer 5 to appear, so we are whiting out the other clothing layers. p1 is hair and p6 is imprisoned, both of which we want whited out. The only layer that remains is c5, which is what we are using for the portraits. In this line, you will put in the unique name you gave to your portrait in the interface file in Step 2. allow_property_values = { 1 = { 0 = { always = yes } } 19 = { 0 = { always = yes } } 33 = { 0 = { always = yes } } 34 = { 0 = { always = yes } } 35 = { 0 = { always = yes } } 36 = { 0 = { always = yes } } 6 = { 0 = { always = yes } } 5 = { 0 = { always = no } 1 = { portrait_has_trait = dwf_kitsune_portrait1 } 2 = { portrait_has_trait = dwf_kitsune_portrait2 } 3 = { portrait_has_trait = dwf_kitsune_portrait3 } 4 = { portrait_has_trait = dwf_kitsune_portrait4 } 5 = { portrait_has_trait = dwf_kitsune_portrait5 } 6 = { portrait_has_trait = dwf_kitsune_portrait6 } 7 = { portrait_has_trait = dwf_kitsune_portrait7 } 8 = { portrait_has_trait = dwf_kitsune_portrait8 } 9 = { portrait_has_trait = dwf_kitsune_portrait9 } 10 = { portrait_has_trait = dwf_kitsune_portrait10 } 11 = { portrait_has_trait = dwf_kitsune_portrait11 } 12 = { portrait_has_trait = dwf_kitsune_portrait12 } 13 = { portrait_has_trait = dwf_kitsune_portrait13 } 14 = { portrait_has_trait = dwf_kitsune_portrait14 } 15 = { portrait_has_trait = dwf_kitsune_portrait15 } 16 = { portrait_has_trait = dwf_kitsune_portrait16 } 17 = { portrait_has_trait = dwf_kitsune_portrait17 } 18 = { portrait_has_trait = dwf_kitsune_portrait18 } 19 = { portrait_has_trait = dwf_kitsune_portrait19 } 20 = { portrait_has_trait = dwf_kitsune_portrait20 } 21 = { portrait_has_trait = dwf_kitsune_portrait21 } 22 = { portrait_has_trait = dwf_kitsune_portrait22 } 23 = { portrait_has_trait = dwf_kitsune_portrait23 } 24 = { portrait_has_trait = dwf_kitsune_portrait24 } 25 = { portrait_has_trait = dwf_kitsune_portrait25 } 26 = { portrait_has_trait = dwf_kitsune_portrait26 } } } } Let's start from the bottom. 5 = { is layer 5, or more specifically the layer we are using for the portraits. Remember the number of frames we used for Step 2? You put them here, starting at 0. If your portrait file has 10 frames, you start from 0 and work your way up to 9. Simply take the number of frames and offset them by -1. These numbers will define which portrait is chosen. If you want the fifth portrait in your dds file to be used, then you will say 4 = { portrait_has_trait = dwf_kitsune_portrait4 }. The portrait traits you created in Step 3 will define which frames are used here. always = no ensures that the first frame is blank. Why? Nobody knows, nobody questions it. You can replace the blank space for another portrait. Moving up the line, we have a bunch of blocks with always = yes. The reason for this is because many layers in vanilla CK2's 00_portrait_properties.txt file disable the clothing layer 5, thus rendering our portraits useless. The 0 block in these layers are always blank, so we want to ensure that these layers use ONLY that block. Setting these to always = yes will force the code to never look at these layers when this portrait is used. Step 5: There is no Step 5 You're done! Save everything and test it out in game. Use the console command add_trait dwf_kitsune_portrait3 to test if your portrait is working. Obviously, we are using DWF kitsunes for this example, so replace dwf_kitsune_portrait3 with whatever trait you assigned to the portrait you want.
Aniknk Posted October 7, 2019 Posted October 7, 2019 OK, thanks for this big solution, but: When I use command, then everything working just fine, but portraits don't appear in the first place for my elf race. Am I doing something wrong?: INTERFACE: spriteTypes = { spriteType = { name = "GFX_woodenelf_female" texturefile = "gfx/static_portraits/gfx_woodenelf_female.dds" noOfFrames = 26 norefcount = yes can_be_lowres = yes } spriteType = { name = "GFX_woodenelf_portraits_child" texturefile = "gfx/static_portraits/gfx_woodenelf_portrait_child.dds" noOfFrames = 1 norefcount = yes can_be_lowres = yes } } spriteTypes = { portraitType = { name = "PORTRAIT_woodelf_female" effectFile = "gfx/FX/portrait.lua" weight = { additive_modifier = { value = 1000000 portrait_clothing = yes OR = { portrait_has_trait = woodenelf_portrait1 portrait_has_trait = woodenelf_portrait2 portrait_has_trait = woodenelf_portrait3 portrait_has_trait = woodenelf_portrait4 portrait_has_trait = woodenelf_portrait5 portrait_has_trait = woodenelf_portrait6 portrait_has_trait = woodenelf_portrait7 portrait_has_trait = woodenelf_portrait8 portrait_has_trait = woodenelf_portrait9 portrait_has_trait = woodenelf_portrait10 portrait_has_trait = woodenelf_portrait11 portrait_has_trait = woodenelf_portrait12 portrait_has_trait = woodenelf_portrait13 portrait_has_trait = woodenelf_portrait14 portrait_has_trait = woodenelf_portrait15 portrait_has_trait = woodenelf_portrait16 portrait_has_trait = woodenelf_portrait17 portrait_has_trait = woodenelf_portrait18 portrait_has_trait = woodenelf_portrait19 portrait_has_trait = woodenelf_portrait20 portrait_has_trait = woodenelf_portrait21 portrait_has_trait = woodenelf_portrait22 portrait_has_trait = woodenelf_portrait23 portrait_has_trait = woodenelf_portrait24 portrait_has_trait = woodenelf_portrait25 portrait_has_trait = woodenelf_portrait26 } } } layer = { "GFX_empty:p0" "GFX_empty:p2" "GFX_empty:c0" "GFX_empty:c2" "GFX_empty:c3" "GFX_empty:c1" "GFX_empty:c4" "GFX_empty:p1:h:y" "GFX_empty:p6" "GFX_woodenelf_female:c5" } allow_property_values = { 1 = { 0 = { always = yes } } 19 = { 0 = { always = yes } } 33 = { 0 = { always = yes } } 34 = { 0 = { always = yes } } 35 = { 0 = { always = yes } } 36 = { 0 = { always = yes } } 6 = { 0 = { always = yes } } 5 = { 0 = { portrait_has_trait = woodenelf_portrait1 } 1 = { portrait_has_trait = woodenelf_portrait2 } 2 = { portrait_has_trait = woodenelf_portrait3 } 3 = { portrait_has_trait = woodenelf_portrait4 } 4 = { portrait_has_trait = woodenelf_portrait5 } 5 = { portrait_has_trait = woodenelf_portrait6 } 6 = { portrait_has_trait = woodenelf_portrait7 } 7 = { portrait_has_trait = woodenelf_portrait8 } 8 = { portrait_has_trait = woodenelf_portrait9 } 9 = { portrait_has_trait = woodenelf_portrait10 } 10 = { portrait_has_trait = woodenelf_portrait11 } 11 = { portrait_has_trait = woodenelf_portrait12 } 12 = { portrait_has_trait = woodenelf_portrait13 } 13 = { portrait_has_trait = woodenelf_portrait14 } 14 = { portrait_has_trait = woodenelf_portrait15 } 15 = { portrait_has_trait = woodenelf_portrait16 } 16 = { portrait_has_trait = woodenelf_portrait17 } 17 = { portrait_has_trait = woodenelf_portrait18 } 18 = { portrait_has_trait = woodenelf_portrait19 } 19 = { portrait_has_trait = woodenelf_portrait20 } 20 = { portrait_has_trait = woodenelf_portrait21 } 21 = { portrait_has_trait = woodenelf_portrait22 } 22 = { portrait_has_trait = woodenelf_portrait23 } 23 = { portrait_has_trait = woodenelf_portrait24 } 24 = { portrait_has_trait = woodenelf_portrait25 } 25 = { portrait_has_trait = woodenelf_portrait26 } } } } } AND TRAITS: woodenelf_portrait1 = { hidden_from_others = yes random = no customizer = no } woodenelf_portrait2 = { hidden_from_others = yes random = no customizer = no } woodenelf_portrait3 = { hidden_from_others = yes random = no customizer = no } woodenelf_portrait4 = { hidden_from_others = yes random = no customizer = no } woodenelf_portrait5 = { hidden_from_others = yes random = no customizer = no } woodenelf_portrait6 = { hidden_from_others = yes random = no customizer = no } woodenelf_portrait7 = { hidden_from_others = yes random = no customizer = no } woodenelf_portrait8 = { hidden_from_others = yes random = no customizer = no } woodenelf_portrait9 = { hidden_from_others = yes random = no customizer = no } woodenelf_portrait10 = { hidden_from_others = yes random = no customizer = no } woodenelf_portrait11 = { hidden_from_others = yes random = no customizer = no } woodenelf_portrait12 = { hidden_from_others = yes random = no customizer = no } woodenelf_portrait13 = { hidden_from_others = yes random = no customizer = no } woodenelf_portrait14 = { hidden_from_others = yes random = no customizer = no } woodenelf_portrait15 = { hidden_from_others = yes random = no customizer = no } woodenelf_portrait16 = { hidden_from_others = yes random = no customizer = no } woodenelf_portrait17 = { hidden_from_others = yes random = no customizer = no } woodenelf_portrait18 = { hidden_from_others = yes random = no customizer = no } woodenelf_portrait19 = { hidden_from_others = yes random = no customizer = no } woodenelf_portrait20 = { hidden_from_others = yes random = no customizer = no } woodenelf_portrait21 = { hidden_from_others = yes random = no customizer = no } woodenelf_portrait22 = { hidden_from_others = yes random = no customizer = no } woodenelf_portrait23 = { hidden_from_others = yes random = no customizer = no } woodenelf_portrait24 = { hidden_from_others = yes random = no customizer = no }woodenelf_portrait1 = { hidden_from_others = yes random = no customizer = no } woodenelf_portrait25 = { hidden_from_others = yes random = no customizer = no } woodenelf_portrait26 = { hidden_from_others = yes random = no customizer = no }
Aniknk Posted October 7, 2019 Posted October 7, 2019 Validator also says something about localisation file for traits.
lockeslylcrit Posted October 7, 2019 Author Posted October 7, 2019 7 hours ago, Aniknk said: When I use command, then everything working just fine, but portraits don't appear in the first place for my elf race. Am I doing something wrong?: Your portrait traits will never appear automatically on someone. You will need to delve into on_action, scripted_effects, and event modding to get them to show up automatically.
coolPein Posted December 6, 2019 Posted December 6, 2019 Hey, I really didn't feel like getting into this coding mumbo-jumbo as it confuses the hell out of me so I decided to simply try to put new images over the pre-existing portrait .dds image. I changed the images so they fit perfectly into the spaces, however whenever I go in-game, none of the portraits from the .dds file seem to work anymore (even the slots I didn't touch) as they don't change the character portrait whatsoever and some make the character appear bald for some reason. I was hoping this was due to some kind of file format problem since I only changed the gfx file, but I have no clue... The .dds file I edited was for the kitsune race "LF_Races_Kitsune.dds" LF_Races_Kitsune.dds
Rascalov1337 Posted December 6, 2019 Posted December 6, 2019 I think there's something wrong with how your file was saved. This is how image viewing program I use sees it: Empty, 100% transparent image. Meanwhile in Photoshop it looks like this: It is not transparent, but compared to the original file from Luxuria, it has much more desaturated colors. So check your image editing program, if it has proper support for .dds files, or maybe there's something wrong with settings.
coolPein Posted December 6, 2019 Posted December 6, 2019 Hm, I was using lockeslylcrit's post as a guide and using paint.net which was recommended, perhaps I have to choose a different colour setting when saving? I was mostly just checking to see which setting looked best and I think selected something with rgb colours and all that. Whenever I open it in paint.net it still shows up as proper png with the transparent background so I have no clue, I've never used this program before so it's probably me messing something up
coolPein Posted December 6, 2019 Posted December 6, 2019 yep, okay, I was just being an idiot, I selected dx11 when saving so the game didn't know how to handle it, just tried it on dx1 and it worked like a charm, wish I had tried that first but thanks for helping me out. I guess just the thought of having to mess with the trait/interaction code got me spooked, thanks again Rascalov1337
kioo Posted December 11, 2019 Posted December 11, 2019 Is it possible to have a static portrait that supports headgear, scars, blindfolds, clothes, etc.?
lockeslylcrit Posted December 11, 2019 Author Posted December 11, 2019 1 hour ago, kioo said: Is it possible to have a static portrait that supports headgear, scars, blindfolds, clothes, etc.? Kind of? Static portraits use portrait layer 5, and there are many things in the other layers that will conflict.
Coalsack94 Posted December 11, 2020 Posted December 11, 2020 Is there any specific way to add an specific portrait to an specific NPC? I'm using Dark World Reborn and have some unique immortal Therianthropes running around my empire that I'd like to give equally unique portraits. Also, do I have to forcefully put the entire stack of 27 portraits on my dds file used as texture? As I said, is kind of one unique picture per character.
Recommended Posts
Archived
This topic is now archived and is closed to further replies.