1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-23 22:37:55 +02:00

Bonus limiters refactoring

- Split massive `parseLimiter` method in smaller chunks
- Added alternative format for limiters with named parameters instead of
unclear `parameters` entry that often leads to bugs in mods. Old format
is still available.
- Added detailed validation for limiter format
- Converted vcmi json's to use new format
- Removed parameter-less `CREATURE_FACTION` and `SAME_FACTION` limiter.
They are unused in mods and have unclear use-case that can be replaced
by other limiters
- Expanded documentation on limiter types

All mods that were supported before should still be supported
This commit is contained in:
Ivan Savenko
2025-07-08 13:00:53 +03:00
parent 46072a1d60
commit 4af7949571
13 changed files with 531 additions and 342 deletions

View File

@@ -2,16 +2,7 @@
## Predefined Limiters
The limiters take no parameters:
- SHOOTER_ONLY
- DRAGON_NATURE
- IS_UNDEAD
- CREATURE_NATIVE_TERRAIN
- CREATURE_FACTION
- SAME_FACTION
- CREATURES_ONLY
- OPPOSITE_SIDE
Simple limiters that take no parameters.
Example:
@@ -19,6 +10,30 @@ Example:
"limiters" : [ "SHOOTER_ONLY" ]
```
### SHOOTER_ONLY
Bonus is active if affected unit is a shooter (has SHOOTER bonus)
### DRAGON_NATURE
Bonus is active if affected unit is a dragon (has DRAGON_NATURE bonus)
### IS_UNDEAD
Bonus is active if affected unit is an undead (has UNDEAD bonus)
### CREATURE_NATIVE_TERRAIN
Bonus is active if affected unit is on native terrain
### CREATURES_ONLY
Bonus is active only on units
### OPPOSITE_SIDE
Bonus is active only for opposite side for a battle-wide bonus. Requires `BONUS_OWNER_UPDATER` to be present on bonus
## Customizable Limiters
### HAS_ANOTHER_BONUS_LIMITER
@@ -27,11 +42,12 @@ Bonus is only active if affected entity has another bonus that meets conditions
Parameters:
- Bonus type
- Bonus subtype (only used if bonus type is set)
- Bonus source type and bonus source ID
- `bonusType` - type of bonus to check against
- `bonusSubtype` - subtype of bonus to check against (only used if bonus type is set)
- `bonusSourceType` - source type of bonus to check against
- `bonusSourceID` -source ID of bonus to check against (only used if bonus type is set)
All parameters are optional. Values that don't need checking can be replaces with `null`
All parameters are optional.
Examples:
@@ -41,14 +57,8 @@ Examples:
"limiters" : [
{
"type" : "HAS_ANOTHER_BONUS_LIMITER",
"parameters" : [
null, // bonus type is ignored
null, // bonus subtype is also ignored
{
"type" : "SPELL_EFFECT", // look for bonus of type SPELL_EFFECT
"id" : "spell.bless" // ... from spell "Bless"
}
]
"bonusSourceType" : "SPELL_EFFECT", // look for bonus of type SPELL_EFFECT
"bonusSourceID" : "spell.bless" // ... from spell "Bless"
}
],
```
@@ -58,8 +68,8 @@ Examples:
```json
"limiters" : [
{
"parameters" : [ "DRAGON_NATURE" ],
"type" : "HAS_ANOTHER_BONUS_LIMITER"
"type" : "HAS_ANOTHER_BONUS_LIMITER",
"bonusType" : "DRAGON_NATURE"
}
],
```
@@ -70,16 +80,19 @@ Bonus is only active on creatures of specified type
Parameters:
- Creature id (string)
- (optional) include upgrades - default is false. If creature has multiple upgrades, or upgrades have their own upgrades, all such creatures will be affected. Special upgrades such as upgrades via specialties (Dragon, Gelu) are not affected
- `creature` - ID of creature to check against
- `includeUpgrades` - whether creature that is upgrade of `creature` should also pass this limiter. If creature has multiple upgrades, or upgrades have their own upgrades, all such creatures will be affected. Special upgrades such as upgrades via specialties (Dragon, Gelu) are not affected
Example:
```json
"limiters": [ {
"type":"CREATURE_TYPE_LIMITER",
"parameters": [ "angel", true ]
} ],
"limiters": [
{
"type" : "CREATURE_TYPE_LIMITER",
"creature" : "angel",
"includeUpgrades" : true
}
],
```
### CREATURE_ALIGNMENT_LIMITER
@@ -88,71 +101,113 @@ Bonus is only active on creatures of factions of specified alignment
Parameters:
- Alignment identifier, `good`, `evil`, or `neutral`
- `alignment` - ID of alignment that creature must have, `good`, `evil`, or `neutral`
```json
"limiters": [
{
"type" : "CREATURE_ALIGNMENT_LIMITER",
"alignment" : "evil"
}
],
```
### CREATURE_LEVEL_LIMITER
If parameters is empty, level limiter works as CREATURES_ONLY limiter
If parameters is empty, any creature will pass this limiter
Parameters:
- Minimal level
- Maximal level
- `minLevel` - minimal level that creature must have to pass limiter
- `maxlevel` - maximal level that creature must have to pass limiter
```json
"limiters": [
{
"type" : "CREATURE_LEVEL_LIMITER",
"minLevel" : 1,
"maxlevel" : 5
}
],
```
### FACTION_LIMITER
Also available as `CREATURE_FACTION_LIMITER`
Parameters:
- Faction identifier
- `faction` - faction that creature or hero must belong to
```json
"limiters": [
{
"type" : "FACTION_LIMITER",
"faction" : "castle"
}
],
```
### CREATURE_TERRAIN_LIMITER
Parameters:
- Terrain identifier
- `terrain` - identifier of terrain on which this creature must be to pass this limiter. If not set, creature will pass this limiter if it is on native terrain
Example:
```json
"limiters" : [ {
"type" : "CREATURE_TERRAIN_LIMITER",
"parameters" : ["sand"]
} ]
"limiters" : [
{
"type" : "CREATURE_TERRAIN_LIMITER",
"terrain" : "sand"
}
]
```
### UNIT_ON_HEXES
Parameters:
- List of affected battlefield hexes
For reference on tiles indexes see image below:
### HAS_CHARGES_LIMITER
Currently works only with spells. Sets the cost of use in charges
Parameters:
- use cost (charges)
- `cost` - use cost (charges)
```json
"limiters" : [ {
"type" : "HAS_CHARGES_LIMITER",
"parameters" : [2]
} ]
"limiters" : [
{
"type" : "HAS_CHARGES_LIMITER",
"cost" : 2
}
]
```
### UNIT_ON_HEXES
Parameters:
- `hexes` - List of affected battlefield hexes
```json
"limiters" : [
{
"type" : "UNIT_ON_HEXES",
"hexes" : [ 25, 50, 75 ]
}
]
```
For reference on tiles indexes see image below:
![Battlefield Hexes Layout](../../images/Battle_Field_Hexes.svg)
## Aggregate Limiters
The following limiters must be specified as the first element of a list,
and operate on the remaining limiters in that list:
The following limiters must be specified as the first element of a list, and operate on the remaining limiters in that list:
- allOf (default when no aggregate limiter is specified)
- anyOf
- noneOf
- `allOf` (default when no aggregate limiter is specified)
- `anyOf`
- `noneOf`
Example: