Resource icon

Using Modifiers - Chapter 1: Creating and attaching modifiers 2016-11-22

NycholusV

Chieftain
Joined
Jun 25, 2016
Messages
86
Location
Sydney, Australia
This is the first chapter of a guide that I will be working on to explain Civ 6's new system of modifiers. The file attached is the example mod created in this first chapter, and the guide itself is on my website:

Moderator Action: link to compromised site removed

I've been working very hard to get this out ASAP to help people who are trying to mod and get their head around modifiers. Hopefully there aren't any mistakes or errors in the guide or the example mod, but if there are, please alert me.

* * *​

Civilization 6 introduces a new system of game mechanics known as ‘modifiers’. Modifiers allow dynamic changes to entities in the game, allowing a far greater degree of flexibility to modders. They are already used ubiquitously throughout the game; bonuses from civics, technologies, buildings, religion, policies etc. are all modifiers. They also exist in the form of unit promotions, diplomatic boosts and penalties, and elsewhere. Modifiers are perhaps the most crucial component of the game that modders must be able to use effectively to create custom content.

This guide assumes that:
  • You are familiar at least at a very basic level with SQL.
  • You understand the file structure and implementation of XML/SQL based mods.
  • You can create a modinfo file for very basic mods. (There will be no discussion of this in the guide’s examples.)

* * *​

In this chapter, you will learn how to implement modifiers into the game. We will be creating a very basic ‘balance patch’, that will make a few changes to the game:
  1. The Stave Church (Norwegian unique building) grants a free missionary when built.
  2. Pax Britannica (Victoria’s leader bonus) grants +10% Production in cities settled on foreign continents.
  3. Increases the rate of border expansion universally by 50%.
By the end of this chapter, you should be able to:
  • Attach modifiers to entities using the entity-modifier tables.
  • Understand what is meant by attaching a modifier as opposed to applying a modifier.
  • Create your own modifiers using modifier types and requirement sets included in the base game.
  • Understand the difference between modifiers and dynamic modifiers.
  • Understand the purpose and usage of the modifier arguments table.
  • Debug modifiers using log files and the tuner.

Moderator Action: content of chapter 1 copied below

modifier-diagram.png


Download the example mod. Please do not attempt to copy and paste code from this webpage; this will not work due to the way that WordPress formats inverted commas.

In this chapter, you will learn how to implement modifiers into the game. We will be creating a very basic ‘balance patch’, that will make a few changes to the game:

  1. The Stave Church (Norwegian unique building) grants a free missionary when built.
  2. Pax Britannica (Victoria’s leader bonus) grants +10% Production in cities settled on foreign continents.
  3. Increases the rate of border expansion universally by 50%.
By the end of this chapter, you should be able to:

  • Attach modifiers to entities using the entity-modifier tables.
  • Understand what is meant by attaching a modifier as opposed to applying a modifier.
  • Create your own modifiers using modifier types and requirement sets included in the base game.
  • Understand the difference between modifiers and dynamic modifiers.
  • Understand the purpose and usage of the modifier arguments table.
  • Debug modifiers using log files and the tuner.
Entity-Modifier Tables
Modifiers can be attached to almost any entity in the game, such as beliefs, policies, traits, etc. Each entity has a table that lists the entities and modifiers associated with them. I will henceforth refer to these as ‘entity-modifier’ tables. These tables include BeliefModifiers, used for attaching modifiers to religious beliefs, BuildingModifiers, used for attaching modifiers to buildings, TraitModifiers, used for attaching modifiers to special abilities and leader bonuses, and so on. Most of these tables share a similar structure: the first column contains the entity type, and the second contains the modifier attached to it. Note that the relationship between entity types and modifiers is a many-to-many relationship; i.e. an entity type can have multiple modifiers assigned to it, and (more obviously) a modifier can be assigned to multiple entity types. An exhaustive list of these tables and their specifications can be found on the reference page for entity-modifier tables.

The entity-modifier tables attach modifiers to entities, and an entity that a modifier is attached to is the owner of the modifier. The terms ‘attach’ and ‘owner’ have very specific and important meanings here that will become clearer as we progress through this tutorial. The important thing to note at this stage is this – the attachment of modifiers does not determine what the modifier actually acts upon (the subjects), nor the conditions that trigger the modifier. These are determined by collections and requirements, respectively. Entity-modifier tables can be thought of as determining when a modifier comes into question. We use ‘attach’ and ‘owner’ in contrast to ‘apply’ and ‘subject’, respectively. A modifier is attached to its owner, and applied to its subjects.

