• We have updated our Community Code of Conduct. Please read through the new rules for the forum that are an integral part of Paradox Interactive’s User Agreement.
Is it possible to check if rulers are landed? I added some weight to the free captive CB ai will do so that the AI considers using it (no longer stealing heirs of empires safely!). The issue is that it's mostly mercenaries using it, probably because it's one of the only CB available to them, and I don't want them to do that.
 
Another question for dummies, I have no experience with this so I'd like somebody to proof read it.

I want to tell the AI not to use subjugation if it's "big" and the opponent is "small". I wrote this to check that if attacker has real size of at least 4 it must not subjugate realms smaller than realm size 4, but small rulers shouldn't mind subjugating anybody, as well as two checks on the attacker age to push it to use subjugation before dying.

Code:
    ai_will_do = { 
        factor = 1
        modifier = { # Subjugating small realms is only worth if the attacker has a small realm
            factor = 0
            AND = {
                ROOT = {
                    realm_size >= 4
                    }
                FROM = {
                    realm_size <= 4
                    }
                }
            }
        modifier = { # Use your once in a lifetime CB
            factor = 1.5
            ROOT = {
                age > 30
                }
            }
        modifier = { # Use your once in a lifetime CB already
            factor = 2
            ROOT = {
                age > 40
                }
            }

Is this how it should be done?
 
One last question: one thing that annoys me to no end is how the AI picks councilors, sometimes just reshuffling everyone could turn a bad council into something decent. Is this logic hard coded?
 
Is it possible to check if rulers are landed? I added some weight to the free captive CB ai will do so that the AI considers using it (no longer stealing heirs of empires safely!). The issue is that it's mostly mercenaries using it, probably because it's one of the only CB available to them, and I don't want them to do that.
I don't know the answers to your other questions without doing some digging, but this one is easy. Check for is_landed = yes. If you haven't seen it already, check out the Conditions page on the wiki: https://ck2.paradoxwikis.com/Conditions
 
  • 1
Reactions:
One last question: one thing that annoys me to no end is how the AI picks councilors, sometimes just reshuffling everyone could turn a bad council into something decent. Is this logic hard coded?

As far as I'm aware the AI just picks any eligible powerful vassal for any free spot (no idea how it handles the case where there isn't one; pick anyone at all?) and never reshuffles the council.
 
  • 1
Reactions:
Thank you both. Pretty sad, but I'm not surprised as I have already been offered a chancelor job as a 0 diplomacy 20 martial character... These days I commonly turn off spymaster job as it feels a lot more dangerous than commander jobs for low intrigue characters.

If it doesn't fire councilors (I don't remember ever being fired...), I guess runing a script every now and then to bring some sanity to that mess could improve it. It could hardly make it worst if anything.
 
Another question for dummies, I have no experience with this so I'd like somebody to proof read it.

I want to tell the AI not to use subjugation if it's "big" and the opponent is "small". I wrote this to check that if attacker has real size of at least 4 it must not subjugate realms smaller than realm size 4, but small rulers shouldn't mind subjugating anybody, as well as two checks on the attacker age to push it to use subjugation before dying.

Code:
    ai_will_do = { 
        factor = 1
        modifier = { # Subjugating small realms is only worth if the attacker has a small realm
            factor = 0
            AND = {
                ROOT = {
                    realm_size >= 4
                    }
                FROM = {
                    realm_size <= 4
                    }
                }
            }
        modifier = { # Use your once in a lifetime CB
            factor = 1.5
            ROOT = {
                age > 30
                }
            }
        modifier = { # Use your once in a lifetime CB already
            factor = 2
            ROOT = {
                age > 40
                }
            }

Is this how it should be done?
This looks correct to me but, really, the best test would be to run an observer game and check that the AI is making the correct decisions.

Thank you both. Pretty sad, but I'm not surprised as I have already been offered a chancelor job as a 0 diplomacy 20 martial character... These days I commonly turn off spymaster job as it feels a lot more dangerous than commander jobs for low intrigue characters.

If it doesn't fire councilors (I don't remember ever being fired...), I guess runing a script every now and then to bring some sanity to that mess could improve it. It could hardly make it worst if anything.

