# How to write a fast targeted decision by Yard1 So, you want to get on that sweet sweet targeted action, don't you? Have little flags next to the icons, code that's easier to write and maintain, dynamic targets... The whole jazz. But, just after you write one, you get that dreaded feeling, that pit in the stomach... *Oh no. I can feel the game slowing down!*. Well, no more! Just follow these simple practices to have your targeted decisions run as fast as possible! Please note that this short guide focuses only on the performance aspect. ## Limit your targets This part is the most important. You know how `target_trigger` works - it checks countries/states, and those that match the trigger become decision targets. However, unless you limit the possible targets, every country or state in the game will be checked, every day! If you put in expensive triggers in there, it can *really* slow everything down. How can we limit targets, then, so that only a certain subset of entities is checked? ### targets First way is to use `targets = {}`. You simply put in the country tags, state IDs (depending on the type of your decision) or variables inside, and `target_trigger` will run only on those. Common use cases: ``` # we know beforehand that only TAG will be checked, so why check every country if we only want one? target_trigger = { FROM = { tag = TAG } } targets = { TAG } ``` ``` # more than one tag is possible target_trigger = { FROM = { OR = { tag = TAG tag = BAG } } } targets = { TAG BAG } ``` ``` # works with states, too state_target = yes target_trigger = { FROM = { OR = { state = 123 state = 987 } } } targets = { 123 987 } ``` ``` # and with variables, both build in and the ones you set yourself. You can also chain them. target_trigger = { FROM = { owns_state = 123 } } targets = { 123.owner } ``` ``` target_trigger = { FROM = { is_faction_leader = yes is_in_faction_with = ROOT } } targets = { faction_leader } ``` You can also have it target dynamic countries with `targets_dynamic = yes` in addition. ``` # we want to also get the eventual civil war countries (D## tags) target_trigger = { FROM = { OR = { original_tag = TAG original_tag = BAG } } } targets = { TAG BAG } targets_dynamic = yes ``` ### target_array Very similar to `targets`, but instead of predefining the possible values in the file, you can just use an array - again, built-in, or one you've set up yourself. If you use multiple `target_array`s, they will be merged into one. Common use cases: ``` target_trigger = { FROM = { is_in_faction_with = ROOT } } target_array = allies ``` ``` target_trigger = { FROM = { is_subject_of = ROOT } } target_array = subjects ``` ``` target_trigger = { FROM = { OR = { is_in_faction_with = ROOT has_war_with = ROOT } } } target_array = enemies target_array = allies ``` ``` state_target = yes target_trigger = { FROM = { is_controlled_by = ROOT } } target_array = controlled_states ``` ``` state_target = yes target_trigger = { FROM = { is_core_of = TAG } } target_array = TAG.core_states ``` ## Limit your ROOTs Make sure to use `allowed` and `target_root_trigger` to ensure that the target checking stage is only reached when really necessary. `allowed` is only checked on game start and when a country spawns, therefore you should only put in `tag`, `original_tag` and `has_dlc` triggers in it. `target_root_trigger` is checked daily, and is similar to `visible` - however, `visible` is checked *after* targets have been selected 9and thus allows the use of `FROM`), but `target_root_trigger` is checked *before* that (and thus only has `ROOT`). If `target_root_trigger` fails, `target_trigger` won't be ran at all. Compare the following: ``` # BAD my_decision = { # decision is only visible for one country, but is being checked for every country... visible = { tag = TAG has_completed_focus = my_focus } # ...and every country checks every country for targets target_trigger = { FROM = { is_in_faction_with = ROOT } } complete_effect = { add_political_power = 10 } # total checks - n*n, where n is the number of existing countries } ``` ``` # GOOD my_decision = { # first we make sure that the decision will only be checked for TAG allowed = { tag = TAG } # since we don't care about the targets if the focus isn't complete, we avoid having to check the targets and discard all of them with target_root_trigger target_root_trigger = { has_completed_focus = my_focus } # we only check for targets if target_root_trigger is true target_trigger = { FROM = { is_in_faction_with = ROOT } } # and instead of checking all countries on the map and discarding those that don't meet the trigger, we make use of a built in array target_array = allies complete_effect = { add_political_power = 10 } # total checks - 1*m, where m is the number of countries in faction (which is always going to be smaller than n) } ``` ## Remember that targets are only added, and never removed Once a country/state meets the triggers in `target_trigger`, it is added to possible targets. That means `target_trigger` will not be ran for that particular country/state again. Make sure that you put in all checks (such as `exists = yes`) in `visible` instead. ``` # BAD: if a country stop existing later, the decision will still be pickable target_trigger = { FROM = { tag = TAG exists = yes } } ``` ``` # GOOD: we make sure to check if the country exists after it becomes a target target_trigger = { FROM = { tag = TAG } } visible = { FROM = { exists = yes } } ``` ## Use cheaper scopes This section applies to not only targeted decisions, but anything. Below are some common mistakes and how to fix them. ``` # BAD: is ran for every state on the map any_state = { is_controlled_by = PREV has_state_flag = my_flag } ``` ``` # GOOD: is only ran for the states we actually care about - the ones controlled any_controlled_state = { has_state_flag = my_flag } ``` ``` # BAD: O(n) complexity, when we only care about the country that owns that state - and only one country can own a state at a time any_country = { owns_state = 123 has_country_flag = my_flag } ``` ``` # GOOD: scope directly to state's owner (or controller) 123 = { owner = { has_country_flag = my_flag } } ``` ``` # BAD: is ran for every state on the map any_state = { is_core_of = TAG has_state_flag = my_flag } ``` ``` # GOOD: while there isn't a scope for core states, we can use an array any_of_scopes = { array = TAG.core_states tooltip = MY_TOOLTIP # optional, but by default, array operations don't have tooltips. If you define one here, it will also show the triggers inside automatically in addition to whatever is in the localisation. has_state_flag = my_flag } ``` Questions? DM on Discord. *Yard*