RequirementSets
But what if we don’t want to grant +5 Food to ALL cities? What if we want to restrict it further to cities with a Granary? Surely there isn’t aCollectionType just for that?
That’s where RequirementSets come in! These are sets of Requirements that must be met for a modifier to be active. A modifier can have up to two RequirementSets, one for the Owner, that checks whether the Owner meets the requirements before activating at all, and one for the Subject, which checks each Subject, then only triggers the effect on those that meet the requirements.
RequirementSets are assigned to Modifiers (using the RequirementSetID as a unique identifier) via the optional OwnerRequirementSetID and SubjectRequirementSetID columns in the Modifiers table. A modifier can have one, none, or both of those columns filled as desired.
RequirementSets table, then go back to where we defined our modifier and edit it to include the new Requirement Set (we’ll assign it as a SubjectRequirementSetID since we want to check whether each city has a Granary).
Note: What’s thisREQUIREMENTSET_TEST_ALLthing? Requirement Sets are collections of multiple requirements. There are two ways these requirements can be collectively handled.
REQUIREMENTSET_TEST_ALLmeans ALL the requirements in the set must be met for the modifier to activate.REQUIREMENTSET_TEST_ANYmeans the modifier will be active if ANY of the requirements in the set are met.
Requirements
Now we need to create a requirement and assign it to the Requirement Set we just created.RequirementId which is a unique identifier for the requirement, and a RequirementType that determines what it’s checking for (In this case, we’re checking if a city has a building via REQUIREMENT_CITY_HAS_BUILDING) . Unlike modifiers, you do not create a custom RequirementType, instead reusing an existing one.
You’ll also determine the specifics of a modifier via the RequirementArguments table. Similar to ModifierArguments, the valid Names and Values will depend on the RequirementType. You can look for other requirements that share the same RequirementType in the game files or through gameplay-copy.sqlite in the Debug folder.
Recap
Phew! That was a lot wasn’t it? Let’s recap:- Modifiers are used to handle many game effects.
- Modifiers have an Owner (how it is introduced to the game), and a Subject (what does it affect?)
- The Owner is generally determined by which “EntityModifier Table(s)” it’s assigned to.
- The effect of a modifier is determined by two things:
- The
ModifierType, which is a combination of anEffectType(what it does) and aCollectionType(what does it affect/what is the subject). - Its
ModifierArguments, which clarifies the specifics of theEffectType.
- The
- When a modifier activates can be controlled by
RequirementSets. They can check either the Owner (viaOwnerRequirementSetID), or the Subjects (viaSubjectRequirementSetID).- When checking the Owner: the Owner must meet the requirements for the modifier to activate at all.
- When checking the Subject(s): As there can be multiple subjects, each subject is checked individually. Only subjects that meet the requirements will have the modifier applied to them.
RequirementSetsconsist of one or moreRequirements.- What a Requirement checks for is determined by its
RequirementTypeand its associatedRequirementArguments.
Warning: Modifiers interact a little weirdly with saved games. When you save a game, any modifiers that exist get saved as they are. If you change them in the game’s database, modifiers in the saved game do NOT get changed, though modifiers added after loading the save will use the new definition. For this reason, it’s good practice to start a brand new game to test out any modifier changes.
GameEffects XML files
The Modifier System requires managing a LOT of different tables. Which is why Civilization VII has a simpler way of managing it all. When working with XML, instead of trying to modify multiple different tables in the database, you can instead do this:<GameEffects> instead of <Database>. You can use this on an UpdateDatabase action with the Game scope as per usual.
This allows you to create a new modifier much more easily, with the ModifierType, ModifierArguments RequirementSetID, and so forth being generated dynamically based off the provided id.
Note the structure. You create a Modifier, define an id, and give it a collection and effect. This allows you to skip defining the ModifierType in a separate step. You define the arguments as child elements of the Modifier. To add requirements, you add either SubjectRequirements or OwnerRequirements child elements, with further Requirement and Argument elements as necessary.
There are two caveats to this.
The first and most important is you cannot also modify the rest of the database in the same file. The XML file you use to create modifiers cannot also be used to add buildings, leaders, and so on. This is because we’re using <GameEffects> instead of <Database>. You’ll need to manage those in a separate file (you can assign both files to the same ActionGroup in the .modinfo file though)!
The second is the various “EntityModifier Tables” are not part of the Modifier declaration. That bit is considered part of the “rest of the database” that was mentioned in the previous point. So the various ConstructibleModifiers, GameModifiers, TraditionModifiers and so on, cannot be added via a gameplay database file with <GameEffects> as the root element.