Let’s start working on our balance patch described at the beginning of this chapter. The first component is intended to show how modifiers can be used if you’re creating a custom building, district, improvement, etc. For the sake of simplicity, we’re simply going to add a modifier to an existing building (rather than have to define a custom building, which is beyond the scope of this guide). We’ll use Norway’s unique building, the stave church, and use modifiers to make a free missionary spawn whenever a stave church is built. If you look at the list of entity-modifier tables, it should be fairly obvious which table we want to use here: the BuildingModifiers table. Let’s start writing our SQL code:

INSERT INTO BuildingModifiers (BuildingType, ModifierId)
VALUES (‘BUILDING_STAVE_CHURCH’, ‘STAVE_CHURCH_GRANT_MISSIONARY’);
If you’re wondering where we got the key of the building from, you can find it in Buildings.xml. (All entity keys in the base game can be found in the XML files in the Data folder). This line adds a row to the table that associates the stave church with the modifier that we will define later in this chapter. At this point, it’s worth discussing the conventions in naming modifiers. Modifier names generally start with the entity or entity type they are associated with, in this case ‘STAVE_CHURCH’, followed by a description of what the modifier does. Using this convention will ensure that you don’t accidentally have two modifiers with the same name, and will make it easier for you (and others) to understand your code and in debugging.

The second component of our balance patch relates to a trait, i.e. a special ability or leader bonus. Unsurprisingly, we’ll be using the TraitModifiers table to achieve this, attaching a modifier to the trait:

INSERT INTO TraitModifiers (TraitType, ModifierId)
VALUES (‘TRAIT_LEADER_PAX_BRITANNICA’, ‘TRAIT_BOOST_PRODUCTION_NON_HOME_CONTINENT’);
So, how about the third component? Which table do we use? This one’s a bit trickier. You might be thinking: there’s no such tables as ‘CityModifiers’ or ‘PlayerModifiers’. This is true, but recall that the entity-modifier tables do not specify what a modifier is applied to, it specifies what a modifier is attached to, and when the modifier comes into question. When does a permanent border expansion for all players come into question? – At the beginning of the game and throughout the entire game. We therefore need to use the GameModifiers table. Modifiers attached to the game exist at the beginning of the game and throughout the entire game. This table is slightly different to other entity-modifier tables as it only has one column: the ModifierId. This is because there’s only ever one instance of ‘Game’. So our SQL code should be:

INSERT INTO GameModifiers (ModifierId)
VALUES (‘GAME_INCREASED_CULTURE_BORDER_EXPANSION’);
The Modifiers Table
Now we need to actually define the modifiers that we specified in the entity-modifier tables. This brings us to the Modifiers table, which, as one might expect, is where the modifiers themselves are stored. The Modifiers table is surprisingly bland, and doesn’t get into the real meaty mechanics of the modifier system. There are two important things that the Modifiers table specifies:

  • Firstly, each row specifies a modifier type, also known as a dynamic modifier. The DynamicModifiers determine what each modifier actually does. In this chapter, we will only be using modifier types included in the base game, however, it is possible (and extremely useful) to create your own, which will be a topic for a later chapter.
  • Secondly, each row can specify a two optional requirement sets. RequirementSets are a list of requirements that must be met for the modifier to become active. Once again, we will only be using requirement sets from the base game, and will leave how you can create your own for a later chapter.
An entry in the Modifiers table can be thought of as a specific purposing of a dynamic modifier; it allows the dynamic modifier to be fashioned in a certain way. The same dynamic modifier can be reused in multiple modifiers with different requirements and different arguments. An example of this in the base game is the four wonders that all grant an additional policy slot. However, Alhambra grants a military policy slot, Big Ben grants an economic policy slot, the Potala Palace grants a diplomatic policy slot, and the Forbidden City grants a wildcard policy slot. All of these wonders have different modifiers attached to them, but all of their modifiers use the same dynamic modifier. The difference lies in the arguments of the modifier (which we will soon discuss). This is one of several ways that the separation of these tables allows for versatility and modularisation.

