Silent events

From Europa Universalis 3 Wiki
Jump to navigation Jump to search

At times, it is necessary to use scripting events that ideally would not be seen by the player. Sometimes it is due to the number of events that have to be fired, other times it's due to immersion or other reasons.

In later games, such as Europa Universalis IV, there is native support to make an event fire in the "background", i.e hidden from view. Europa Universalis III, however, lacks this feature, and as such other ways must be found to create so-called silent events.

In this guide, we'll be exploring how to set up an event mule tag (also sometimes called a utility tag) to handle silent events that can affect the player.

Creating the event mule tag

Follow the guide to creating new countries in order to familiarize yourself with the procedure.

In common/countries.txt, add the line:

EVT = "countries/eventmule.txt"

In common/countries, create the text file: "eventmule.txt" by copying another country's text file.

In gfx/flags, copy the flag REB.tga and rename it to EVT.tga

in history/countries, copy an existing country's history file and rename it to EVT - Eventmule.txt

in the localisation folder, open "newtext.csv" and add the lines:

EVT;Event Mule;;;;;;x

EVT_ADJ;Event Mule;;;;;;x

Now, the event mule country has been created under the tag "EVT"

Creating an inaccessible province for the event mule

Warning: this section is written for In Nomine. It is unknown whether placing a province surrounded by "wasteland" provinces in Divine Wind works correctly.

We must now create an inaccessible 5x5 province surrounded on all sides by permanent terra incognita. This article won't rehash how to create individual provinces, as there is an existing guide on this wiki.

The most important thing to remember is when placing your new province in provinces.bmp, one should pick a large area of perma terra incognita and create a 5x5 pixel square province completely surrounded by perma terra incognita. Contrary to popular belief, this will NOT crash the game and surprisingly works fine.

Once the above steps are complete, assign your event mule tag to occupy the inaccessible event mule province that was just created.

Using an event mule to handle global scripting

Your new event mule can be used to handle global scripting via events that would otherwise be too spammy or unsightly for individual countries.

In the following example, I will imagine that a modder wants to have "permanent" provincial modifiers on every province that has a base tax of exactly 4. In later games like EUIV, modders have access to the add_permanent_province_modifier command that sets a provincial modifier that will stay active even when the province changes owner. In Europa Universalis III, however, any province modifiers are lost with changes to ownership.

The obvious solution is to create a simple province event, but in this case the modder wants it to happen silently and automatically, without the province owner being notified.

For simple province events like this, which do not require a THIS relativity clause with the province owner, we can use the event mule:

## Some parts of this event have been omitted for readability reasons
trigger = {
    tag = EVT
    any_province_region = { #this is a metaregion
        base_tax = 4
        NOT = { base_tax = 5 }
        NOT = { has_province_modifier = base_tax_5_modifier }
    }
}
immediate = {
    any_province_region = { #metaregion
        limit = {
            base_tax = 4
            NOT = { base_tax = 5 }
            NOT = { has_province_modifier = base_tax_5_modifier }
        }
        add_province_modifier = {
            name = base_tax_5_modifier
            duration = -1
        }
    }
}

Here, we are using the any_province_region metaregion from the point of view of the event mule to seek out the existence of any province that fulfills the conditions: a base tax of exactly 4, and the lack of a modifier. We then use the immediate clause to isolate all provinces that fulfill the condition, and then apply the fix. Remember, for optimization and game stability reasons, we must restrict the event from happening only to the EVT tag. In the following example, a modder wants to randomize the chance of a country flag being set to either FRA, ENG, CAS, or POR. Rather than have multiple events with various MTTH, the modder wants a single "silent" event to happen that uses the random_list command to instantly give out the country flag to one of these tags.

### part of this event has been omitted for convenience
trigger = {
    tag = EVT
    NOT = {
        any_province_region = { #metaregion
            owner = {
                has_country_flag = columbus_spawns_here
            }
        }
    }
    OR = {
        exists = ENG
        exists = CAS
        exists = POR
        exists = FRA
    }
    year = 1470
}
mean_time_to_happen = {
    years = 20
}
immediate = {
    random_list = {
        25 = { 
            ENG = { set_country_flag = columbus_spawns_here }
        }
        25 = { 
            CAS = { set_country_flag = columbus_spawns_here }
        }
        25 = { 
            POR = { set_country_flag = columbus_spawns_here }
        }
        25 = { 
            FRA = { set_country_flag = columbus_spawns_here }
        }
    }
}

In the first section of this event, we restrict the event to the event mule tag. Next, we use the any_province_region metaregion to act as a global reference and replace the any_known_country scope that would be used in its place. This is because any_known_country not only omits THIS (which is fine for an event mule), but also omits tags which are not discovered by THIS. Therefore, using any_province_region becomes necessary. We also do a quick check for the year, as well as to ensure that at least one of the tags in question exist.

The next part of the event launches a simple random_list command and equally divides the chance between the four tags. If the modder wants, they can add extra weight to any specific tag.

Limitations of silent events and lack of THIS relativity

Using a silent event to handle province or country scripting has the advantage of rendering the effect silent, automatic, and "under the hood" for all players. However, this comes at the cost of forsaking the THIS relativity clause that comes with every country or province event.

THIS relativity involves the dynamic THIS scope that always refers to the country that received the event (both in country events and province events). Normally, in a province event, the province owner is THIS, and this allows a great deal of flexibility in events. For example, the following piece of code can check whether or not a province controller in a war is of the same culture group as the province owner through THIS relativity:

trigger = {
    NOT = { controlled_by = owner }
    NOT = { controlled_by = REB }
    owner = { war = yes }
    controller = {
        culture_group = THIS
    }
}

As the culture_group country-scope trigger needs to be linked to the tag of the province owner, the only way to dynamically refer to it is to use THIS relativity.

THIS relativity in silent events

In silent events, THIS relativity is broken as THIS will always refer to the event mule tag EVT. Maintaining THIS relativity with EVT is useless as the event mule itself is simply a surrogate for the event itself and no conditions can be matched to it. This means that a silent event cannot dynamically check for the above example trigger, or to put it differently, a silent event cannot globally check for the existence of any province that is occupied by a non-owner country of the same culture group as the owner. The only way in which this would be possible would be if the modder wrote static code, rather than dynamic code, referring to a single culture group instead of a dynamic culture_group = THIS.

trigger = {
    any_province_region = { #metaregion
        NOT = { controlled_by = owner }
        NOT = { controlled_by = REB }
        owner = { war = yes }
        OR = {
            AND = { 
                owner = { culture_group = british }
                controller = { culture_group = british }
            }
            AND = { 
                owner = { culture_group = french }
                controller = { culture_group = french }
            }
            AND = { 
                owner = { culture_group = iberian }
                controller = { culture_group = iberian }
            }
            [...]
        }
    }
}

The obvious disadvantage with static code is the incompatibilities introduced with editing any element of the above. For example, if a modder adds a new culture group, any events using static code must be manually rebuilt.