Old World Event Modding Guide

Author: Solver

Events are one of the key elements of Old World. They provide a lot of replay value due to making each game different, they add depth due to having interesting choices to make, and they can give Old World a fair amount of role-playing flavor. The game’s event system handles not only the many random events, but also the in-game tutorial and mechanics like ancient ruins.

Creating your own events is one of the many ways to mod Old World, and this guide will explain how the event system works, and how to use it to create your own events.

There are two methods for creating or editing events. One is to edit XML files by hand, the other is to use the in-game event browser, accessible from the Tools menu. It’s up to you which method to use. The event browser simplifies some aspects, but has its own bugs and quirks. This guide will mostly show XML code, as it’s well suited to the text format. The event browser is an UI for displaying these fields, so if you know what something is called in XML, you’ll easily find it in the event browser, and vice versa.

The basics of how to create a mod, and how mods work in Old World, are not in the scope of this guide. Your event mod will be a mod with its own Infos folder, containig files such as eventStory-add.xml. That file would have the same structure as the base game’s own eventStory.xml, which is intuitive enough, but you should refer to other guides for information on how exactly mods are stored and loaded.

Special thanks to KKCoder at Mohawk for clarifying multiple questions that arose while writing this guide!

Event Structure

Let’s jump straight into it. What is an event in Old World, and what are its constituent parts? Here are the main concepts:

There are more concepts like Event Triggers and Event Links, but the five above are the most important ones, and four of them (except Subject Relations) will be needed for almost all events.

Let’s imagine a very simple event. When it triggers, it gives a choice between receiving some Iron and receiving some Stone. What components would it need then?

Only one Subject, the player, would be needed for this event. Two Event Options would provide the choices, and each Option would have an Event Bonus that grants Iron or Stone, respectively. Finally, the Event Story would just tie all of it together, having the Subject and the two Options.

Creating a simple Event

To understand what the constituent parts of an event actually look like, let’s go ahead and create a simple event as described above. We can start with the following in your eventStory-add.xml file

<Entry>
    <zType>EVENTSTORY_MY_FIRST_EVENT</zType>
    <Name>TEXT_EVENTSTORY_MY_FIRST_EVENT_TITLE</Name>
    <Text>TEXT_EVENTSTORY_MY_FIRST_EVENT</Text>
    <aeSubjects>
            <zValue>SUBJECT_PLAYER_US</zValue>
    </aeSubjects>
</Entry>

Just like in other Old World files, zType is the unique identifier for your story. Name and Text are the event’s title and text respectively, with tags that refer to text-eventStory-add.xml and text-eventStoryTitle-add.xml. The in-game event editor would auto-link those for you, otherwise you get to create the text later, but for we’ll examine the non-text parts. The story has a list of Subjects, aeSubjects, and each entry on that list is some kind of Subject from the game’s subject.xml. You can define your own Subjects for more advanced events, but the game’s own set of Subjects provides quite a broad selection.

In the example above, we’re using only SUBJECT_PLAYER_US, a Subject that refers to the nation we’re playing as. It’s probably the most common Subject that shows up in events. Since we only have this one Subject, we don’t need any Subject Relations, and we’re not using any other optional fields of the Event Story for now. The Story is already valid, as in it could be triggered by the game, but it needs Options. Those are also written as a list, aeOptions. The complete Story definition would be as follows:

<Entry>
    <zType>EVENTSTORY_MY_FIRST_EVENT</zType>
    <Name>TEXT_EVENTSTORY_MY_FIRST_EVENT_TITLE</Name>
    <Text>TEXT_EVENTSTORY_MY_FIRST_EVENT</Text>
    <aeSubjects>
            <zValue>SUBJECT_PLAYER_US</zValue>
    </aeSubjects>
    <aeOptions>
            <zValue>EVENTOPTION_MY_FIRST_EVENT_OPTION_IRON</zValue>
            <zValue>EVENTOPTION_MY_FIRST_EVENT_OPTION_STONE</zValue>
    </aeOptions>
