Jump to content

[CK2][Resource] A new way of implementing static portraits!


ngppgn

Recommended Posts

Thanks to a couple fellow modders from the Geheimnisnacht team, and the previous work of ReMeDy here at loverslab, I've put together a new schematic way of doing static portraits which is completely independent from any DLC. Yes, no longer do we have to worry about what portrait pach do we lack and so what .gfx file do we have to remove. Furthermore, it is virtually compatible with almost any mod out there!*

 

*well, more or less. This is what will happen if you use it with other mods:

-If said mods use the old way of doing static portraits (i.e. adding extra layers to portrait definitions), then those mods' portraits will show up.

-Otherwise, your static portraits will show up.

-The only exception is if the other mod don't use the old style of static portraits but uses the new system for society clothing and give a custom layer a weight over 1000000 (vanilla uses 10000)

 

So,

 

How does it works?

 

To illustrate the new system better, I'll explain it step by step, by comparison with ReMeDy's system:

 

1) The traits:

We need a unique trait per protrait that we are going to use. Ideally all the portrait traits should be opposites of each other, so that when an event adds one it removes all the others. Also, they should be hidden so as not to overcrowd the trait tab in the character sheets.

 

2) The graphical assets:

Portraits needs to be provided as .dds or .tga files under the mod's \gfx folder, or a subfolder thereof. ReMeDy's .dds files are in \gfx\characters.

Each of those files will contain a horizontal strip of up to 27 portraits. Each portrait has to be 152x152 pixels, to the file needs to be (152*number of portraits)x152

With the old system, the first portrait in each strip needed to be fully transparent. This is not required with the new system!

 

3) The spriteTypes:

CK2 needs entries in some .gfx file(s) under the \interface folder in the mod to link the .dds or .tga files to the actual game. The content of such .gfx files would look like this:

spriteTypes = { 
   ...
   spriteType = {
	name = #Here you put a tag for the game to reference it. They start with "GFX_"
	texturefile = #Here you put the address of the .dds or .tga file relative to the root mod folder
	noOfFrames = #here you put the number of portraits in the file, including any transparent ones. Maximum is 27
	norefcount = yes
	can_be_lowres = yes
   }
   ...
}
We could also add spriteType entries for our traits, but since they are hidden whe shouldn't worry about that.

 

4) The portraitType:

 

Now, for the big step, and the real difference between the old and the new system.

For the static portraits to actually sho up in-game, the old system needed to add new property slots to each portraitType, meaning to each different ethnicity definition in the game, then edit a portrait_properties file that would govern when each portrait in each strip would be used. This was the grat source of conflict with other mods and DLCs - surely those conflicts could be worked out, but they were an inconvenience for the end user.

 

The new system takes advantage of the mechainc introduced by the developers to display society clothings. Only that instead of overriding the clothing property to show other clothing, we'll be overriding to show a static portrait!.

 

This is how a .gfx definition for a society clothing looks like in vanilla:

