Whenever you pick a new skill for a character, or gain an item, or apply a banner to a unit, or build a building - you are getting and using effects.
Effects are one of the most common game objects in all of Total War, and they drive a vast majority of any sort of dynamic/changing values throughout the game, and many game play systems. For example - the income from buildings is done through effects; attrition immunity is applied through effects; stat changes for units (ie. +Melee Attack for all archers) are done through effects.
Learning how to create and alter effects is a fundamental part of being able to make meaningful edits to the game.
NOTE: Written with R2/3K/WH2 in mind, this information should be valid from Empire to the present though. Please share if there are any inconsistencies.
Anatomy of an Effect
At the heart of all effects is the
effects_table db file. This table defines a few important things - the key of the effect, to link it up to other data objects and the localised text. It will also define some UI details here, typical - such as icon, priority (which determines the order effects show up, or whether it is hidden from view with 0), and the category, which determines where an effect shows up on a Character Details panel for example. Also mind the boolean in here, positive_is_good. This means that, if your value is a positive integer and this bool is set to true, the text will show up as green; if your value is negative and this bool is set to false, the text will show up as red.
An effect defined in just this table has no, well, effect - it has to be linked to another game object called
bonus_values. Bonus values are the game object that actually do a thing. Effects just enable those bonus values to be applied elsewhere. Bonus values can do a bunch, from increasing recruited lords' ranks, to adding charge bonus to a unit set, and far beyond, varying greatly based on the individual game. It's important to note here: no, you can't make new bonus_values. They are defined in the underlying game engine, and have code attached to them that actually make stuff happen. You can only use existing bonus_values, ever.
The bonus_values are defined in data in dummy tables called
campaign_bonus_value_ids_BONUS VALUE TYPE. For instance, the
basic bonus_values are found in the tables
campaign_bonus_value_ids_basic. Do note that you won't find these tables in RPFM; they're dummy tables, meaning they're not actually used to build data in the game and can't be edited.
The links between an effect is defined in tables called
effect_bonus_value_BONUS VALUE TYPE. These tables are typically either two or three columns - you link an effect key to the bonus_value dummy key, and a potential third piece of data needed for the effect. For instance,
effect_bonus_value_ids_unit_sets has three columns -
bonus_value_id which defines WHAT'S being edited (upkeep, charge bonus, etc), and
unit_set which defines which units get this effect.
However, not every effect needs a bonus value - it's fairly common to make a "dummy" effect, which is just UI and text, but doesn't actually have any bonus_values attached to it. This could be desired to make some clear UX about a functionality that is done through script or some other data object.
Applying an Effect
From here, the effect works and is a beautiful machination, but it doesn't do anything since it isn't applied anywhere. In order to take hold, it needs to be attached into an
Effect bundles are another fairly common data object, and their name is pretty much their definition - they're a nice lil' package of effects. There are two types of effect_bundles - explicit, and implicit. Explicit effect bundles are defined in the table
effect_bundles, and then those effect bundles can be applied through a variety of means. Implicit effect bundles are created when another effect-bundling table is used - for instance,
building_effects_junction. This table defines a list of effects that attach to a building, which are then bundled up in the game, thus implicitly.
Looking first at explicit effect_bundles - you would first define the effect_bundle key in
effect_bundles, which again is primarily UI information. However - there's an important bit of data in this table too, that we'll have to return to later. The
bundle_target column is very important, as it plays a big role in a future bit that we'll cover soon. It's mostly common sense here - if the effect bundle is going to be applied to a character via an ancillary, use the
character bundle_target. If it's applied to an army through a stance, use the
force bundle_target. This is the game object that has the effect_bundle, and the effects will be applied from that object.
From there, the next jump for making an explicit effect_bundle is the table
effect_bundles_to_effects_junctions. You'll never guess what it does!
First off the bat, we have the
effect_bundle_key - self-explanatory. Same with
effect_key and, I assume,
value. If you're editing a numerical bonus_value - like, editing a stat - it'll just be whatever number you want to add to the stat. If you're applying some stranger effect - like attrition immunity - that doesn't use actually numbers, you'll either use
0 for "deactivate", or
1 for "activate".
effect_scope is where it gets really important. Effect_scopes are defined in data, and new ones can be made - and, sometimes, are needed. Effect_scopes are composed of source and a target. The source of an effect_scope will have to be the
bundle_target defined in the effect_bundle earlier - you're applying an effect from the bundle_target's effect_bundle to something else. For example, if you wanted to add charge bonus on a character through an ancillary, you would just use the
character_to_character_own effect_scope - since the character has the effect_bundle and will receive the effect.
One more very important note - not every effect works with every effect target. You can't assign a charge_bonus to a
faction, for instance. That just doesn't make sense. 90% of the time, you can find which game objects are valid targets in the bonus value definitions (
campaign_bonus_value_ids_xxxxx), in the notes column. They'll say something like "used at character bonuses", which means it's only applicable to a character. On the 10% that aren't noted in that table, you can typically find examples in vanilla for what you want to do, and you can copy what they do.
Implicit effect_bundles are much the same - just without defining the effect_bundle on its own, and its bundle_target. This means the
effect_scope column doesn't have a predefined effect source, so you will need to be slightly more aware of what you're using. Again, check vanilla examples as much as you can.
Aside from using the aforementioned data structures, you can script some effect bundles as well. You can use a Lua script to apply (or remove) an explicit effect_bundle from a bundle_target - though mind it won't work for implicit effect_bundles.
For Warhammer 2 - you can read up here. The same general commands should exist in all other games, with the biggest difference lying in Three Kingdoms.
Likewise, Warhammer 2 got a GREAT new ability to completely change explicit effect_bundles dynamically while the game is going on. Instead of defining a dozen different effect bundles with 12 different values for the same effect, you can make one effect_bundle, and change its effect value dynamically. Read up more on it here.