Let’s now go through each of the columns of the Modifiers table:

  • ModifierId: The name of the modifier, as referenced in the entity-modifier tables. As previously stated, you should follow the game’s convention for naming modifiers, such as:
    FORBIDDEN_CITY_WILDCARD_GOVERNMENT_SLOT
    TRAIT_FREE_ROADS_TO_CAPITAL
    GODDESS_OF_THE_HUNT_CAMP_FOOD_MODIFIER
  • ModifierType: Identifies the dynamic modifier from the DynamicModifiers table that this modifier uses.
  • RunOnce: A boolean that identifies whether or not this modifier applies a one-time effect, such as a free unit, an inspiration or eureka boost, etc. False by default. It is not always clear when this should be used, but when in doubt, refer to the base game files and emulate them, i.e. find a modifier with the same ModifierType as the one you’re using, and use that as a reference.
  • Permanent: A boolean that identifies whether or not this modifier should apply permanently. False by default. While seemingly contradictory, this is often used in conjunction with RunOnce. This is to prevent the modifier from applying itself again if, for whatever reason, the modifier disappears and then reappears. There are also some cases where this is used without RunOnce. Again, when in doubt as to whether you should use these, emulate the base game.
  • OwnerRequirementSetId: Identifies a requirement set from the RequirementSets table that must be met by the owner for the modifier to become active. Recall that the owner of a modifier is what the modifier instance is attached to, which is determined by the rows of the entity-modifier tables. The use of this column is rare. It even seems that the developers have made a point of avoiding this column. In the base game, owner requirements are used by leader agendas, where the owner is the leader with the agenda, and the subjects are other leaders. It is also used in some situations for combat bonuses, where the owner is the unit with the bonus, and the subjects are enemy units.
  • SubjectRequirementSetId: Identifies a requirement set from the RequirementSets table that must be met by a subject for the modifier to be applied to that particular subject. Recall that a subject is an entity that the modifier applies to.
Just a quick note about booleans – If you’re using SQL, ‘false’ should be entered as ‘0’ and ‘true’ should be entered as ‘1’.

Let’s create our SQL queries for the Modifiers table. The list of DynamicModifiers (modifier types) is available in Modifiers.xml. Unfortunately, the RequirementSets are scattered throughout the the XML files, but in a few chapters you’ll learn how to define your own requirement sets (which thenceforth you’ll always want to do).

INSERT INTO Modifiers (ModifierId, ModifierType, RunOnce, Permanent, SubjectRequirementSetId)
VALUES (‘STAVE_CHURCH_GRANT_MISSIONARY’, ‘MODIFIER_SINGLE_CITY_GRANT_UNIT_IN_CITY’, ‘1’, ‘1’, NULL),
(‘TRAIT_BOOST_PRODUCTION_NON_HOME_CONTINENT’, ‘MODIFIER_PLAYER_CITIES_ADJUST_CITY_YIELD_MODIFIER’, ‘0’, ‘0’, ‘CITY_NOT_OWNER_CAPITAL_CONTINENT_REQUIREMENTS’),
(‘GAME_INCREASED_CULTURE_BORDER_EXPANSION’, ‘MODIFIER_ALL_CITIES_CULTURE_BORDER_EXPANSION’, ‘0’, ‘0’, NULL);
For the first component of our mod, we are attaching a modifier to a building that spawns a unit. This is an instance where we need to use RunOnce and Permanent, because we only want to spawn a unit once. Without Permanent, we open up the possibility of some quirky exploits. Since this modifier has no requirements, we leave both requirement set columns to NULL. (None of the modifiers are using owner requirements, so we’ve omitted that column from the INSERT statement entirely.)

The second component of our mod has a requirement set. This base game requirement set checks whether the city is on a foreign continent. We want the production boost to apply continuously, so RunOnce is not necessary. Permanent, while it wouldn’t do any harm to set it to ‘true’, is not necessary either. We only need to use Permanent if there’s a risk that the modifier will disappear then reappear.

Our final component does not have requirements nor does it necessitates use of the boolean columns. We simply want a universal boost to border expansion.

Modifier Arguments
The last table we’ll be concerning ourselves with in this chapter is the ModifierArguments table. Earlier we learnt that modifiers are best thought of as a particular fashioning of a dynamic modifier. The ModifierArguments table is where most of this ‘fashioning’ takes place. It is here that we specify what unit the stave church grants, what yield Pax Britannica provides a boost to, how much this boost is, and how much border expansion is increased. Let’s go through the columns of this table:

  • ModifierId: The modifier from the Modifiers table that this argument is for.
  • Name: The name of the argument that is being assigned.
  • Type: The purpose of this column is hard to discern from the base game code because it is rare and cryptic in its use. It has a default value set to ARGTYPE_IDENTITY. For almost all modding purposes, it seems unnecessary to concern oneself with this column.
  • Value: The value of the argument that is being assigned.
  • Extra: Presumably an additional value column. Appears in a few instances in the game code, but its exact purpose is unclear.
Let’s start coding the arguments. The meaning of each line should be self-explanatory:

