Jump to content

CK2 Modding Tricks


Recommended Posts

In my time modding, I have come across several tricks that are either poorly documented, not documented, or referenced once in the forums and seemingly forgotten.  I have also discovered some things by simple trial and error.  
 
 
societies

  • you can have up to seven levels in a society before the graphics start to get cutoff, but I am not sure if the code will fully support levels beyond 4 at this time.

trigger_switch

  • this also works with variables, including date variables.  You do need to remember to use the proper order because it will trigger on the first one that matches and then stop processing.  Also, when using a date or a number, remember that "=" really means ">="!  example: 
    trigger_switch = {
    	on_trigger = start_date
    	769.1.1			=	{character_event = { id = NOXBCE.769 days = 80   }}
    	867.1.1			=	{character_event = { id = NOXBCE.867 days = 80   }}
    	1066.9.15		=	{character_event = { id = NOXBCE.1066 days = 187 }}
    	1066.12.26		=	{character_event = { id = NOXBCE.1066 days = 85  }}
    	1081.4.1		=	{character_event = { id = NOXBCE.1081 days = 356 }}
    	1187.1.1		=	{character_event = { id = NOXBCE.1187 days = 80  }}
    	1204.5.16		=	{character_event = { id = NOXBCE.1204 days = 309 }}
    	1220.2.1		=	{character_event = { id = NOXBCE.1220 days = 48  }}
    	1241.5.1		=	{character_event = { id = NOXBCE.1241 days = 324 }}
    	1337.1.1		=	{character_event = { id = NOXBCE.1337 days = 80  }}
    }
    
    
  • If there is a way of doing a fail-safe at the end of a trigger switch, I have not yet discovered it.

custom graphical races & portraits:

  • Thanks to a mix of the work by ReMeDy and the AGOT team, I discovered that the base image can be modified with up to 27 different images.  This can be seen in my centaur race which looks like the static portrait replacer, but it does not use any traits for the images.  example: 
    spriteType = {
    	name = "GFX_centaur_male"
    	texturefile = "gfx\\characters\\centaurs\\male_centaur.tga"
    	noOfFrames = 27
    	norefcount = yes
    	can_be_lowres = yes
    }
    
    You must move the base entry lower down in the list so that you don't get hair and cloths overlaid on top of your static image.  Also, you still need to add code to make it compatible with mods that do use ReMeDy's static portrait replacer.  example:

  • # Young centaur
    portraitType = {
    	name = "PORTRAIT_centaurgfx_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_horse_male_clothes_behind:p3:c0"
    		"GFX_horse_male_headgear_behind:p5:c1"
    		"GFX_horse_male_hair_behind:p1:h:y"
    		"GFX_horse_male_beard_behind:p4:h:y"
    		#"GFX_horse_male_base:p2"	# this was the original 
    		"GFX_horse_male_neck:d0"
    		"GFX_horse_male_cheeks:d4"
    		"GFX_horse_male_chin:d1"
    		"GFX_horse_male_mouth:d2"
    		"GFX_horse_male_nose:d3"
    		"GFX_horse_male_eyes:d6"
    		"GFX_horse_male_eyes2:d6:e"
    		"GFX_character_scars:p7:y"
    		"GFX_character_reddots:p8"
    		"GFX_character_boils:p9"
    		"GFX_character_blinded_eyes:p10"
    		"GFX_horse_male_clothes:p3:c2"
    		"GFX_horse_male_headgear_mid:p5:c3"
    		"GFX_horse_male_ear:d7:o27x54"			
    		"GFX_horse_male_beard:p4:h:y"
    		"GFX_horse_male_hair:p1:h:y"
    		"GFX_horse_male_clothes_infront:p3:c4"
    		"GFX_horse_male_headgear:p5:c5"
    		"GFX_centaur_male:p2"		# this is the new one with the multiple frames defined in previous example
    		"GFX_character_remedy_portrait_swapping:p14"
    		"GFX_character_remedy_portrait_swapping2:p15"
    		"GFX_character_remedy_portrait_swapping3:p16"
    		"GFX_character_remedy_portrait_swapping4:p17"
    		"GFX_character_remedy_portrait_swapping5:p18"
    		"GFX_character_remedy_portrait_swapping6:p19"
    		"GFX_character_remedy_portrait_swapping7:p20"
    		"GFX_character_remedy_portrait_swapping8:p21"
    		"GFX_character_remedy_portrait_swapping9:p22"
    		"GFX_character_remedy_portrait_swapping10:p23"
    		"GFX_character_remedy_portrait_swapping11:p24"
    		"GFX_character_remedy_portrait_swapping12:p25"
    		"GFX_character_remedy_portrait_swapping13:p26"
    		"GFX_character_remedy_portrait_swapping14:p27"
    		"GFX_character_remedy_portrait_swapping15:p28"
    		"GFX_character_remedy_portrait_swapping16:p29"
    		"GFX_character_remedy_portrait_swapping17:p30"
    		"GFX_character_remedy_portrait_swapping18:p31"
    		"GFX_character_remedy_portrait_swapping19:p32"
    		"GFX_character_remedy_portrait_swapping20:p33"
    		"GFX_character_imprisoned:p6"
    		"GFX_player_overlay:p11"
    	}
    


    So far I have not verified an easy way to allow someone to chose their portrait, but I believe the new portrait controls we got with CK2 version 2.7 might solve this.

