-
Notifications
You must be signed in to change notification settings - Fork 1
scripting
Let's take a sentence: If King Henry is brave, he gains 100 gold.
This sentence is relevant to CK3 and can be translated into script while also serving as a perfect metaphor for the basics of CK3 code
Note: add_gold_to_person
and random_and_every_effects
are both
scripted_effects, which is something I'll explain later.
In the sentence above, King Henry is a scope. A scope is essentially a noun: a person, place, or thing. If you're wondering who, where, or what are your effects happening to, they're happening to whatever is scoped. CK3 has built in scopes, listed in this wiki.
Those can be reached easily in code. In the below code, let's assume that the effect is already scoped to a character.
If we want to instead add gold to the character's mother, we do this:
But why stop with her? Let's keep going further:
Now the character's matrilineal grandfather is gaining gold. But what if we go further?
Starting to see a problem? This code gets clunky. Thankfully, there's a way to simplify it. We can chain scopes together with a period.
Far better. It still fetches the mother's father's liege's primary heirs' court owner, but it reduces unnecessary bloat.
Alright then: there are three types of scopes I should cover: Relation, call, and saved scopes (I just made up these names, but they'll suffice.)
Relation scopes are what you saw above. Mother, father, primary_title, liege, culture, faith, etc. Those are all relation scopes. They get something directly related to the scope they are called in. mother.father get's the character's mother's father. Relation scopes are what you see on the linked scopes wiki above. There are three scopes which also fall into this category which don't really count as relations. These are root, which calls the original at the very start of the chain of effects or events or whatever, this, which calls the current scope, and prev, which calls the previous scope.
Call scopes are harder to explain. While we can get a character/place's culture with the culture scope, we can also call a specific culture with culture:latin
, or culture:french
. With these we can call:
-
character:1020
(see history/characters) -
title:k_england
(see common/landed_titles) -
culture:english
(see common/cultures) -
faith:catholic
(see common/religion/religions) -
religion:christian
(see common/religion/religions)
There are other "call" scopes but these are the ones you'll use in all but the extreme cases. Note, you can use scopes in triggers (which are the next part) along the lines of culture = culture:english
or culture = mother.culture
.
Saved scopes are the easiest to understand. You take a person, use the effect save_scope_as = (scopename)
.
Now, at any time I can call on scope:persona, as shown below, it will get whoever I saved as persona
This adds gold to whoever was saved as persona. The mother.court_owner
part was just to show that it can be called from anywhere in that effect and any effects that are linked to it that execute after it. I'll explain that part later.
Most triggers and effects need a specific scope type for them to work: has_trait
and add_gold
only work for characters, has_innovation
only works for cultures, etc.
Ok, you got through scopes. Now we've got to explain triggers. If you remember my sentence from earlier, the trigger is if he is brave. It's the conditions for which something applies. If you are brave, you gain gold. If the triggers aren't met, nothing happens. Here is a link containing all valid normal triggers (not scripted_triggers.)
https://ck3.paradoxwikis.com/Triggers
Triggers must be contained in a trigger block (for on actions and even options) or a limit block (for everything else.) However, these blocks can't be just anywhere.
This, right above, won't work. This is just a random limit = {} block. What does it apply to? Nothing.
Now here is something that works. An if block must contain a limit = {}. Now, the gold is only added if you have the trait brave while everything outside of the if block is unaffected by the limit. If = {} is going to be the most common thing you will use in this game, without question.
Else blocks can be added after an if block. They trigger if the if block conditions are not met. If you are brave, you gain one hundred gold. Else, you only gain 50.
{width="2.698292869641295in" height="1.458536745406824in"}As previously stated, specific triggers generally only work in specific scopes. So you need to know what will work where. The website I linked above does explain that to you:
{width="6.5in" height="1.2472222222222222in"}
Traits here means what you need for the trigger: eg. blood_legacy_track_perks > 1 vs. dynasty_can_unlock_relevant_perk = yes.
Different triggers have different traits. Some test vs a number, where you have < (less then,) <= (less then or equal to,) = (equal to,) > (greater then,) and >= (greater or equal to.) Some test basic true or false, where the answer is either = yes or = no. Some get strings, like has_holy_site_flag = some_flag. Finally, there are some, typically beginning with any_, like any_vassal.
{width="2.0940419947506563in" height="1.062648731408574in"}
This iterates through all of your direct vassals, and if any of them have the trait brave, the conditions are met. But what if I need all of them to have the trait brave? You add count = all. If you only need 2 to have it, you add count = 2. Count does only work in the any_ triggers though.
{width="2.0940419947506563in" height="1.2293383639545057in"}
{width="2.0836242344706912in" height="1.2918471128608924in"}
Finally we have AND, OR, NOT, NAND and NOR.
{width="2.3229166666666665in" height="1.28125in"}
In this, you either need to have brave OR arrogant. Having both also works. OR statements mean that only one condition ever needs to be met for the code to work. This is very useful, especially if you're making more complex code
{width="2.3232403762029747in" height="1.271010498687664in"}
In this, you need both traits. AND isn't necessary if you just have limit = {}, since that's the default for it. But you do need this inside of OR statements if you want multiple things to be required for it to work
{width="2.6566207349081363in" height="1.8231714785651794in"}
Here, you either need to have over 200 gold or be both brave and arrogant. This is useful for complex triggers.
{width="2.3961679790026245in" height="1.250174978127734in"}
In NOT, one of the triggers must be false. For some reason, only one needs to be false, as NOT is the exact same as NOR instead of NAND. It's stupid, but if you need a complex NOT trigger where multiply things needs to be false, use NAND
{width="2.333659230096238in" height="1.2397561242344708in"}
Here we go. Now you can't have arrogant and brave. If you have either, the trigger fails.
Alright now, effects. These should be the simplest things to cover in the basic section. Effects are what happens to characters in your script. In the sentence metaphor, they're the 100 gold he gains. That said, effects are the most varied things in scripting, and are too diverse for me to cover the specifics.
https://ck3.paradoxwikis.com/Effects
Above is a link to all base effects in the game. There are a few important things to know. Remember any_vassal from triggers? In effects we have random_vassal and every_vassal. I assume you can guess what they do. In random_vassal, we can add a weight so that it's more likely to get a specific one. I'll explain weighting things later on, since it's not one of the basics
{width="2.3232403762029747in" height="1.0418121172353456in"}Here we have essentially what a random_vassal will look like. Note that you can add a limit = {} block into both of these to limit what the possible people are in these. Random_ and every_ are the only place outside of if statements that can have limit = {}.
Honestly, effects don't need a lot to be explained.
{width="2.604529746281715in" height="3.406725721784777in"}Modifiers are kinda confusing in CK3. The devs made three entirely different forms of modifiers, which share the same name but have entirely different purposes. So for the sake of the guide, I'll split this part into weight modifiers, opinion modifiers, and affecting modifiers.
Weight modifiers are what affect the game's choice of an object. What this means is that they affect the chance for the ai to pick one option over another, or how likely an object is to be picked from a random list. In random_ effects, such as random_living character, they are in a weight = {} block, while in events, they are in ai_chance = {} blocks, while in decisions they are in ai_will_do. What does that mean? Look to the left:
In weighting items on a list, the base number only really matters in relation to the other numbers of the weighting. A base of 1 when 5 is added to is far, far more significant than a base of 100 when 5 is added to it. In the first example, it's a 500% increase in likelihood, while in the second it's a 5% increase. The base number has no effect when it's on its own, as the base is the same for everyone, so the chance of getting picked is 1/x where x is the amount of valid people.
In weight modifiers, beyond the base value, you can add the modifier = {}. Inside it, you add the triggers for that specific modifier, and then can either add or multiply more to the weight. For an example, let's take the below picture.
{width="1.7814982502187227in" height="1.0313943569553805in"}The base is 1, then the modifier adds 5 if you have the trait brave. Now your character has a weight of 6 to be picked while everyone else has 1. Statistically, you are 6x more likely than everyone else to be picked by the code. In this scenario, with a random_living_character, you're still very unlikely to be picked, but in smaller pools it can be a major change.
Something I do want to make clear is that not only characters are applicable here, as titles and other scope groups are just as valid.
{width="2.344076990376203in" height="2.4065857392825896in"}Here, the ai has a 60% chance to select option A. and a 40% chance for option B. Events use ai_chance. Meanwhile interactions and decisions use the ai_accept and ai_will_do out of 100 to dictate their percent chance of accepting/using those decisions/events.
{width="2.7816382327209097in" height="1.0522298775153105in"}
Now here are opinion modifiers for weighted modifiers (as opposed to normal opinion modifiers, which affect people's opinion.) This adds the scoped character's opinion of scope:person to the weight/ai_chance. The who should typically always be this unless you want to get someone else's opinion of someone for it. If the multiplier is less than 1 but over 0, it adds the opinion divided, while if it's one it adds the flat opinion. If it's over 1, it multiplies the opinion value, for better or worse. If it's negative, it does essentially the same thing as the positive version would be but flips the sign, going from positive to negative or vice-versa.
Affecting modifiers are called on in common/modifiers, innovations, and cultures. They affect scopes over time instead of an instant thing such as effects.
https://ck3.paradoxwikis.com/Modifier_list
You can see a full list of them on the above link. With these, whenever you have a mult or factor modifier, a value such as 0.2 instead of shrinking whatever it's affecting instead adds 20% to your current gains for that.
{width="3.5317432195975504in" height="1.4272823709536309in"}In the image shown here, we have a modifier called province_governor. The icon is something I'll cover later, but the monthly_county_control_change_add modifier adds 0.1 county control to the county monthly, while the tax_mult = 0.5 means that the holder gets 50% more tax from that county.
The last type of modifier, opinion modifiers, aren't really important here as they are things you can add to people to affect people's opinion of each other.
Ok, so now you know how to read most script in CK3. So where do you put it? Let's go into different folders in CK3.
Common is, well, the most common file you'll be working in in CK3. Common also has the most varied files, and is where the majority of things in CK3 are defined, outside of events, history, and localization. To get to this folder, click browse local files for CK3 and then open the game folder. Common is inside that. Because of how each subfolder defines something different in the game, they all have their own syntax and not all of them actually use script. Most of its subfolders I will not cover, as they either don't fall under this guide or will never be touched by you. That said, most common subsfolders have a .info file that will explain how to make stuff in them. It contains:
- achievements
- activities
- ai_goaltypes
- ai_war_stances
- bookmark_portraits
- bookmarks
- buildings
- casus_belli_groups
- casus_belli_types
- character_backgrounds
- character_interaction_categories
- character_interactions
- coat_of_arms
- combat_effects
- console_groups
- council_positions
- council_tasks
- courtier_guest_management
- culture
- customizable_localization
- deathreasons
- decisions
- defines
- dna_data
- dynasties
- dynasty_house_motto_inserts
- dynasty_house_mottos
- dynasty_houses
- dynasty_legacies
- dynasty_perks
- effect_localization
- ethnicities
- event_backgrounds
- event_themes
- factions
- flavorization
- focuses
- game_concepts
- game_rules
- genes
- governments
- holdings
- hook_types
- important_actions
- landed_titles
- laws
- lease_contracts
- lifestyle_perks
- lifestyles
- men_at_arms_types
- messages
- modifier_icons
- modifiers
- named_colors
- nicknames
- on_action
- opinion_modifiers
- playable_difficulty_infos
- pool_character_selectors
- province_terrain
- religion
- schemes
- script_values
- scripted_character_templates
- scripted_effects
- scripted_guis
- scripted_lists
- scripted_modifiers
- scripted_relations
- scripted_rules
- scripted_triggers
- secret_types
- story_cycles
- succession_election
- suggestions
- terrain_types
- traits
- trigger_localization
- tutorial_lesson_chains
- tutorial_lessons
- vassal_contracts
Of these folders, you will only ever touch maybe 5-6 on a regular basis. Maybe closer to 10 if you are making a total conversion mod.
This subfolder of common has a fairly simple job. Want to guess what it is? If your guess was decisions, you're correct. If it wasn't, I'm questioning your ability to read.
Here, we have an example of a basic decision. Please note that the picture file I added there doesn't exist, but the decision images are all in that folder.
Ok, so: we have the decision key, test_this_decision, which is the key used when you call that decision and the loc key for the decision's name. We also have a desc, which is the description for the loc. There is also a test_this_decision_confirm and test_this_decision_tooltip, but those are defined by the decision key and not the code. Major = yes is not a necessary line, but if you add it the decision becomes a major one (think found a new kingdom)
Ai_potential essentially just tests to see if the ai can use the decision. Copy over your code from is_shown and is_valid. Ai_check_interval asks how often the game checks the decision. Ai_check_interval = 5 means the ai will check every 5 months. If it's set as 0, they will never check. Ai_will_do just sees if the ai will use the decision. Here, if the ai character is brave, they have a 50% chance to use the decision. Otherwise, they won't at all.
Is_shown checks if the decision even shows up for you, while is_valid test if you can do it. Here, the decision shows if you are brave, but you can't use it unless you are also feudal. Neither of these blocks is necessary, and if removed the default for it is just always true.
Cost can cost prestige, piety, and/or gold. You don't need all three in it, I just added it for an example. This block is also unnecessary, and can be removed if you want the decision to be free. Effect = {} should be self-explanatory. Anything you add to it is what happens to you when you use the decision. Hidden_effect = {} is not unique to decisions, btw, and can be added anywhere if you don't want the effects to show up if the effects are being shown to the character.
Character interactions are also a fairly self-explanatory name. Once again, you have the interaction key, here test_interaction, the desc line, an ai_will_do, is_shown, ai_frequency, and ai_potential.
Here, we also have ai_accept, which determines the ai accept chance (out of 100.) If you want it to always be accepted, replace ai_accept = {} with auto_accept = yes. Can_send is the same thing as is_valid from decisions and on_accept is the same as effect = {}. We can also add an on_decline = {} block.
Note that we need to couch all triggers in either scope:actor (the person using the interaction) or scope:recipient (the person targeted.) Interface priority determined how high up in the list it will show in the interactions menu.
Finally, common interaction should generally just be yes. A non-common interaction shoots up to the top of the interface. While what I showed here is the most basic interaction ever, there are multiple other tags you can add to the interaction, some of which I will list below and are explained in the character interactions .info file.
-
is_highlighted = trigger - Should the interaction be highlighted in the menu
-
highlighted_reason = loc_key - Tooltip if highlighted in menu
-
scheme = elope/murder/etc. - The type of scheme the interaction starts
-
popup_on_receive = yes - Have the interaction pop-up for the recipient when received
-
pause_on_receive = yes/no - Pause the game on receive. It usually makes sense to combine it with popup_on_receive
-
use_diplomatic_range = yes/no/trigger - Does this interaction check diplomatic range? Yes by default
-
can_send_despite_rejection = yes -- Ever if the AI's chance of accepting this is 0, it can still be sent. It equals no by default
-
ignores_pending_interaction_block = yes -- Lets you ignore the "ai is already considering a proposal from you." Defaults to no
-
ai_maybe = yes - The ai can reply maybe. Not sure why'd you use this
-
ai_min_reply_days = 4 - Minimum days before ai replies. Useful if you want to control this.
-
ai_max_reply_days = 9 - Maximum days before ai replies
-
greeting = negative/positive - Sets tone in request text (what's sent to the recipient)
-
notification_text = loc_key - Request text (what's sent to the recipient)
-
cooldown = { years = x } - How long until the decision can be taken again?
-
cooldown_against_recipient = { years = x } - How long until the decision can be taken against that specific person again?
These 4 folders are very useful for simplifying your code. What they are is essentially templates for your code. Maybe you're repeating your code often and want to simplify it. So, you make a scripted (whatever your code is) and then can call on that in your code.
{width="3.0420909886264216in" height="3.6463418635170606in"}{width="2.0836242344706912in" height="1.0313943569553805in"}With this scripted effect, I can add the line "basic_scripted_effect = {}" or "basic_scripted_effect = yes" to any effects area, the scopes character will gain 100 gold, 50 piety, and 10 prestige in only one line of code. Scripted triggers are exactly the same, except that they're for triggers. Scripted effects and triggers are what I used above such as add_gold_to_person for examples
Scripted modifiers are like scripted effects but for weighting things. If you have a weight = {} or ai_chance = {} or anything like that, you can add basic_scripted_modifier = yes and all of the modifiers contained within will be applied (assuming the scope meets the conditions.)
Once again, scripted modifiers are useful for preventing unnecessary duplication of linger lines of code.
{width="4.469373359580053in" height="0.8542858705161854in"}Scripted lists are a unique one here. You know every_ruler, random_ruler, any_ruler and the stuff like those? Well, if you ignore the prefixes, you have a list called ruler. Scripted lists mean we can create our own lists, using another as a base and then applying a number of triggers, like the government type. You can consider the conditions = {} block the same thing as a limit = {} block. With this scripted list, I can now call on every_feudal_ruler, random_feudal_ruler, and any_feudal_ruler.
Alright, on to other folders
Script values have one use: dynamic values. You can add, subtract, divide, set a min and max for the values, make it round decimals into integers or leave them as is. You can add other dynamic values to it as well, such as other script values. Whenever you see an "add = sometext," it's adding a script value.
You won't really need script values for basic code, but later on, when you are making more advanced code/mechanics, script values are extremely useful.
Script values don't really do anything on their own, but rather their use is tied to when they are called. Please note that these CANNOT be used in traits and affecting modifiers.
Alright, this will be the last common/ subfolder I will cover in this guide. On actions are a very useful tool in CK3, as the vanilla ones trigger at specific events for characters. What does this mean? I'll show you
{width="2.8337292213473315in" height="1.3856102362204725in"}Specific on actions, which I'll call root on actions, are triggered by the game at specific times. These often link to other on_actions, or branch on actions, which you can see here. On_birthday triggers for a character whenever it's their birthday (as I'm sure you guessed.) We can't create root on actions, but we can create branch ones.
{width="2.135715223097113in" height="2.8441469816272966in"}In an on action, we can have 4 blocks: trigger, effect, events, and on_actions. If a trigger is false, none of the on actions triggers for the scoped character. Effect should be self-explanatory, you add effects to it.
In the events and on_actions blocks, you can add different events and on actions you want the on actions to run. You can list as many as you want, without needing to add more than a line break.
{width="1.6564807524059493in" height="0.7813593613298337in"}Now a major thing you should know if you are editing an on action. If you want to edit what it does, the file that it is located in MUST be named the same as the on action is originally from. If you are editing an on action in a separate file, all you can do is add on_actions for it to branch off into. It's kinda annoying.
Ok, time for events. This, like common, is a main game folder. However, unlike common, this doesn't define all the things in the game. This is just events, plain and simple. As such, subfolders don't really matter here. They serve only as a means of organization, not separating different things that are defined.
For once, here, we have an actual guide on the wiki for how to mod:
https://ck3.paradoxwikis.com/Event_modding
{width="3.0in" height="7.365277777777778in"}So why are events important? Events dictate how a character's life goes, just as much as the wars and diplomacy and all that. They add flavor and make characters dynamic. They are also the very first thing I recommend a new modder start with. They provide a good way to understand the script and are a good way to quickly get a grasp on scripting.
So, let's go over the structure of an event. Here, we have a character event. First, we have a namespace. Every events file [MUST]{.underline} start with one of these, no matter the event type, and every event name [MUST]{.underline} start with the name defined by the namespace, then .numberID. These numbers can be arbitrarily picked.
Type can be character_event or letter_event (I will give an example later on.) Title and desc, and name (for options) define the loc keys for those things. Desc is the actual event description, title the event title, and name is the option's text.
Trigger in the event must be met or the event won't even happen for you, while trigger in the option determines if the option will show. If you're brave, the event will show up, while if you're not zealous, you still won't see the first option but only the second. That said, trigger is not necessary and the game will default to it always showing.
The theme determines the icon and even background, they can be found listed on the website above. Left_portrait, right_portrait, lower_left_portrait, lower_center_portrait, and lower_right_portrait adds characters that show up on the events. Character requires a scope and animations can also be found on the website.
The immediate block runs the effects in it right as the event opens, which is useful for getting scopes before the event shows. Options (which I assume are self-explanatory) require a name and then you can just add effects. Finally, after = {} applies its effects after an option is selected. So here, a character first gets 200 prestige, then either 70 or 20 gold, and then finally you die. (probably not worth it.) You can add an ai_chance = {} block to options, I should note.
{width="2.1878051181102363in" height="1.6356452318460193in"}Hidden events are events that don't show up. They're simple enough and all they need/can have are these three lines/blocks. They can be used if you want something to happen to a character that you don't want said character to see. They're mostly used for maintenance, and there's not much to say about them.
{width="3.448397856517935in" height="5.386167979002624in"}Letter events are the final type of event. They need an opening, which the loc of which goes along the lines of "Greetings, random guy," a description, which is the text of the letter, and a sender, which is the only portrait this type of event can have. They have options, triggers, ai_chances, immediate ={}, and after = {} like normal events as well.
Something that should be understood is that all events need at least one event to show up for a character. Furthermore, if none are valid for a character, the event also won't show up.
Events can be triggered with the effect trigger event, like as shown below:
trigger_event = example_event.1003
Variables and variable lists are probably THE most used thing in script for more advanced modders. They serve as a form of storage on scopes. You can set them on:
-
{width="2.1041666666666665in" height="3.21875in"}characters
-
titles
-
faiths/religions
-
cultures
-
schemes
-
secrets
-
holy orders
-
dynasties
-
houses
-
armies
-
wars
-
etc.
We can save a few things with variables. One, we can save values (either flat numbers or script values.) If you save a number, you can use the command change_variable to edit the value at any time.
You can also save scoped objects with a variable. Think of it like save_scope_as, except the scope lasts beyond the chain of effects or events.
Finally, you can save flags with variables. Flags are essentially just strings of text (you cannot use spaces.) You won't really ever be able to use flags for any real purpose until you start GUI modding, so ignore this part for now.
To fetch the value of a variable in your code, you can use what is essentially a call scope of var:example_var. You can't call a variable saved on another scope, only those saved on the current scope. To remove a variable, we have the remove_variable = varname effect. We can also set_global_variable, change_global_variable, and remove_global_variable, which can be set anywhere and called anywhere with global_var:globalvarname.
{width="2.281568241469816in" height="3.229617235345582in"}Variable lists are essentially a slightly more advanced form of variables. They can save multiple objects, and you can use them like you do a normal list (such as every_ruler.)
You can save the same things on them as you can on variables, except for numerical values. These are very useful for getting a group of characters, titles, or what have you that you want to apply something to en masse. They're also used in GUI a lot.
We can also use any_in_list, which is essentially the same as random_in_list but for triggers. The syntax here is kinda weird, but you get use to it. You cannot use the var:name to fetch the value here, since it can have multiply entries. Once again, we can also make a global version of a variable list, with add_to_global_variable_list, random_in_global_list, every_in_global_list, any_in_global_list, and remove_list_global_variable.
https://ck3.paradoxwikis.com/Scopes
https://ck3.paradoxwikis.com/Effects
https://ck3.paradoxwikis.com/Triggers
https://ck3.paradoxwikis.com/Modifier_list
https://ck3.paradoxwikis.com/Event_modding
The discord invite is a link to the Mod Coop. This is where you can recruit people for your mod, show off stuff, and ask modders for help when you need it. It also serves as a central hub for modding in CK3. You can find invite links to most large mods on it.