FWIW, I believe you can make it worse, so you should be a bit careful. (Being fired from the council gives an opinion debuff for quite a long time, so an AI who constantly fires his vassals will become internally unstable.)

However, I agree that it's a decent idea to write some sensible scripts so that AI will use their council properly. (Fire the malcontents unless they are powerful vassals. Make sure your spymaster has high skill and is loyal. Set marshal to train troops if at war. Etc.)
 
  • 1
Reactions:
There are actually two opinion debuffs for someone who is fired from the council. The bigger one lasts a good while, whereas the smaller one Recently fired only gives a malus of -5 opinion and lasts for a much shorter time. However, it's important because while the person has that opinion towards their liege, they cannot be rehired for councilor. So that's something to consider when reshuffling the council.
 
I am trying to implement a sorting algorithm for the "send artifact to offmap" decision, but I seem to have run into a problem: I cannot locate all artifacts of the same type that are owned by the same person. (Eg: All rival_skulls need to receive the same sorting flag.)

To narrow it down to the most basic example:
Code:
namespace = artifact_sorting
character_event = {
	id = artifact_sorting.9002
	hide_window = yes
	is_triggered_only = yes
	immediate = {
		random_artifact = {
			limit = { NOT = { has_artifact_flag = artifact_sorting_test_is_dup } }
			owner = {
				any_artifact = {
					limit = { is_artifact_same_type_as = PREVPREV }
					set_artifact_flag = artifact_sorting_test_is_dup
				}
			}
		}
	}
}

When you run this event for a character who has two of the same artifact (eg. new game -> console -> add_artifact X -> add_artifact X -> event artifact_sorting.9002 ), I would expect both artifacts to be given the artifact_sorting_test_is_dup flag. But it doesn't work - no artifacts are given the flag.

As far as I can tell, the issue seems to be with my usage of is_artifact_same_type_as - but I can't see what I've done wrong.

Any thoughts?
 
Last edited:
I am trying to implement a sorting algorithm for the "send artifact to offmap" decision, but I seem to have run into a problem: I cannot locate all artifacts of the same type that are owned by the same person. (Eg: All rival_skulls need to receive the same sorting flag.)

To narrow it down to the most basic example:
Code:
namespace = artifact_sorting
character_event = {
	id = artifact_sorting.9002
	hide_window = yes
	is_triggered_only = yes
	immediate = {
		random_artifact = {
			limit = { NOT = { has_artifact_flag = artifact_sorting_test_is_dup } }
			owner = {
				any_artifact = {
					limit = { is_artifact_same_type_as = PREVPREV }
					set_artifact_flag = artifact_sorting_test_is_dup
				}
			}
		}
	}
}

When you run this event for a character who has two of the same artifact (eg. new game -> console -> add_artifact X -> add_artifact X -> event artifact_sorting.9002 ), I would expect both artifacts to be given the artifact_sorting_test_is_dup flag. But it doesn't work - no artifacts are given the flag.

As far as I can tell, the issue seems to be with my usage of is_artifact_same_type_as - but I can't see what I've done wrong.

Any thoughts?

Does it work if you use artifact_owner instead of owner?
 
I am trying to implement a sorting algorithm for the "send artifact to offmap" decision, but I seem to have run into a problem: I cannot locate all artifacts of the same type that are owned by the same person. (Eg: All rival_skulls need to receive the same sorting flag.)

To narrow it down to the most basic example:
Code:
namespace = artifact_sorting
character_event = {
    id = artifact_sorting.9002
    hide_window = yes
    is_triggered_only = yes
    immediate = {
        random_artifact = {
            limit = { NOT = { has_artifact_flag = artifact_sorting_test_is_dup } }
            owner = {
                any_artifact = {
                    limit = { is_artifact_same_type_as = PREVPREV }
                    set_artifact_flag = artifact_sorting_test_is_dup
                }
            }
        }
    }
}