</Entry>

We added references to two Options. The convention in Old World is that Event Option zType contains the event zType, and then a suffix that begins with OPTION_. You can use something like OPTION_0 and OPTION_1 (that’s what the in-game event editor auto-generates), or you can also use more descriptive suffixes like OPTION_IRON and OPTION_STONE.

An Event Story refers to Options, and what we added above are the references, not the Options themselves. Now we need to create the options in eventOptions-add.xml. They could look like this:

<Entry>
    <zType>EVENTOPTION_MY_FIRST_EVENT_OPTION_IRON</zType>
    <Text>TEXT_EVENTOPTION_MY_FIRST_EVENT_OPTION_IRON</Text>
    <aeBonuses>
            <zValue>BONUS_GAIN_IRON</zValue>
    </aeBonuses>
</Entry>
<Entry>
    <zType>EVENTOPTION_MY_FIRST_EVENT_OPTION_STONE</zType>
    <Text>TEXT_EVENTOPTION_MY_FIRST_EVENT_OPTION_STONE</Text>
    <aeBonuses>
            <zValue>BONUS_GAIN_STONE</zValue>
    </aeBonuses>
</Entry>

Options are usually simple. They have a Text tag for the text that will be displayed on the button, and they refer to a list of bonuses. It is these bonuses that have actual gameplay effects, as noted previously, and a bit confusingly, they’re in a file called bonus-event-add.xml, a slightly different naming pattern.

The first Option we created refers to BONUS_GAIN_IRON as its bonus, so let’s create that bonus in bonus-event-add.xml:

<Entry>
    <zType>BONUS_GAIN_IRON</zType>
    <aiGlobalYieldsBase>
            <Pair>
                    <zIndex>YIELD_IRON</zIndex>
                    <iValue>100</iValue>
            </Pair>
    </aiGlobalYieldsBase>
</Entry>

The bonus entry doesn’t contain any text, it’s just a gameplay effect. aiGlobalYieldBase is a bonus effect for gaining, or losing, one of the global yields, so the above bonus definition would give 100 Iron. Create another entry for the Stone option, and you have everything that’s needed for an event, except for text.

To complete the event, we’ll briefly create the necessary text items, but only in the simplest possible way.

In text-eventStoryTitle-add.xml:

<Entry>
    <zType>TEXT_EVENTSTORY_MY_FIRST_EVENT_TITLE</zType>
    <English>Free Stuff!</English>
</Entry>

In text-eventStory-add.xml, the main event text appears:

<Entry>
    <zType>TEXT_EVENTSTORY_MY_FIRST_EVENT</zType>
    <English>Things have happened and you're allowed to get some free stuff. Do you want some Iron or some Stone?</English>
</Entry>

Text for event options goes into text-eventOption-add.xml

<Entry>
    <zType>TEXT_EVENTOPTION_MY_FIRST_EVENT_OPTION_STONE</zType>
    <English>I'd like some stone</English>
</Entry>
<Entry>
    <zType>TEXT_EVENTOPTION_MY_FIRST_EVENT_OPTION_IRON</zType>
    <English>I'd like some iron</English>
</Entry>

Whether you’re creating events by editing XML files or not, the in-game editor’s preview feature is highly useful, and you should make use of it. If you load your mod in the event browser, select the event and click Preview, you can see that the event appears as intended, and that the options provide what you expect them to - just move your mouse over the option buttons. Note that this preview feature is not quite the same as being in-game “for real”, so some more sophisticated requirements get ignored or some subjects may be shown incorrectly.

The other very useful thing in the event browser is the “Run Tests” button. It makes the browser run several built-in tests on the mod’s events, which will identify an array of possible mistakes, such as invalid subjects or impossible triggers.

The first event displayed
The first event displayed

A full set of files that provides this one event is available for download here.


NOTE: Currently, Old World requires each -add.xml file to begin with an empty <Entry> of the appropriate type. So eventStory-add.xml should begin with an empty entry that you can copy from the start of the game’s main eventStory.xml file, and so on. This also applies to text-* files. You can see how this pattern applies by downloading the sample mod from above.