referencing historic characters

  • I wanted to be able to affect historic characters, living or dead, from within my code.  In the example below, I give Emperor Nero a father and mother that were from my own history files, without having to modify CK2 history files: 
    c_1811 = { c_145287 = { set_father = PREV }}	# Emperor Nero
    c_1818 = { c_145287 = { set_mother = PREV }}	# Emperor Nero
    

random event pictures

  • As of CK2 version 2.6.3 this was still tricky to do if you were using triggered descriptions.  My solution is a bit complicated and quite tedious, but it works. In my example, I am using 4 possible images, but this can be done with any number you wish to code for. First, I made a scripted effect for setting randomly setting 1 of 4 character flags.

    nox_randomizer_4 = {
    	clr_character_flag = nox_random_1
    	clr_character_flag = nox_random_2
    	clr_character_flag = nox_random_3
    	clr_character_flag = nox_random_4
    	random_list = {
    		10 = { set_character_flag = nox_random_1 }
    		10 = { set_character_flag = nox_random_2 }
    		10 = { set_character_flag = nox_random_3 }
    		10 = { set_character_flag = nox_random_4 }
    	}
    }


    The tedious part comes when you realize that you have to make a separate triggered description entry for each picture, and then repeat this for each possible triggered descriptions.  For randomly displaying one of 4 images, a single possible triggered description requires 4 entries, 2 needs 8, 3 needs 12, and so on.  To keep the validator happy, you need a default picture set at the top.  Also, you need to call the randomizer scripted effect from the "immediate" block so that the random number is generated before the triggered descriptions are evaluated.  Here is an example:

    picture = NOX_placeholder
    
    immediate = {
    	nox_randomizer_4 = yes
    }
    
    desc ={
    	trigger = {
    		has_character_flag = nox_random_1
    	}
    	text = NXBST10030a_desc				
    	picture = NOX_mare_cunilingus2
    }
    
    desc ={
    	trigger = {
    		has_character_flag = nox_random_2
    	}
    	text = NXBST10030a_desc			
    	picture = NOX_mare_cunilingus3
    }
    
    desc ={
    	trigger = {
    		has_character_flag = nox_random_3
    	}
    	text = NXBST10030a_desc
    	picture = NOX_mare_cunilingus4
    }
    
    desc ={
    	trigger = {
    		has_character_flag = nox_random_4
    	}
    	text = NXBST10030a_desc				
    	picture = NOX_mare_cunilingus1
    }


    I know for some modders this is just too much, but the results are neat.I will attempt to regularly update this entry with more tricks as they are submitted to me or as I discover them.

I hope the rest of the CK2 adult modding community finds these helpful.   :)

Link to comment

Re: evemt picture randomiser:

You can take advantage of customisable localisation. Use the different desc blocks with different pixtures but the same text key. The define the key using dynamic localisation with several entries governed by another "randomiser".

 

Re:trigger_switch. No "else" or similar exhausting clause. But you can work around this. In each entry of the switch add a custom flag. Then after the switch check for the absence of the flag.

 

An a pretty amazing thing: you can script sound effects for wvents. I hope to see moans and other naughty sounds in mods here soon!

Link to comment
  • If there is a way of doing a fail-safe at the end of a trigger switch, I have not yet discovered it.

I think you could accomplish it with breaks. Have your cases be like this:

769.1.1            =    {
character_event = { id = NOXBCE.769 days = 80 }
break = yes
}

Then put your default action after the trigger_switch block. Caveat: I haven't actually tested that.

Link to comment

 

  • If there is a way of doing a fail-safe at the end of a trigger switch, I have not yet discovered it.

I think you could accomplish it with breaks. Have your cases be like this:

769.1.1            =    {
character_event = { id = NOXBCE.769 days = 80 }
break = yes
}

Then put your default action after the trigger_switch block. Caveat: I haven't actually tested that.

 

 

Not really. Or rather, only in some special cases. The problem with that is that break = yes exists the whole immediate/option/effect block. So you cannot do that way something like

 

-do the trigger switch with the failsafe.

-then do some other things.

 

Since if one of the cases is matched, the block will be exited and "do some other things" will never be executed.

 

In that regard, the trick I proposed above is more general as it is also applicable in those cases. To be explicit, It'd be something like this:

trigger_switch = {
  on_trigger = trait
  <trait1> = { set_character_flag = x <do things1> }
  ...
  <traitn> = { set_character_flag = x <do thingsn> }
}
if = { limit = { not = { has_character_flag = x } } <do failsave things> }
clr_character_flag = x.

Link to comment

 

In that regard, the trick I proposed above is more general as it is also applicable in those cases. To be explicit, It'd be something like this:

trigger_switch = {
  on_trigger = trait
  <trait1> = { set_character_flag = x <do things1> }
  ...
  <traitn> = { set_character_flag = x <do thingsn> }
}
if = { limit = { not = { has_character_flag = x } } <do failsave things> }
clr_character_flag = x.

 