spriteTypes = {
    portraitType = { #you need to create one of these for each .dds or .tga portrait strip you're using
        name = "PORTRAIT_static_1" #you need to use a unique tag for each of these definitions, but they are not referenced anywhere else that I know of.

        weight = {
            additive_modifier = {
                value = 1000000 #vanilla uses 10000 for the societies clothing. We are using this to make sure it takes priority.
                portrait_clothing = yes #I'm not really sure what this does, but it is mandatory. In my tests, comenting it out has produced only blank portraits.
			OR = { #a list of the portraits associeted with the portraits on the strip
				portrait_has_trait = portrait1
				portrait_has_trait = portrait2
				portrait_has_trait = portrait3
				portrait_has_trait = portrait4
				portrait_has_trait = portrait5
				portrait_has_trait = portrait6
				portrait_has_trait = portrait7
				portrait_has_trait = portrait8
				portrait_has_trait = portrait9
				portrait_has_trait = portrait10
				portrait_has_trait = portrait11
				portrait_has_trait = portrait12
				portrait_has_trait = portrait13
				portrait_has_trait = portrait14
				portrait_has_trait = portrait15
				portrait_has_trait = portrait16
				portrait_has_trait = portrait17
				portrait_has_trait = portrait18
				portrait_has_trait = portrait19
				portrait_has_trait = portrait20
				portrait_has_trait = portrait21
				portrait_has_trait = portrait22
				portrait_has_trait = portrait23
				portrait_has_trait = portrait24
				portrait_has_trait = portrait25
				portrait_has_trait = portrait26
			}
	 	}
        }

        layer = { #the properties that this is overriding
            "GFX_empty:c0" #These might or might not be relevant, I still haven't tested it.
            "GFX_empty:c2"
            "GFX_empty:c3"
            "GFX_empty:c1"
            "GFX_empty:c4"
            "GFX_empty:p1:h:y"
            "GFX_portrait_remedy_portrait_swapping:c5" #c5 is the clothing property, the one we'll be using.
        }

        allow_property_values = {
            1 = { #outer number denotes the property.
                0 = { always = yes } #inner number denotes the frame of each property, i.e. the portrait in each strip, The first is always 0, so in a 27-slots strip, the last is 26
            } #this is here only for illustration and testing, can be removed.
            5 = { #the clothing property
		0 = { always = no } #this is the first frame, which is transparent in the old system, thus the always = no. But it could be used to have one extra portrait per frame.
		1 = { portrait_has_trait = portrait1 }
		2 = { portrait_has_trait = portrait2 }
		3 = { portrait_has_trait = portrait3 }
		4 = { portrait_has_trait = portrait4 }
		5 = { portrait_has_trait = portrait5 }
		6 = { portrait_has_trait = portrait6 }
		7 = { portrait_has_trait = portrait7 }
		8 = { portrait_has_trait = portrait8 }
		9 = { portrait_has_trait = portrait9 }
		10 = { portrait_has_trait = portrait10 }
		11 = { portrait_has_trait = portrait11 }
		12 = { portrait_has_trait = portrait12 }
		13 = { portrait_has_trait = portrait13 }
		14 = { portrait_has_trait = portrait14 }
		15 = { portrait_has_trait = portrait15 }
		16 = { portrait_has_trait = portrait16 }
		17 = { portrait_has_trait = portrait17 }
		18 = { portrait_has_trait = portrait18 }
		19 = { portrait_has_trait = portrait19 }
		20 = { portrait_has_trait = portrait20 }
		21 = { portrait_has_trait = portrait21 }
		22 = { portrait_has_trait = portrait22 }
		23 = { portrait_has_trait = portrait23 }
		24 = { portrait_has_trait = portrait24 }
		25 = { portrait_has_trait = portrait25 }
		26 = { portrait_has_trait = portrait26 }
	    }
        }
    }
   ...
}
Once we have it all setup, adding a portrait trait will show the corresponding static portrait with no problem

 

Automating the process

 

Now, while all that stuff is neat, it'd be a PITA to code oeself, that that'd be a good argument to keep using the current system.

 

So what I did was make myself a python 3.6 script to automate the process.

 

Sadly, I cannot at the moment turn it into an .exe so if you want to use it you'll have yo install Python 3.6 (I use formatted strings, which are not available in previous version of Python, so if you have an older version you'll have to upgrade to be able to use it).

 

Inside the .zip file there are two files: a setup.ini which you can open with a text editor such as notepad++ or sublime, that allows you to customise the program to your needs and the python script itself. Just edit the .ini file to suit your needs and then run the program.

 

1) settings.ini

In the Paths section you have three entries:

mod is the adbsolute path to your mod folder.

assets is the subfolder of mod where the .dds or .tga files your are going to use for the static portraits are located. Only the files you want to use for portraits must be in this folder. Also note that the file names will be read in ASCII order when generating files, so if e.g. you want file2 to be read before file10, be sure to rename if to file02 instead!

 

noOfFrames is the number of portraits each strip in the above folder will have. The program assumes all strips have the same length. Values over 27 will cause bugs once in the game, so 27 is the optimal choice.

 