Doing more with Subjects

The choice of Subjects for an Event Story has a lot of impact on when the Story can trigger and what it can do, so let’s examine subjects and their interaction a bit more.

One important thing to understand about Subjects is that they also act as conditions. The game need to find suitable candidates for all subjects in a Story, otherwise the Story will not be triggered. As such, you should define Subjects not only to apply bonuses to them, but also to specify the conditions under which the Story you wrote can trigger. For example, the subject SUBJECT_SPOUSE_OF_LEADER_US refers to the living spouse of your current leader. If the leader is unmarried, or if the spouse is dead, then no suitable candidate exists for SUBJECT_SPOUSE_OF_LEADER_US and the Story will not trigger.

A simple example of a second Subject in a story would be some trade event involving yourself and another nation. The Subject SUBJECT_PLAYER_THEM picks another nation that the player has met. If a Story defines its aeSubjects as follows

<aeSubjects>
    <zValue>SUBJECT_PLAYER_US</zValue>
    <zValue>SUBJECT_PLAYER_THEM</zValue>
</aeSubjects>

then it will only be possible to trigger after meeting another nation. Simple enough.

Having multiple Subjects also has an important effect on how Event Options work. Each Option will need as many references to Bonuses as there are subjects, and they will apply in the same order. For an event with two Subjects, the Option entry should contain a definition like this

    <aeBonuses>
            <zValue>NONE</zValue>
            <zValue>BONUS_GAIN_IRON</zValue>
    </aeBonuses>

If the Option is chosen, then the first bonus will apply to the first subject, the second bonus to the second subject, and so on. In the example above, NONE (no bonus) would apply to SUBJECT_PLAYER_US, and BONUS_GAIN_IRON would apply to SUBJECT_PLAYER_THEM - so we’ve defined an option that would give the other player some Iron.

It’s very important to keep track of the order of Subjects and Bonuses. Having the wrong order will apply the wrong effects or, more often, fail to apply any effects whatsoever.

When creating your own events, make use of the data already present in the base game! If you’re making an event representing a trade proposal, similar to the above, it doesn’t make much sense for the proposal to trigger for nations you’re at war with. Turns out, the game already has a suitable subject. Instead of SUBJECT_PLAYER_THEM you can use SUBJECT_LEADER_PEACE_OR_TRUCE, which will pick a leader you’re not at war with.


NOTE: It’s often pretty clear what subjects some bonus effects can apply to. Culture in Old World is a per-city yield, so a bonus granting culture would apply to City subjects. A bonus that increases Wisdom could only apply to characters, since Wisdom is one of the character ratings. This makes sense.

Treatment of the Player and Leader Subjects is a bit special though. Player subjects represent the nation, Leader subjects represent the current leader. But, to make things easier, many bonuses that really apply to the nation as a whole (such as a lump sum of money) can also be applied to Leader subjects in events.


Subject Extras

Alright, how about setting additional requirements on Subjects? This is where the Subject Relations and their lighter cousin, Subject Extras come in. You already know that the SUBJECT_SPOUSE_OF_LEADER_US selects the leader’s spouse. What if you want an event that triggers only if the spouse is estranged from the leader? The game also has a ready subject for that, SUBJECT_ESTRANGED_FROM_LEADER, which applies to any character estranged from the current leader.

Doing the following would not work:

<aeSubjects>
    <zValue>SUBJECT_SPOUSE_OF_LEADER_US</zValue>
    <zValue>SUBJECT_ESTRANGED_FROM_LEADER</zValue>
</aeSubjects>

That snippet defines two Subjects, but they can be different. The story could trigger if the leader has a spouse, and also an estranged sibling. Or even if a foreign leader is estranged. The game finds a candidate for each subject independently, which wouldn’t give you the “estranged spouse” condition.