INSERT INTO ModifierArguments (ModifierId, Name, Value)
VALUES (‘STAVE_CHURCH_GRANT_MISSIONARY’, ‘UnitType’, ‘UNIT_MISSIONARY’),
(‘STAVE_CHURCH_GRANT_MISSIONARY’, ‘Amount’, ‘1’),
(‘TRAIT_BOOST_PRODUCTION_NON_HOME_CONTINENT’, ‘YieldType’, ‘YIELD_PRODUCTION’),
(‘TRAIT_BOOST_PRODUCTION_NON_HOME_CONTINENT’, ‘Amount’, ’10’),
(‘GAME_INCREASED_CULTURE_BORDER_EXPANSION’, ‘Amount’, ’50’);
You might be wondering how we know what the valid names, values and meanings of each modifier argument is. The answer is cross-referencing the base game code. There is no file that lists all valid modifier arguments. One thing to understand while cross-referencing is that the validity of modifier arguments is not determined by the modifier, nor the dynamic modifier. It is determined by the effect, which is yet another level down from the dynamic modifier (refer to the diagram). This means that all modifiers with the same effect type will have the same set of argument definitions, and this is important to consider when cross-referencing. This will hopefully make more sense once we have discussed effects in a later chapter. Note that invalid modifier arguments will cause the modifier to fail to load, so it’s important to get it right.

With the modifier arguments assigned, we have completed our balance patch! Though of course, the changes that we made will not be reflected in the game’s text, but this is again beyond the scope of this guide.

Debugging Modifiers
We’ll briefly discuss how to diagnose problems with modifiers, which you will undoubtedly experience at some point in your modding. The key things you’ll want to do are:

  • Enable the tuner and logging by editing AppOptions.txt in the Civ 6 documents folder.
  • Enable effects diagnostics by editing ‘GameEffectsLogLevel’ in UserOptions.txt.
  • Refer to Logs/Database.txt for SQL errors.
  • Refer to Logs/GameEffects.txt for errors with modifiers. This can be a lengthy log file, so try searching for the name of your modifier.
  • Use the tuner for Civ 5 with Civ 6 and open the Modifiers debug panel, available in the Debug folder from the root game files directory. This contains useful information about the current state of modifiers in the game.
The concludes the first chapter of this guide. In the next chapter, we’ll develop our own dynamic modifiers, which will open up to you an enormous depth of possibility for your modding endeavours.

Next Chapter:
Chapter 2: Dynamic modifiers, effects, collections and arguments
 
Last edited by a moderator:
+1 for thanks and very useful

Probably you already have this, but just in case i was looking at the DynamicModifiers table after learning of it's existence and i've extracted all the collections, effects and effects/collection in Libre Office spreadsheets if you want those.

I guess effects and collections are hard-coded and DynamicModifiers is as far as we can go without dll modification aren't they?
 
+1 for thanks and very useful

Probably you already have this, but just in case i was looking at the DynamicModifiers table after learning of it's existence and i've extracted all the collections, effects and effects/collection in Libre Office spreadsheets if you want those.

I guess effects and collections are hard-coded and DynamicModifiers is as far as we can go without dll modification aren't they?

Effects and Collections are listed in GameEffects.xml, but cross-referencing is required to find out what they do, what their arguments are, and whether one should use some of the quirkier columns (like RunOnce and Permanent).

Yes, effects and collections are hard-coded. The red boxes in the diagram at the top of the page represent hard-coded components. Still, there's so much you can do with just defining DynamicModifiers.
 
My God. I cannot begin to express how helpful this is. Thank you so much. I only wish I had this two days ago when I spent the entire day frustrated and trying to assess why my mod wouldn't work (I'm self-taught with this stuff), until I eventually noticed the "Modifiers.xml" file and started analyzing it. A few hours later, I literally smacked myself on the forehead. I've still got some issues getting certain aspects of my mod(s) to work, but at the very least they now load every time.

(btw if anyone successfully added their own unique improvement to a mod and wouldn't mind giving me some help, I would appreciate it. I scoured the files for hours yesterday and it seems like currently it isn't possible solely by using .xml files)
 
My God. I cannot begin to express how helpful this is. Thank you so much. I only wish I had this two days ago when I spent the entire day frustrated and trying to assess why my mod wouldn't work (I'm self-taught with this stuff), until I eventually noticed the "Modifiers.xml" file and started analyzing it. A few hours later, I literally smacked myself on the forehead. I've still got some issues getting certain aspects of my mod(s) to work, but at the very least they now load every time.