start_af_frame = x is used to tell the program to ignore the the x first portraits in each strip. E.g. the strips from ReMeDy's mod have the first frame transparent so to use them, we should set start_at_frame to 1. If set to 0 no frame will be ignored.

 

In the Output section you'll see five entries:

prefix is the string we'll use in the naming of the traits. E.g. if prefix is portrait then the traits will be named portrait1, portrait2, etc.

 

trait_filename = x Your trait file will be named x.txt

gfx_filename = x Your .gfx file will be named x.gfx

 

NOTE: All the required foldersi must exist beforehand for the program to run. Else, it will throw an error. This includes the mod's folder, the mod's common\traits and interface\portraits subfolder as well as the subfolder specified for the graphical assets. I want for a future version to create the appropriate folders if they don't exist, but there are some subtleties with python involved in that task which I don't completely graps ATM (hey, I'm an amateur coder!).

 

2) static_portrait_generator.py

This is the program itself. Once you have python 3.6 installed you can double-click on it or call it from the comand line to execute it. Also you can open it with a text editor such as Notepad++, sublime, or Python's IDLE to read and edit it if you so which.

 

Remember that static_portrait_generator.py and settings.ini must be in the same folder!

 

 

Besides the program itself, I've attacked another .zip with an example of the result, using ReMeDy's template assets.

 

I hope you find this useful and as always, any feedback or suggestion is welcome!

 

My deepest thanks to ReMeDy for his invaluable original work, and for the modders who showed me the technique in the first place.

static_portrait_generator.zip

Template test.zip

Link to comment

Okay, I had more time to fiddle with it. Now I see why you created that generator, lol. Maintaining this massive code by hand would be a nightmare. Yea, the Python requirement for editing is a bummer, but the good news is I doubt many people need to use the generator, and thankfully you'll probably never need to update this mod, since it's not dependent on portrait DLC changes, your files are custom named, and I doubt anyone will need more than the current 650 portraits. That's great, because you're on your own with the updates, as Python is not my specialty!

 

You mentioned with this system, the first portrait in each strip doesn't need to be transparent. At this point, utilizing the extra portrait per strip probably isn't worth the effort, as 650 portraits is plenty, and could mess with the ordering of people's existing gfx strips and break Dewguru's portrait codes, as all the portraits would have to slide over to the left, and people would have to re-position their portraits on their gfx strips.

 

There's one downside I'm noticing: I can't use my custom naming convention used in my anime pack. The script generator -- from my understanding -- uses only a limited naming approach to populate the entire code, whereas I prefer unique trait names for each portrait for convenience. That isn't an issue though for a template pack user, and based on my download numbers, users prefer the template pack anyways, as does Dewguru with Dark World. I'll continue updating my custom naming approach, because I absolutely need this functionality for, say, my Game of Thrones portrait mod, as going through the history files and giving characters nondescript names like "portrait 23, 48, etc." would drive me crazy, lol. Plus, Game of Thrones uses custom cultures, so it's not affected by the weakness of requiring portrait DLC.

 

I also tested your mod with Seiji's Anime Portraits and I'm pleased to say they're compatible. The mods can run separate and no dependencies are required.

 

Basically, my template pack is obsolete, and I encourage Dew to upgrade to this topic's template test. He may as well also remove his portrait sub-mod and merge all your files into his mod, as they're all custom named and shouldn't conflict with anything. I'll edit my template pack to link to your mod.

Link to comment

Okay, I had more time to fiddle with it. Now I see why you created that generator, lol. Maintaining this massive code by hand would be a nightmare. Yea, the Python requirement for editing is a bummer, but the good news is I doubt many people need to use the generator, and thankfully you'll probably never need to update this mod, since it's not dependent on portrait DLC changes, your files are custom named, and I doubt anyone will need more than the current 650 portraits. That's great, because you're on your own with the updates, as Python is not my specialty!

 

You mentioned with this system, the first portrait in each strip doesn't need to be transparent. At this point, utilizing the extra portrait per strip probably isn't worth the effort, as 650 portraits is plenty, and could mess with the ordering of people's existing gfx strips and break Dewguru's portrait codes, as all the portraits would have to slide over to the left, and people would have to re-position their portraits on their gfx strips.

 