In cases like this, the answer lies in Subject Extra tests. Each Subject in a story can be tested to see if it also meets the requirements for another subject. If not, then the candidate is discarded. So for the estranged spouse case, you should only have one Subject, the spouse, and then define an additional test as follows:

<aeSubjects>
    <zValue>SUBJECT_SPOUSE_OF_LEADER_US</zValue>
</aeSubjects>
<SubjectExtras>
    <Pair>
            <First>0</First>
            <Second>SUBJECT_ESTRANGED_FROM_LEADER</Second>
    </Pair>
</SubjectExtras>

Within SubjectExtras, each element should be a Pair. A Pair holds two values, in this case First and Second. You may recognize that you already saw a Pair for bonuses that grant resources. For a SubjectExtras test, the First value should be the index of the subject to which it applies, starting the count at 0. The SUBJECT_SPOUSE_OF_LEADER_US subject is the first (and only) subject in this story, so it has index 0. The Second value is another Subject type that the first Subject is also expected to fit.

More naturally, the Pair above says “this story’s Subject 0 must also match SUBJECT_ESTRANGED_FROM_LEADER”. When the game finds a suitable candidate for the spouse character, it will test whether that character is also estranged from the leader. If not, then the Subject remains unpicked, which means the event does not trigger.

Each Subject can have multiple tests in SubjectExtras if desired. You could change the “estranged spouse” requirement into “estranged husband” by requiring that the same subject is also male, that is, fits the game’s SUBJECT_MALE as follows:

<SubjectExtras>
    <Pair>
            <First>0</First>
            <Second>SUBJECT_ESTRANGED_FROM_LEADER</Second>
    </Pair>
    <Pair>
            <First>0</First>
            <Second>SUBJECT_MALE</Second>
    </Pair>
</SubjectExtras>

If you have several subject, then each of them can of course have their own Extras tests. They’re completely independent.

One more important constraint is that, with certain subject classes, the event’s subject must be an us-subject or a them-subject. This applies to families, for instance. The game has a subject called SUBJECT_FAMILY_US, which picks one of your nation’s families, and also has SUBJECT_FAMILY_MIN_CAUTIOUS, which picks a family with Cautious opinion or better. Applying what you’ve learned about subjects so far, you should be able to guess that, to use your nation’s cautious family in an event, you’d want to combine the two subjects with a Subject Extras. But, in the case of families (and units, and cities), the subject that indicates “us” or “them” has to be in the aeSubjects list. So here’s how you get a cautious-or-better family:

<aeSubjects>
    <zValue>SUBJECT_FAMILY_US</zValue>
</aeSubjects>
<SubjectExtras>
    <Pair>
            <First>0</First>
            <Second>SUBJECT_FAMILY_MIN_CAUTIOUS</Second>
    </Pair>
</SubjectExtras>

Reversing the subjects in the aeSubjects and the SubjectExtras test above would not work.

Subject Relations

You now know how to introduce additional constraints for an event’s Subject using Subject Extras. That’s a powerful tool, and you can accomplish a great deal with what you know thus far. But for more complex events, you’ll need even more powerful tools.

Whenever you have multiple subjects in an event, and require those subjects to have a certain relation, you’ll need to make use of the Subject Relations field. It’s similar to the Subject Extras, but Subject Relations compare two subjects and check whether they have a relation you specify. Once again, the game’s files already have a considerable amount of relations specified, so you’re likely to find what you need there.

Let’s examine Subject Relations by the most typical example, requiring two subjects to be the same, or to be different. Suppose we want to create an event involving the player nation and two foreign nations. The event story’s Subject definition would then be

<aeSubjects>
    <zValue>SUBJECT_PLAYER_US</zValue>
    <zValue>SUBJECT_PLAYER_THEM</zValue>
    <zValue>SUBJECT_PLAYER_THEM</zValue>
</aeSubjects>

Recall that each subject in an event is assigned independently. When choosing the three subjects above, the game might assign the same foreign nation to both SUBJECT_PLAYER_THEM. The event might even trigger when you’ve only met one foreign nation. That’s not what you want, so you need to say that both SUBJECT_PLAYER_THEM subjects have to be different. That’s a relation between two subjects, so it’s time for the SubjectRelations field.