That looks like a great way of working around the lack of a switch fail-safe.

Link to comment
  • 9 months later...
On 3/17/2017 at 4:19 AM, ngppgn said:

 

In that regard, the trick I proposed above is more general as it is also applicable in those cases. To be explicit, It'd be something like this:


trigger_switch = {
  on_trigger = trait
  <trait1> = { set_character_flag = x <do things1> }
  ...
  <traitn> = { set_character_flag = x <do thingsn> }
}
if = { limit = { not = { has_character_flag = x } } <do failsave things> }
clr_character_flag = x.

@ngppgn Just wanted to let you know that I was using this trick in my code when I was still thinking I needed the *_DNA traits for proper inheritance.  It worked great.  :smile:

 

 

Link to comment
5 hours ago, noxbestia said:

@ngppgn Just wanted to let you know that I was using this trick in my code when I was still thinking I needed the *_DNA traits for proper inheritance.  It worked great.  :smile:

 

 

Thanks, man. Was thinking about that the othe day. It has a limitation in that when you nest switches inside other switches you need to remember to use a different flag for each level of nesting.

 

In any case, right now we have the if-else_if-...-else_if-else pattern as an alternative.

 

Another little trick, you can use local variables, event targtets and scripted effects to simulate functions that take argument.

 

For example, inside an effect block have


save_event_target_as = _arg_scope

set_variable = { which = local__arg_value }

some_function_like_effect = yes

 

And have the scripted effect look like this (this is justa dummy examplr):

 


some_function_like_effect = {

  event_target:_arg_scope = { prestige = local__arg_value

}

  set_variable = { which = local__arg_value value = 0 }

  clear_event_target = _arg_scope

 

Note that if you are nesting "functions" inside more "functions" you need to be careful eith naming the arguments diferently so that they don't obscure one another (damnit paradox, import meta-scripted blocks from eu4 already!)

Link to comment
  • 3 weeks later...

Miscellaneous advice: If you have a piece of code thst's doing very intendive effect work in the bacground (e.g. going through any_realm_character and adding opinion modifier), put it inside hidden_effect = { generate_tooltip = no (your code here) }

 

Reason is the game generates toolrip text for all effects even if when the effect is in hidden_effect block, so the engine could unwittingly generate huge xhuncks of tooltips only for them to be wadted away. 

 

The only caveat is that in the hifden section you set event tsrgetd that sre used later in the visible psrt of the overall block (e.g. event option) the tooltip will misbehave.

 

So, as a rule, make a hsbit of putting genererste_tooltip = no inside hidden_effect unless you desl with event targets there.

Link to comment
  • 2 years later...

Hello @NoxBestia!

 

Sorry for necro...

But you don't explain, where excactly does this part go?

Do I have to create a new file for this?

nox_randomizer_4 = {
	clr_character_flag = nox_random_1
	clr_character_flag = nox_random_2
	clr_character_flag = nox_random_3
	clr_character_flag = nox_random_4
	random_list = {
		10 = { set_character_flag = nox_random_1 }
		10 = { set_character_flag = nox_random_2 }
		10 = { set_character_flag = nox_random_3 }
		10 = { set_character_flag = nox_random_4 }
	}
}

And, did you figure out an easier way to randomize pictures?

 

Thanks!

Link to comment
16 hours ago, Drax70 said:

Hello @NoxBestia!

 

Sorry for necro...

But you don't explain, where excactly does this part go?

Do I have to create a new file for this?


nox_randomizer_4 = {
	clr_character_flag = nox_random_1
	clr_character_flag = nox_random_2
	clr_character_flag = nox_random_3
	clr_character_flag = nox_random_4
	random_list = {
		10 = { set_character_flag = nox_random_1 }
		10 = { set_character_flag = nox_random_2 }
		10 = { set_character_flag = nox_random_3 }
		10 = { set_character_flag = nox_random_4 }
	}
}

And, did you figure out an easier way to randomize pictures?

 

Thanks!

https://ck2.paradoxwikis.com/Event_modding#Picture

Link to comment
4 hours ago, s-w-a said:

Thanks for the response!

But, I already know about the wiki and it takes most of the modding for granted and it is not clear enough to actually help, which means, that you will have to bounce from page to page to understand things...!

That's why, I hopped, that @NoxBestia should have come up with a simpler solution by now!

Anyway, thanks again! :)

Link to comment
11 hours ago, Drax70 said:

Thanks for the response!

But, I already know about the wiki and it takes most of the modding for granted and it is not clear enough to actually help, which means, that you will have to bounce from page to page to understand things...!

That's why, I hopped, that @NoxBestia should have come up with a simpler solution by now!

Anyway, thanks again! :)

NoxBestia's trick was basically to randomly generate a flag in an event1; event1 would then call event2, who has a bunch of desc/picture blocks with triggers checkjing for said flags. The flags to ensure you only ever end up with one flag, instead of having them build up over time.

However, CK2 has updated quite a bit since then - I know that having multiple legal descs will make the event pick a random one, so perhaps you should check to see if it does the same with pictures.

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • 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