When you run this event for a character who has two of the same artifact (eg. new game -> console -> add_artifact X -> add_artifact X -> event artifact_sorting.9002 ), I would expect both artifacts to be given the artifact_sorting_test_is_dup flag. But it doesn't work - no artifacts are given the flag.

As far as I can tell, the issue seems to be with my usage of is_artifact_same_type_as - but I can't see what I've done wrong.

Any thoughts?
I assume you've already checked to make sure the event is actually firing and in Validator.

The only place I can find is_artifact_same_type_as in the vanilla game is in scripted_triggers, where it goes like this.
Code:
selected_ingredient_1_and_2_are_same = {
    #Checks whether the ingredients selected are same type, such as two Hibiscus (if so, returns true)...
    any_artifact = {
        has_artifact_flag = selected_ingredient_1
        ROOT = {
            any_artifact = {
                has_artifact_flag = selected_ingredient_2
                is_artifact_same_type_as = PREVPREV
            }
        }
    }
}

The main difference, other than no limit = {} clause due to using any_artifact instead of random_artifact, is that it uses ROOT instead of owner, so maybe you could try that? Since sometimes scopes are finicky for certain conditions.

As an aside, the only place I see that particular scripted trigger used is in a single Hermetics society event, where it's used several times as either a trigger condition for an option or as a trigger condition for one option text/name/localization over another.

It's also possible that this is one of the things that works for any_ but not for random_ for no apparent reason. I'm pretty sure I've come across at least one condition that works that way before, frustratingly.
 
EDIT2: This condition might only work in triggers and not effects. See the larger EDIT2 section at the end of this post for more details.

---

I assume you've already checked to make sure the event is actually firing and in Validator.

Good point. The Validator's only error is that the event is triggered only but is never called. (IE: Not actually an error in this context.)

Re: Actually firing: See below.

The only place I can find is_artifact_same_type_as in the vanilla game is in scripted_triggers, where it goes like this.
Code:
selected_ingredient_1_and_2_are_same = {
    #Checks whether the ingredients selected are same type, such as two Hibiscus (if so, returns true)...
    any_artifact = {
        has_artifact_flag = selected_ingredient_1
        ROOT = {
            any_artifact = {
                has_artifact_flag = selected_ingredient_2
                is_artifact_same_type_as = PREVPREV
            }
        }
    }
}

The main difference, other than no limit = {} clause due to using any_artifact instead of random_artifact, is that it uses ROOT instead of owner, so maybe you could try that? Since sometimes scopes are finicky for certain conditions.

As an aside, the only place I see that particular scripted trigger used is in a single Hermetics society event, where it's used several times as either a trigger condition for an option or as a trigger condition for one option text/name/localization over another.