<SubjectRelations>
    <Triple>
        <First>1</First>
        <Second>SUBJECTRELATION_PLAYER_DIFFERENT</Second>
        <Third>2</Third>
    </Triple>
</SubjectRelations>

While Subject Extras tests used Pair elements, here we’re looking at a Triple element. For SubjectRelations, a Triple has First and Third fields specifying a subject index, and a Second field specifying a subject relation that has to be fulfilled. The above snippet says that subjects with indices 1 and 2 (remember that counting starts at 0) should have the SUBJECTRELATION_PLAYER_DIFFERENT relation. The relation’s name is quite obvious, requiring that two player subjects are different. With this in place, the two SUBJECT_PLAYER_THEM will have to be different.

Using Subject Relations, you can check for most things that make sense in Old World. You can check if two foreign nations dislike one another, you can check if a particular family has your state religion, and much more. Let’s take the family / religion example.

We want an event that can trigger if one of our, the player’s, families follows a religion that is not the state religion. We need one subject for the family, and we need another subject for the religion. The game is once again great at providing useful subjects, it already has SUBJECT_RELIGION_STATE_NO for a non-state religion (and SUBJECT_RELIGION_STATE for the state religion). And instead of the usual SUBJECT_FAMILY_US to pick a family, we can use SUBJECT_FAMILY_RELIGION_US, which will pick a family that follows a religion.

<aeSubjects>
    <zValue>SUBJECT_FAMILY_RELIGION_US</zValue>
    <zValue>SUBJECT_RELIGION_STATE_NO</zValue>
</aeSubjects>

There’s a family and a religion now, great. Now we need to make sure the family, subject 0, follows the religion that is subject 1. To compare two religions, there’s SUBJECTRELATION_RELIGION_SAME, so the Subject Relation would be:

<SubjectRelations>
    <Triple>
        <First>0</First>
        <Second>SUBJECTRELATION_RELIGION_SAME</Second>
        <Third>1</Third>
    </Triple>
</SubjectRelations>

Just like that, you can create an event about a family that’s unhappy that their religion isn’t the state one!

Since there are two subjects involved in a SubjectRelations check, the order matters as well! For a check like SUBJECTRELATION_REGION_SAME, it doesn’t matter because equality doesn’t depend on the order, but there are plenty of other different relations when this matters. Take the previously mentioned case of an estranged spouse. It was convenient to check with the SUBJECT_ESTRANGED_FROM_LEADER Extras check, but you could do the same thing with Subject Relations since there’s a SUBJECTRELATION_ESTRANGED_FROM. Then the relation below -

<SubjectRelations>
    <Triple>
        <First>1</First>
        <Second>SUBJECTRELATION_ESTRANGED_FROM</Second>
        <Third>0</Third>
    </Triple>
</SubjectRelations>

