Files
vcmi/docs/developers/Bonus_System.md
T

78 lines
4.3 KiB
Markdown
Raw Normal View History

2024-07-16 20:29:20 +02:00
# Bonus System
2023-09-01 15:25:21 +03:00
The bonus system of VCMI is a set of mechanisms that make handling of different bonuses for heroes, towns, players and units easier. The system consists of a set of nodes representing objects that can be a source or a subject of a bonus and two directed acyclic graphs (DAGs) representing inheritance and propagation of bonuses. Core of bonus system is defined in HeroBonus.h file.
2023-08-13 00:17:38 +03:00
## Propagation and inheritance
2023-09-01 15:25:21 +03:00
Each bonus originates from some node in the bonus system, and may have propagator and limiter objects attached to it. Bonuses are shared around as follows:
2023-08-13 00:17:38 +03:00
2024-11-30 20:20:15 +00:00
1. Bonuses with propagator are propagated to "matching" descendants in the red DAG - which descendants match is determined by the propagator. Bonuses without a propagator will not be propagated.
2. Bonuses without limiters are inherited by all descendants in the black DAG. If limiters are present, they can restrict inheritance to certain nodes.
2023-08-13 00:17:38 +03:00
2023-09-01 15:25:21 +03:00
Inheritance is the default means of sharing bonuses. A typical example is an artefact granting a bonus to attack/defense stat, which is inherited by the hero wearing it, and then by creatures in the hero's army.
A common limiter is by creature - e.g. the hero Eric has a specialty that grants bonuses to attack, defense and speed, but only to griffins.
Propagation is used when bonuses need to be shared in a different direction than the black DAG for inheritance. E.g. Magi and Archmagi on the battlefield reduce the cost of spells for the controlling hero.
2023-08-13 00:17:38 +03:00
### Technical Details
2024-11-30 20:20:15 +00:00
- Propagation is done by copying bonuses to the target nodes. This happens when bonuses are added.
- Inheritance is done on-the-fly when needed, by traversing the black DAG. Results are cached to improve performance.
- Whenever a node changes (e.g. bonus added), a global counter gets increased which is used to check whether cached results are still current.
2023-08-13 00:17:38 +03:00
## Operations on the graph
2023-09-01 15:25:21 +03:00
There are two basic types of operations that can be performed on the graph:
2023-08-13 00:17:38 +03:00
### Adding a new node
2023-09-05 00:52:36 +03:00
When node is attached to a new black parent (the only possibility - adding parent is the same as adding a child to it), the propagation system is triggered and works as follows:
2024-11-30 20:20:15 +00:00
2023-09-01 15:25:21 +03:00
- For the attached node and its all red ancestors
- For every bonus
2023-09-05 00:52:36 +03:00
- Call propagator giving the new descendant - then attach appropriately bonuses to the red descendant of attached node (or the node itself).
2023-08-13 00:17:38 +03:00
2023-09-01 15:25:21 +03:00
E.g. when a hero equips an artifact, the hero gets attached to the artifact to inherit its bonuses.
2023-08-13 00:17:38 +03:00
### Deleting an existing node
2023-09-01 15:25:21 +03:00
Analogically to the adding a new node, just remove propagated bonuses instead of adding them. Then update the hierarchy.
2023-08-13 00:17:38 +03:00
2023-09-01 15:25:21 +03:00
E.g. when a hero removes an artifact, the hero (which became a child of the artifact when equipping it) is removed from it.
2023-08-13 00:17:38 +03:00
2023-09-01 15:25:21 +03:00
Note that only *propagated* bonuses need to be handled when nodes are added or removed. *Inheritance* is done on-the-fly and thus automatic.
2023-08-13 00:17:38 +03:00
## Limiters
2023-09-01 15:25:21 +03:00
If multiple limiters are specified for a bonus, a child inherits the bonus only if all limiters say that it should.
2023-08-13 00:17:38 +03:00
2023-09-01 15:25:21 +03:00
So e.g. a list of multiple creature type limiters (with different creatures) would ensure that no creature inherits the bonus. In such a case, the solution is to use one bonus per creature.
2023-08-13 00:17:38 +03:00
## Propagators
## Updaters
2023-09-01 15:25:21 +03:00
Updaters are objects attached to bonuses. They can modify a bonus (typically by changing *val*) during inheritance, including bonuses that a node "inherits" from itself, based on properties (typically level) of the node it passes through. Which nodes update a bonus depends on the type of updater. E.g. updaters that perform updates based on hero level will update bonuses as the are inherited by heroes.
2023-08-13 00:17:38 +03:00
2023-09-01 15:25:21 +03:00
The following example shows an artifact providing a bonus based on the level of the hero that wears it:
2023-08-13 00:17:38 +03:00
2024-12-01 12:18:06 +00:00
```json5
2023-09-01 15:25:21 +03:00
"core:greaterGnollsFlail":
{
"text" : { "description" : "This mighty flail increases the attack of all gnolls under the hero's command by twice the hero's level." },
"bonuses" : [
{
"limiters" : [
{
"parameters" : [ "gnoll", true ],
"type" : "CREATURE_TYPE_LIMITER"
}
],
"subtype" : "primSkill.attack",
"type" : "PRIMARY_SKILL",
"val" : 2,
"updater" : "TIMES_HERO_LEVEL"
}
]
}
```