There's one downside I'm noticing: I can't use my custom naming convention used in my anime pack. The script generator -- from my understanding -- uses only a limited naming approach to populate the entire code, whereas I prefer unique trait names for each portrait for convenience. That isn't an issue though for a template pack user, and based on my download numbers, users prefer the template pack anyways, as does Dewguru with Dark World. I'll continue updating my custom naming approach, because I absolutely need this functionality for, say, my Game of Thrones portrait mod, as going through the history files and giving characters nondescript names like "portrait 23, 48, etc." would drive me crazy, lol. Plus, Game of Thrones uses custom cultures, so it's not affected by the weakness of requiring portrait DLC.

 

I also tested your mod with Seiji's Anime Portraits and I'm pleased to say they're compatible. The mods can run separate and no dependencies are required.

 

Basically, my template pack is obsolete, and I encourage Dew to upgrade to this topic's template test. He may as well also remove his portrait sub-mod and merge all your files into his mod, as they're all custom named and shouldn't conflict with anything. I'll edit my template pack to link to your mod.

Thanks for the feedback! I haven't looked into the AGOT portrait pack. What is the naming convention there? Maybe I can rig something for you. I'm thinking of providing a list of names as imputs and make the generator treat the first name as portrait1, the second name as portrait2, etc. Would that work?

Link to comment

 

Thanks for the feedback! I haven't looked into the AGOT portrait pack. What is the naming convention there? Maybe I can rig something for you. I'm thinking of providing a list of names as imputs and make the generator treat the first name as portrait1, the second name as portrait2, etc. Would that work?

 

 

I just use the character's first name (joffrey, melisandre, stannis, etc.). I add them in the history files so that the portraits are automatically assigned on start-up, but yea, because of that unique naming approach, it probably wouldn't work. Oh well, I wouldn't worry about it. In the case of the AGoT pack, it's fully dlc compatible anyways, namely because it's a total conversion, so it doesn't use any of Paradox's portrait dlc to begin with.

Link to comment

Hmm, I just thought something. I can easily implement a custom naming approach using what you've done, and tailoring the Python script to it wouldn't be necessary, albeit I'd need to do a manual insertion method. All I need to do is use Notepad++, perform a shit ton of finding and replacing (ex. all instances of portrait 1 = beatrice, portrait 2 = battler, etc.), and that would populate the entire file, despite how massive the text is. Of course, the problem is if the user wanted to change the names or add their own, they'd need Notepad++ or something similar supporting find/replace, but Notepad++ is legally free, and it's a helluva lot better than asking my users to purchase portrait DLC, and they would only need Notepad++ if they wanted to make changes to my anime pack; it wouldn't be a requirement for using the pack itself.

 

I'll give it a go when I have the free time. If I were to apply your approach to my Game of Thrones mod, do I have your permission to share the update on Steam and adding your name to the credits? What name do you go by on Steam?

Link to comment

Hmm, I just thought something. I can easily implement a custom naming approach using what you've done, and tailoring the Python script to it wouldn't be necessary, albeit I'd need to do a manual insertion method. All I need to do is use Notepad++, perform a shit ton of finding and replacing (ex. all instances of portrait 1 = beatrice, portrait 2 = battler, etc.), and that would populate the entire file, despite how massive the text is. Of course, the problem is if the user wanted to change the names or add their own, they'd need Notepad++ or something similar supporting find/replace, but Notepad++ is legally free, and it's a helluva lot better than asking my users to purchase portrait DLC, and they would only need Notepad++ if they wanted to make changes to my anime pack; it wouldn't be a requirement for using the pack itself.

 

I'll give it a go when I have the free time. If I were to apply your approach to my Game of Thrones mod, do I have your permission to share the update on Steam and adding your name to the credits? What name do you go by on Steam?

 

By all means, go ahead. I go by the same username on Steam as I do on here.

 

 

 

Link to comment

Archived

This topic is now archived and is closed to further replies.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. For more information, see our Privacy Policy & Terms of Use