would require that Subject 1 is estranged from Subject 0. When you’re unsure of how to write a Subject Relation, it helps to remember to read them in their XML order, First,SecondandThird`. That’s why you read the above as “1 estranged from 0”.

Useful subjects and relations

There are many subjects and relations already defined in the game files, but some of them are particularly common in events. Here’s a brief list of some you might find yourself using often:

Event requirements and probabilities

Whenever creating an event, you want to control the requirements for that event to happen, and often also the probability of it happening. You have now learned a lot about Subjects, and they are one layer of event requirements. If the game cannot find suitable candidates for all the Subjects defined in an event story, the event will not trigger. But there are more requirements that you can specify at the event story level, so still eventStory-add.xml.

You can require a certain law to be active for the event to trigger, or prevent it from triggering if some laws are active. The law requirement is specified with LawPrereq:

<LawPrereq>LAW_SLAVERY</LawPrereq>

will require Slavery for the law to be triggered, whereas multiple laws can be specified in the aeLawInvalid list, and any of those would prevent the event:

<aeLawInvalid>
    <zValue>LAW_FREEDOM</zValue>
    <zValue>LAW_CONSTITUTION</zValue>
</aeLawInvalid>

In the above case, having either the Freedom law or the Constitution law would prevent the event.

It’s similar but even simpler for technologies. You can require one tech for an event, or make the event impossible upon one tech being researched. Here’s how to enable an event after Spoked Wheel and disable it after Stirrups:

<TechPrereq>TECH_SPOKED_WHEEL</TechPrereq>
<TechInvalid>TECH_STIRRUPS</TechInvalid>

Another interesting condition field is CouncilInvalid, which prevents the event from triggering if a certain Council position is filled. You could create an event that only triggers when the player has no Spymaster by specifying <CouncilInvalid>COUNCIL_SPYMASTER</CouncilInvalid>.

That covers the common cases for setting event prerequisites. Often, you will also want some kind of control over event probability and repetition. Let’s consider the two variables for probability first, iProb and iWeight.

To understand those, you should first understand how random events are picked by the game. On each turn, events whose requirements are fulfilled (that is, Subjects can be found, and other requirements like the above are met), are added to the event pool. From that pool, one or more events are picked to trigger, with the maximum amount depending on the game’s event frequency setting.

iProb determines the likelihood that an event will be added to the event pool. iWeight determines the probability that the event will be picked, if it is in the event pool for the current turn. So iProb comes into play first. For most events, it’s at 100, the default value, but lowering iProb is a good way to ensure more variety in the game. If you have an event with conditions that are rather common, lowering iProb would help ensure that the player doesn’t encounter it every game, or too soon after the conditions are met. You can set iProb to 25 for example, meaning that the event will only end up in the event pool 25% of the time even if the requirements are met.

iWeight is the weight for that particular event to be picked out of the event pool. The default value is 1, and it’s a linear weight - having an iWeight of 2 would make the event twice as likely to be picked, and so on. In Old World, it’s very common for many events to be in the event pool on a given turn (because there are many whose requirements are met), and so iWeight is the key to making some of those events show up more often. If you have an event with conditions that are rare and unlikely to be met, you might want to give the event a higher iWeight so the player can actually get to see the event in the short timeframe when it’s possible to.

The weight can also be modified depending on the leader’s ratings! This is a bit obscure but very cool. The aiRatingWeight list contains pairs such as this:

<aiRatingWeight>
    <Pair>
        <First>RATING_WISDOM</First>
        <Second>1</Second>
    </Pair>
<aiRatingWeight>

The above would increase the event’s weight (from iWeight) by the leader’s Wisdom times 1 (the second part of the pair). So if you have a leader with a Wisdom of 3 and an event with iWeight of 1, that event’s total weight would be 1 + (3 * 1) = 4. You can thus use aiRatingWeight to make events that are very likely to trigger shortly after you get a leader with high Charisma, for example.

You might also want to control an event’s repetition to make sure it does not come up too often, or never comes up twice in a game. The most basic tool you have for this is iRepeatTurns in an event story. It’s a number that specifies the minimum amount of turns between repetitions of the event. So <iRepeatTurns>40</iRepeatTurns> means the event cannot repeat within 40 turns. Specifying a value of -1 means the event will never repeat, making it a once-per-game story.

There’s a more interesting way of using iRepeatTurns, which is to make it apply per subject. You then use a SubjectRepeatTurns list like this:

<aeSubjects>
    <zValue>SUBJECT_PLAYER_THEM</zValue>
</aeSubjects>
<SubjectRepeatTurns>
    <Pair>
        <First>0</First>
        <Second>-1</Second>
    </Pair>
</SubjectRepeatTurns>
<iRepeatTurns>10</iRepeatTurns>

In SubjectRepeatTurns, the First is the Subject index, and the Second field is the repeat interval. The above event could repeat every 10 turns, due to iRepeatTurns, but it would never repeat (-1 turns) for a specific SUBJECT_PLAYER_THEM. That is, the event would pick a new player every time! Or, if you had SUBJECT_LEADER_US there, it’d be an event that could only occur once per each leader of the player nation.

The final common setting for controlling event repetition is aeEventStoryNoRepeat, which can be used in conjunction with iRepeatTurns to make a certain event story not trigger too soon after some other stories. For instance:

<zType>EVENTSTORY_FAMINE_COLD_SNAP</zType>
...
<aeEventStoryNoRepeat>
    <zValue>EVENTSTORY_FAMINE_LOCUSTS</zValue>
    <zValue>EVENTSTORY_FAMINE_DROUGHT</zValue>
</aeEventStoryNoRepeat>
<iRepeatTurns>30</iRepeatTurns>

The above shows how you can make several thematically related events not occur within a short timeframe. You have a “Cold snap famine” event, which you would like not to occur within 30 turns of the “Locust famine” or “Drought famine” events. You specify those other events in aeEventStoryNoRepeat, which means that the iRepeatTurns will be counted from the events in that list.

Finally, there’s the ultimate event priority mechanic, the iPriority variable. Out of all events that the game wants to trigger on a particular turn, only the highest-priority events will actually trigger. Suppose three events with iPriority of 1 were picked, and one event with iPriority of 2. In that case, only the latter event will actually trigger, and the other three will be skipped. Most events in the game have an iPriority of 1, so this mechanic doesn’t come into play often, but it can be used as a tie-breaker for equal weight events, or just to make one event suppress most others.

Creating interesting outcomes

Most of the guide so far has been about Event Stories themselves, especially about controlling their Subjects and triggering conditions. You don’t just want your events to trigger, you also want them to provide interesting choices to the player. It’s time to look at some of what you can accomplish with the bonus system.

Let’s quickly recap how choices in events worked. Each Event Story has one or more Event Options, and each Option contains a list of Bonuses, one for each Subject in the event, and it’s these Bonuses that describe in-game effects. Near the beginning of this guide, we stepped through a simple event that grants Iron or Stone, and haven’t looked at any other possible effects yet.

There are some 120 possible effects for bonuses, which can of course be combined. That is too many to cover in this guide, but we’ll look at a few examples. First, here’s a very rough breakdown of event bonuses into some major categories:

The good thing about bonus effects is that many of them are rather self-explanatory. Look through the game’s bonus-event.xml file to see all possible effects, and you’ll be able to guess what a good many of them do, especially if you’ve encountered them in the game yourself. For instance, you’ll see FreeLaw, and it’s not hard to guess that it allows for an immediate and free (no civics cost) change in laws, or that AdoptReligion adopts a particular religion as the state religion.

In the interest of brevity, I will then not cover the vast majority of the effects, but let’s examine a few that are common, and a few that are not particularly obvious.

AddLeaderRelationship and RemoveLeaderRelationship are effects that apply to characters, and are a key mechanism to manage how the characters feel about the leader. This is where you can make some other character endeared to or disappoiinted with the leader (RELATIONSHIP_ENDEARED_TO and RELATIONSHIP_DISAPPOINTED_WITH respectively), and those relationships are very good to use in your events. They add role-playing value, modify the character’s opinion, and can serve as triggers for other events.

MakeCourtier is a way to make an existing character (that perhaps only now appeared in this event) into a courtier, that is, Great Scientist / Great Merchant / etc.

Character traits can be added with aeAddTraits, or with aeRandomTrait to randomly pick one of several specified traits.

As the first example, let’s look at the common heir education events from the game. What happens when you choose to educate a heir in Philosophy? The following bonus entry gets applied to them:

<Entry>
        <zType>BONUS_EVENTOPTION_STUDY_PHILOSOPHY</zType>
        <aiRatings>
                <Pair>
                        <zIndex>RATING_WISDOM</zIndex>
                        <iValue>1</iValue>
                </Pair>
        </aiRatings>
        <aeAddTraits>
                <zValue>TRAIT_STUDY_PHILOSOPHY</zValue>
        </aeAddTraits>
</Entry>

That shows two common effects from bonuses. The subject’s Wisdom is increased by 1, and the TRAIT_STUDY_PHILOSOPHY trait is applied to the subject. Adding traits to characters is a very convenient way to create additional event possibilities for them. If you check how this trait is defined in trait.xml, it doesn’t do much:

<Entry>
        <zType>TRAIT_STUDY_PHILOSOPHY</zType>
        <Name>TEXT_TRAIT_STUDY_PHILOSOPHY</Name>
        <bNoJob>1</bNoJob>
</Entry>

It specifies that characters with this trait cannot hold any jobs (governor, general, councillor), and nothing else. The trait is used to trigger more events though - there’s a corresponding subject, SUBJECT_STUDY_PHILOSOPHY, that is valid for characters with this trait. And the subsequent events that trigger for philosophy students are implemented by having a SUBJECT_CHARACTER_US with an extra check for SUBJECT_STUDY_PHILOSOPHY. This is a very common pattern that you can make use of in your own events.

Another very common thing to do in events is to give (or take) some resources. You can also do that to individual cities, given a city subject. Note that Discontent is also a yield, so reducing discontent is one of the typical use cases here.

Adding 100 civics to the global stockpile:

<aiGlobalYieldsBase>
        <Pair>
                <zIndex>YIELD_CIVICS</zIndex>
                <iValue>100</iValue>
        </Pair>
</aiGlobalYieldsBase>

Reducing discontent in a city:

<aiCityYields>
        <Pair>
                <zIndex>YIELD_DISCONTENT</zIndex>
                <iValue>-20</iValue>
        </Pair>
</aiCityYields>

Note: you can also add or remove an entire discontent level in a city, for which there is a separate bonus effect - do <iDiscontentLevels>-1</iDiscontentLevels> to remove one discontent level.

Religious bonuses

Bonuses related to religion deserve a separate subsection because they are somewhat non-obvious.

First, you have the FoundReligion bonus effect, which can be used to found a specific religion, e.g. <FoundReligion>RELIGION_CHRISTIANITY</FoundReligion>. Further, this effect can be applied to different subject classes. If it applies to a leader, so likely SUBJECT_LEADER_US, the religion will be founded in a random city. The same effect can be applied to a specific city, such as with the SUBJECT_CITY_US subject, in which case the religion will be founded in that particular city.

Then there’s bFoundReligion, which founds a random religion and should be applied to the leader, or another character. If you want to found a random religion in a city, you should have a city subject and apply bFoundReligionCity to it.

There are also several different options for handling state religion. The bStateReligion effect applies to a religion subject and causes that religion to become the player’s state religion. It can be used as in the War Offer event from the game. First, the subjects:

<aeSubjects>
        <zValue>SUBJECT_PLAYER_MAX_CAUTIOUS</zValue>
        <zValue>SUBJECT_PLAYER_US</zValue>
        <zValue>SUBJECT_RELIGION</zValue>
</aeSubjects>
<SubjectExtras>
        <Pair>
                <First>0</First>
                <Second>SUBJECT_PLAYER_STATE_RELIGION</Second>
        </Pair>
</SubjectExtras>
<SubjectRelations>
        <Triple>
                <First>2</First>
                <Second>SUBJECTRELATION_RELIGION_STATE</Second>
                <Third>0</Third>
        </Triple>
</SubjectRelations>

Subject 0 is an AI player that has a state religion (due to the SubjectExtras check), and subject 2 is that player’s state religion (due to the SubjectRelations check). One of the options in that event applies the following bonus to subject 2 (the religion):

<Entry>
        <zType>BONUS_EVENTOPTION_WAR_OFFER_RELIGION_STATE_YES_RELIGION</zType>
        <bStateReligion>1</bStateReligion>
</Entry>

The bonus makes the player who gets the event adopt that religion as the state religion, so the event as a whole is a demand by another nation for you to adopt their religion.

bStateReligionEnd, as you might guess, ends a player’s state religion, returning to the state with no state religion.