(btw if anyone successfully added their own unique improvement to a mod and wouldn't mind giving me some help, I would appreciate it. I scoured the files for hours yesterday and it seems like currently it isn't possible solely by using .xml files)

Makes me really glad that this has helped this much. :)

I have almost finished working on a custom civ with a unique improvement, and it's working fine. What in particular isn't working for you?
 
My God. I cannot begin to express how helpful this is. Thank you so much. I only wish I had this two days ago when I spent the entire day frustrated and trying to assess why my mod wouldn't work (I'm self-taught with this stuff), until I eventually noticed the "Modifiers.xml" file and started analyzing it. A few hours later, I literally smacked myself on the forehead. I've still got some issues getting certain aspects of my mod(s) to work, but at the very least they now load every time.

(btw if anyone successfully added their own unique improvement to a mod and wouldn't mind giving me some help, I would appreciate it. I scoured the files for hours yesterday and it seems like currently it isn't possible solely by using .xml files)

i made a unique trait. you can see my code in GDG OP Civ mod. maybe it can help you
 
to any Mod can this thread be sticky?

this thread should stay relevant for the life of the game
 
I have almost finished working on a custom civ with a unique improvement, and it's working fine. What in particular isn't working for you?
Basically my builders have no option for building the improvement. It never even shows that the builders WOULD be able to build it but can't due to "incorrect terrain/feature". That would at least narrow down my problem a bit. Maybe it specifically needs to be a leader trait and I'm using it as a civilization trait? I don't know the rules/etiquette on posting any actual code, but I know I have tried to copy the code from the main game files verbatim and couldn't get it to show up.
i made a unique trait. you can see my code in GDG OP Civ mod. maybe it can help you
I must have missed that one, I will take a look right now. Thanks.
 
Last edited:
Still, there's so much you can do with just defining DynamicModifiers.
Yep, but nothing i found to create a yield/population modifier for instance.
 
@NycholusV can you help me making china to allow faster builds on every wonder? i cant seem to find the era modifier that needs to be altered

Took me some time to find it too. One would expect this would simply be a modifier argument, but it turns out it isn't. Line 44 in UnitCommands.xml is what is restricting this; the last field is 'MaxEra', which has been set to '2'. Seems a bit silly the way this is coded, but there's probably a good reason for it.

Basically my builders have no option for building the improvement. It never even shows that the builders WOULD be able to build it but can't due to "incorrect terrain/feature". That would at least narrow down my problem a bit. Maybe it specifically needs to be a leader trait and I'm using it as a civilization trait? I don't know the rules/etiquette on posting any actual code, but I know I have tried to copy the code from the main game files verbatim and couldn't get it to show up.

Unique components must have their own trait. The trait can be the civ's or the leader's, but the important thing is that it is a trait exclusively for the unique component, it seems that otherwise it doesn't work. Units, improvements, etc. have a field called 'TraitType', which is where you associate the trait to the component.

Yep, but nothing i found to create a yield/population modifier for instance.

What specifically do you mean by a "yield/population modifier"? That sounds like something that is possible, if you would care to elaborate.

Great work. Any chance you'll be doing a deep dive into dynamic modifiers? Specifically collections? I'm not entirely sure what the differences are between them and when one is more appropriate than another.

Absolutely. That'll be the next part. Have you read the entire first chapter? I try to explain their difference. Also refer to the diagram at the top of the page, which shows the relationships between different tables.
 
Took me some time to find it too. One would expect this would simply be a modifier argument, but it turns out it isn't. Line 44 in UnitCommands.xml is what is restricting this; the last field is 'MaxEra', which has been set to '2'. Seems a bit silly the way this is coded, but there's probably a good reason for it.

So you can only just alter it and not recreate it?
 
What specifically do you mean by a "yield/population modifier"? That sounds like something that is possible, if you would care to elaborate.
As a simple example, something that would add gold/population to every city after Currency to represent taxes, like 0.3 gold/population.
I guess it's possible to create +1 gold/city and add a condition to check city is size 3, then another +1 if city is size 6 and so on to get roughly the same effect, but i haven't found an effect that directly adds a yield that grows with the size of the city. They are either fixed or % modifiers.
 
wouldn't lua quite simply allow this kind of effect ?
When/if we can finally load gameplay scripts into saved games probably.
However, since we now have a very flexible modifiers system, it would be nice to be able to create such a modifier without scripts.
 
When/if we can finally load gameplay scripts into saved games probably.
However, since we now have a very flexible modifiers system, it would be nice to be able to create such a modifier without scripts.

Can't Lua scripts be used at this point?
 
Back
Top Bottom