It's also possible that this is one of the things that works for any_ but not for random_ for no apparent reason. I'm pretty sure I've come across at least one condition that works that way before, frustratingly.
Does it work if you use artifact_owner instead of owner?
Some good ideas there. I wrote (what I believe is) a comprehensive test series:
Code:
namespace = artifact_sorting
character_event = {
    id = artifact_sorting.9001
    hide_window = yes
    is_triggered_only = yes
    immediate = {
        set_character_flag = artifact_sorting_test1a
        random_artifact = {
            limit = { NOT = { has_artifact_flag = artifact_sorting_test1b } }
            set_artifact_flag = artifact_sorting_test1c
            owner = {
                set_character_flag = artifact_sorting_test1d
                any_artifact = {
                    set_artifact_flag = artifact_sorting_test1e
                }
                any_artifact = {
                    limit = { is_artifact_same_type_as = PREVPREV }
                    set_artifact_flag = artifact_sorting_test1b
                }
            }
        }
    }
}
character_event = {
    id = artifact_sorting.9002
    hide_window = yes
    is_triggered_only = yes
    immediate = {
        set_character_flag = artifact_sorting_test2a
        random_artifact = {
            limit = { NOT = { has_artifact_flag = artifact_sorting_test2b } }
            set_artifact_flag = artifact_sorting_test2c
            artifact_owner = {
                set_character_flag = artifact_sorting_test2d
                any_artifact = {
                    set_artifact_flag = artifact_sorting_test2e
                }
                any_artifact = {
                    limit = { is_artifact_same_type_as = PREVPREV }
                    set_artifact_flag = artifact_sorting_test2b
                }
            }
        }
    }
}
character_event = {
    id = artifact_sorting.9003
    hide_window = yes
    is_triggered_only = yes
    immediate = {
        set_character_flag = artifact_sorting_test3a
        random_artifact = {
            limit = { NOT = { has_artifact_flag = artifact_sorting_test3b } }
            set_artifact_flag = artifact_sorting_test3c
            ROOT = {
                set_character_flag = artifact_sorting_test3d
                any_artifact = {
                    set_artifact_flag = artifact_sorting_test3e
                }
                any_artifact = {
                    limit = { is_artifact_same_type_as = PREVPREV }
                    set_artifact_flag = artifact_sorting_test3b
                }
            }
        }
    }
}
character_event = {
    id = artifact_sorting.9004
    hide_window = yes
    is_triggered_only = yes
    immediate = {
        set_character_flag = artifact_sorting_test4a
        any_artifact = {
            limit = { NOT = { has_artifact_flag = artifact_sorting_test4b } }
            set_artifact_flag = artifact_sorting_test4c
            owner = {
                set_character_flag = artifact_sorting_test4d
                any_artifact = {
                    set_artifact_flag = artifact_sorting_test4e
                }
                any_artifact = {
                    limit = { is_artifact_same_type_as = PREVPREV }
                    set_artifact_flag = artifact_sorting_test4b
                }
            }
        }
    }
}
character_event = {
    id = artifact_sorting.9005
    hide_window = yes
    is_triggered_only = yes
    immediate = {
        set_character_flag = artifact_sorting_test5a
        any_artifact = {
            limit = { NOT = { has_artifact_flag = artifact_sorting_test5b } }
            set_artifact_flag = artifact_sorting_test5c
            artifact_owner = {
                set_character_flag = artifact_sorting_test5d
                any_artifact = {
                    set_artifact_flag = artifact_sorting_test5e
                }
                any_artifact = {
                    limit = { is_artifact_same_type_as = PREVPREV }
                    set_artifact_flag = artifact_sorting_test5b
                }
            }
        }
    }
}
character_event = {
    id = artifact_sorting.9006
    hide_window = yes
    is_triggered_only = yes
    immediate = {
        set_character_flag = artifact_sorting_test6a
        any_artifact = {
            limit = { NOT = { has_artifact_flag = artifact_sorting_test6b } }
            set_artifact_flag = artifact_sorting_test6c
            ROOT = {
                set_character_flag = artifact_sorting_test6d
                any_artifact = {
                    set_artifact_flag = artifact_sorting_test6e
                }
                any_artifact = {
                    limit = { is_artifact_same_type_as = PREVPREV }
                    set_artifact_flag = artifact_sorting_test6b
                }
            }
        }
    }
}
Results (after adding 2 pairs of artifacts to a character, and running all 6 events):
  • As expected:
    • Every event is firing (every artifact_sorting_test*a is present on the character)
    • The initial any_artifact/random_artifact scope change (including the limit) is locating an artifact (every artifact_sorting_test*c is present on at least one artifact) (and, as expected, only present on 1 artifact for tests 1-3, but present on all for tests 4-6)
    • ROOT, owner and artifact_owner can all be used, from both any_artifact and random_artifact to access the artifact's owner (every artifact_sorting_test*d is present on the character)
    • After referring back to the owner, the any_artifact scope is correctly locating every artifact owned by that character (every artifact_sorting_test*e flag is present on every artifact)
  • Anomaly:
    • Adding limit = { is_artifact_same_type_as = PREVPREV } to the previous test leads to no artifacts being returned (there are no artifacts with flag artifact_sorting_test*b
Screenshots of results (in case I'm missing anything):
20241211005829_1.jpg20241211005918_1.jpg20241211005920_1.jpg20241211005922_1.jpg20241211005924_1.jpg

Conclusion: Some part of limit = { is_artifact_same_type_as = PREVPREV } is failing.

---

EDIT: Maybe is_artifact_same_type_as only works in triggers (ie. does not work in effects)? I'll try to think of a way to test that...

---

EDIT2: Seems like my hunch was correct:
Code:
character_event = {
    id = artifact_sorting.9007
    hide_window = yes
    is_triggered_only = yes
    immediate = {
        set_character_flag = artifact_sorting_test7a
        random_artifact = {
            set_artifact_flag = artifact_sorting_test7b
        }
        if = {
            limit = {
                any_artifact = {
                    has_artifact_flag = artifact_sorting_test7b
                    owner = {
                        any_artifact = {
                            NOT = { has_artifact_flag = artifact_sorting_test7b }
                            is_artifact_same_type_as = PREVPREV
                        }
                    }
                }
            }
            set_character_flag = artifact_sorting_test7c
        }
    }
}
Results:
  • On a character with 2 pairs and 1 singleton artifact, the character received flags 7a & 7c, and one of the paired artifacts received flag 7b
Conclusion:
  • is_artifact_same_type_as works as intended in triggers
Next steps:
  • Can you think of a definitive proof/disproof of the idea that "is_artifact_same_type_as doesn't work in effects"?
  • Can you think of a good way to add the same flag to every artifact of the same type?
 
Last edited:
Next steps:
  • Can you think of a definitive proof/disproof of the idea that "is_artifact_same_type_as doesn't work in effects"?
  • Can you think of a good way to add the same flag to every artifact of the same type?
Well, I really hope that you guys have got some good ideas on this, because the alternative is quite disgusting:
This is a proof of concept, without an outer loop (ie. you have to run the event multiple times), and supporting a maximum of 5 types of artifact.

It works.... but calling it "inelegant" would be generous... and the final version (supporting 999 artifact types on one character) can only be worse...

Code:
character_event = {
    id = artifact_sorting.9008
    hide_window = yes
    is_triggered_only = yes
    immediate = {
      
        # Count the number of times this event has been run
        if = {
            limit = { check_variable = { which = artifact_sorting_test8_counter value == 0 } }
            set_variable = { which = artifact_sorting_test8_counter value = 1 }
        }
        else = {
            change_variable = { which = artifact_sorting_test8_counter value = 1 }
        }
      
        any_artifact = {
            clr_artifact_flag = artifact_comparison_first
            clr_artifact_flag = artifact_comparison_second
            clr_artifact_flag = artifact_comparison_checked
        }
      
        random_artifact = {
            limit = {
                NOR = {
                    has_artifact_flag = artifact_sort_group_1
                    has_artifact_flag = artifact_sort_group_2
                    has_artifact_flag = artifact_sort_group_3
                    has_artifact_flag = artifact_sort_group_4
                    has_artifact_flag = artifact_sort_group_5
                }
            }
            set_artifact_flag = artifact_comparison_first
            if = {
                limit = { owner = { check_variable = { which = artifact_sorting_test8_counter value == 1 } } }
                set_artifact_flag = artifact_sort_group_1
            }
            else_if = {
                limit = { owner = { check_variable = { which = artifact_sorting_test8_counter value == 2 } } }
                set_artifact_flag = artifact_sort_group_2
            }
            else_if = {
                limit = { owner = { check_variable = { which = artifact_sorting_test8_counter value == 3 } } }
                set_artifact_flag = artifact_sort_group_3
            }
            else_if = {
                limit = { owner = { check_variable = { which = artifact_sorting_test8_counter value == 4 } } }
                set_artifact_flag = artifact_sort_group_4
            }
            else_if = {
                limit = { owner = { check_variable = { which = artifact_sorting_test8_counter value == 5 } } }
                set_artifact_flag = artifact_sort_group_5
            }
        }
      
        while = {
            limit = {
                any_artifact = {
                    NOR = {
                        has_artifact_flag = artifact_sort_group_1
                        has_artifact_flag = artifact_sort_group_2
                        has_artifact_flag = artifact_sort_group_3
                        has_artifact_flag = artifact_sort_group_4
                        has_artifact_flag = artifact_sort_group_5
                    }
                    NOR = {
                        has_artifact_flag = artifact_comparison_first
                        has_artifact_flag = artifact_comparison_checked
                    }
                }
            }
            random_artifact = {
                limit = {
                    NOR = {
                        has_artifact_flag = artifact_sort_group_1
                        has_artifact_flag = artifact_sort_group_2
                        has_artifact_flag = artifact_sort_group_3
                        has_artifact_flag = artifact_sort_group_4
                        has_artifact_flag = artifact_sort_group_5
                    }
                    NOR = {
                        has_artifact_flag = artifact_comparison_first
                        has_artifact_flag = artifact_comparison_checked
                    }
                }
                set_artifact_flag = artifact_comparison_second
            }
            if = {
                limit = {
                    any_artifact = {
                        has_artifact_flag = artifact_comparison_first
                        owner = {
                            any_artifact = {
                                has_artifact_flag = artifact_comparison_second
                                is_artifact_same_type_as = PREVPREV
                            }
                        }
                    }
                }
                any_artifact = {
                    limit = { has_artifact_flag = artifact_comparison_second }
                    if = {
                        limit = { owner = { check_variable = { which = artifact_sorting_test8_counter value == 1 } } }
                        set_artifact_flag = artifact_sort_group_1
                    }
                    else_if = {
                        limit = { owner = { check_variable = { which = artifact_sorting_test8_counter value == 2 } } }
                        set_artifact_flag = artifact_sort_group_2
                    }
                    else_if = {
                        limit = { owner = { check_variable = { which = artifact_sorting_test8_counter value == 3 } } }
                        set_artifact_flag = artifact_sort_group_3
                    }
                    else_if = {
                        limit = { owner = { check_variable = { which = artifact_sorting_test8_counter value == 4 } } }
                        set_artifact_flag = artifact_sort_group_4
                    }
                    else_if = {
                        limit = { owner = { check_variable = { which = artifact_sorting_test8_counter value == 5 } } }
                        set_artifact_flag = artifact_sort_group_5
                    }
                }
            }
            any_artifact = {
                limit = { has_artifact_flag = artifact_comparison_second }
                clr_artifact_flag = artifact_comparison_second
                set_artifact_flag = artifact_comparison_checked
            }
        }
      
        any_artifact = {
            clr_artifact_flag = artifact_comparison_first
            clr_artifact_flag = artifact_comparison_second
            clr_artifact_flag = artifact_comparison_checked
        }
    }
}
 
Nothing easy is coming to mind. If it only works in triggers, maybe you could fire events to an AI that will always exist (such as the Pope), then scope the player and his artifacts and have options for said AI defined by triggers that check is_same_type_of_artifact_as

Never mind, what you figured out is probably easier than that.
 
Follow-up question: Is there any reliable way to rearrange artifacts in your inventory (ie. the window which pops out to the side of your character profile)?

Eg: Move all armor to the top of the window, followed by all weapons, followed by everything else.
 
Does the condition realm_levies include non-levy troops in its check? Such as retinue troops or event-spawned units.

The wiki just says "ruler's current total realm levies" and I don't see any other similar condition.
 
How does the selection of HF reformation features work for the AI; I understand the AI weights, but is there an order to it?

I am primarily wondering about cases like "Doctrine A requires Nature B and Leadership C", because the AI being ineligible for something as a consewuence of always going e.g. Nature -> Doctrine 1 -> Doctrine 2 -> Leadership would be good to know.
 
Is there a way to condense the titles of someone who holds a lot of titles equal to his or her highest level title? I tried making a minor title with show_as_title = yes and while that does give them the appropriate prefix from the minor title, mousing over their portrait still shows the entire list of their highest-level titles they hold, which is really cluttered and messy.
 
Is there a way to condense the titles of someone who holds a lot of titles equal to his or her highest level title? I tried making a minor title with show_as_title = yes and while that does give them the appropriate prefix from the minor title, mousing over their portrait still shows the entire list of their highest-level titles they hold, which is really cluttered and messy.

In the CHARACTER_TOOLTIP loc string, replace GetHighestTitles with some custom loc like the below

Code:
defined_text = {
    name = GetHightestTitlesShorter
    use_first_valid = yes
    
    text = {
        trigger = {
            NOT = {
                any_demesne_title = {
                    tier = PREV
                    count >= 5 # Or whatever
                }
            }
        }
        localisation_key = GetHightestTitlesActual # "[This.GetHightestTitles]"
    }
    
    
    text = {
        trigger = {
            any_demesne_title = {
                tier = PREV
                count >= 5 # Or whatever
            }
        }
        localisation_key = GetHightestTitlesSummary # "[This.GetTitle] of [This.PrimaryTitle.GetName] and other titles", or perhaps "[This.GetTitle] of [This.PrimaryTitle.GetName], of [<some other title, if scopeable in loc>.GetName], of [<third title>.GetName], etc., etc."
    }
}

There are a couple of places where it would break down, however:

- Anyone with a primary title with a custom ruler title (e.g. the Principality of Antioch) would in the second case be e.g. "Prince of Antioch, of Sicily, of Jerusalem, etc., etc.", which might be weird.

- Rel heads would always get weird if they hold a higher title, e.g. "Bob, Fylkir of Britannia" instead of "Fylkir Bob, Emperor of Britannia". Might be possible to work around with a special rel head version of the custom loc, however.

- Though very rare (I think vanilla only uses it for Temujin), any ruler with a special character title would possibly break in a similar manner to the above, and such titles persist after (landed) title loss unless cleared in script, meaning a "has_landed_title = <title>" wouldn't work (and Temujin would break even when holding titles because nomadic titles are dynamic and he'd fail "has_landed_title = e_mongol_empire" as a result).
 
  • 1
Reactions:
In the CHARACTER_TOOLTIP loc string, replace GetHighestTitles with some custom loc like the below

Code:
defined_text = {
    name = GetHightestTitlesShorter
    use_first_valid = yes
   
    text = {
        trigger = {
            NOT = {
                any_demesne_title = {
                    tier = PREV
                    count >= 5 # Or whatever
                }
            }
        }
        localisation_key = GetHightestTitlesActual # "[This.GetHightestTitles]"
    }
   
   
    text = {
        trigger = {
            any_demesne_title = {
                tier = PREV
                count >= 5 # Or whatever
            }
        }
        localisation_key = GetHightestTitlesSummary # "[This.GetTitle] of [This.PrimaryTitle.GetName] and other titles", or perhaps "[This.GetTitle] of [This.PrimaryTitle.GetName], of [<some other title, if scopeable in loc>.GetName], of [<third title>.GetName], etc., etc."
    }
}

There are a couple of places where it would break down, however:

- Anyone with a primary title with a custom ruler title (e.g. the Principality of Antioch) would in the second case be e.g. "Prince of Antioch, of Sicily, of Jerusalem, etc., etc.", which might be weird.

- Rel heads would always get weird if they hold a higher title, e.g. "Bob, Fylkir of Britannia" instead of "Fylkir Bob, Emperor of Britannia". Might be possible to work around with a special rel head version of the custom loc, however.

- Though very rare (I think vanilla only uses it for Temujin), any ruler with a special character title would possibly break in a similar manner to the above, and such titles persist after (landed) title loss unless cleared in script, meaning a "has_landed_title = <title>" wouldn't work (and Temujin would break even when holding titles because nomadic titles are dynamic and he'd fail "has_landed_title = e_mongol_empire" as a result).
Thanks, this worked perfectly.

Another side effect I notice, of the second case, is that minor titles no longer show up. Apparently the default GetHighestTitles also includes minor titles, so for GetHighestTitlesSummary they're not included. I don't see a localisation command for getting minor titles, is there one? It's a worthwhile tradeoff to me, but if there is a way to work minor titles into my new GetHighestTitlesSummary, that'd be good.