mirror of
https://github.com/vcmi/vcmi.git
synced 2025-09-16 09:26:28 +02:00
Merge pull request #5900 from IvanSavenko/bonus_limiters
Bonus limiters refactoring
This commit is contained in:
@@ -913,14 +913,10 @@
|
||||
"limiters" : [
|
||||
{
|
||||
"type" : "HAS_ANOTHER_BONUS_LIMITER",
|
||||
"parameters" : [
|
||||
"PERCENTAGE_DAMAGE_BOOST",
|
||||
"damageTypeRanged",
|
||||
{
|
||||
"type" : "SECONDARY_SKILL",
|
||||
"id" : "secondarySkill.archery"
|
||||
}
|
||||
]
|
||||
"bonusType" : "PERCENTAGE_DAMAGE_BOOST",
|
||||
"bonusSubtype" : "damageTypeRanged",
|
||||
"bonusSourceType" : "SECONDARY_SKILL",
|
||||
"bonusSourceID" : "secondarySkill.archery"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -939,14 +935,10 @@
|
||||
"limiters" : [
|
||||
{
|
||||
"type" : "HAS_ANOTHER_BONUS_LIMITER",
|
||||
"parameters" : [
|
||||
"PERCENTAGE_DAMAGE_BOOST",
|
||||
"damageTypeRanged",
|
||||
{
|
||||
"type" : "SECONDARY_SKILL",
|
||||
"id" : "secondarySkill.archery"
|
||||
}
|
||||
]
|
||||
"bonusType" : "PERCENTAGE_DAMAGE_BOOST",
|
||||
"bonusSubtype" : "damageTypeRanged",
|
||||
"bonusSourceType" : "SECONDARY_SKILL",
|
||||
"bonusSourceID" : "secondarySkill.archery"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -965,14 +957,10 @@
|
||||
"limiters" : [
|
||||
{
|
||||
"type" : "HAS_ANOTHER_BONUS_LIMITER",
|
||||
"parameters" : [
|
||||
"PERCENTAGE_DAMAGE_BOOST",
|
||||
"damageTypeRanged",
|
||||
{
|
||||
"type" : "SECONDARY_SKILL",
|
||||
"id" : "secondarySkill.archery"
|
||||
}
|
||||
]
|
||||
"bonusType" : "PERCENTAGE_DAMAGE_BOOST",
|
||||
"bonusSubtype" : "damageTypeRanged",
|
||||
"bonusSourceType" : "SECONDARY_SKILL",
|
||||
"bonusSourceID" : "secondarySkill.archery"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1993,19 +1981,19 @@
|
||||
"IS_UNDEAD",
|
||||
{
|
||||
"type" : "HAS_ANOTHER_BONUS_LIMITER",
|
||||
"parameters" : [ "NON_LIVING" ]
|
||||
"bonusType" : "NON_LIVING"
|
||||
},
|
||||
{
|
||||
"type" : "HAS_ANOTHER_BONUS_LIMITER",
|
||||
"parameters" : [ "MECHANICAL" ]
|
||||
"bonusType" : "MECHANICAL"
|
||||
},
|
||||
{
|
||||
"type" : "HAS_ANOTHER_BONUS_LIMITER",
|
||||
"parameters" : [ "GARGOYLE" ]
|
||||
"bonusType" : "GARGOYLE"
|
||||
},
|
||||
{
|
||||
"type" : "HAS_ANOTHER_BONUS_LIMITER",
|
||||
"parameters" : [ "SIEGE_WEAPON" ]
|
||||
"bonusType" : "SIEGE_WEAPON"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -2018,15 +2006,15 @@
|
||||
"IS_UNDEAD",
|
||||
{
|
||||
"type" : "HAS_ANOTHER_BONUS_LIMITER",
|
||||
"parameters" : [ "NON_LIVING" ]
|
||||
"bonusType" : "NON_LIVING"
|
||||
},
|
||||
{
|
||||
"type" : "HAS_ANOTHER_BONUS_LIMITER",
|
||||
"parameters" : [ "MECHANICAL" ]
|
||||
"bonusType" : "MECHANICAL"
|
||||
},
|
||||
{
|
||||
"type" : "HAS_ANOTHER_BONUS_LIMITER",
|
||||
"parameters" : [ "GARGOYLE" ]
|
||||
"bonusType" : "GARGOYLE"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@@ -80,14 +80,14 @@
|
||||
"val" : 1,
|
||||
"valueType" : "BASE_NUMBER",
|
||||
"description" : "@core.arraytxt.123",
|
||||
"limiters": [{ "type" : "CREATURE_ALIGNMENT_LIMITER", "parameters" : ["good"] }]
|
||||
"limiters": [{ "type" : "CREATURE_ALIGNMENT_LIMITER", "alignment" : "good" }]
|
||||
},
|
||||
{
|
||||
"type" : "MORALE",
|
||||
"val" : -1,
|
||||
"valueType" : "BASE_NUMBER",
|
||||
"description" : "@core.arraytxt.124",
|
||||
"limiters": [{ "type" : "CREATURE_ALIGNMENT_LIMITER", "parameters" : ["evil"] }]
|
||||
"limiters": [{ "type" : "CREATURE_ALIGNMENT_LIMITER", "alignment" : "evil" }]
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -100,7 +100,7 @@
|
||||
"val" : 2,
|
||||
"valueType" : "BASE_NUMBER",
|
||||
"description" : "@core.arraytxt.83",
|
||||
"limiters": [{ "type" : "CREATURE_ALIGNMENT_LIMITER", "parameters" : ["neutral"] }]
|
||||
"limiters": [{ "type" : "CREATURE_ALIGNMENT_LIMITER", "alignment" : "neutral" }]
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -113,14 +113,14 @@
|
||||
"val" : -1,
|
||||
"valueType" : "BASE_NUMBER",
|
||||
"description" : "@core.arraytxt.126",
|
||||
"limiters": [{ "type" : "CREATURE_ALIGNMENT_LIMITER", "parameters" : ["good"] }]
|
||||
"limiters": [{ "type" : "CREATURE_ALIGNMENT_LIMITER", "alignment" : "good" }]
|
||||
},
|
||||
{
|
||||
"type" : "MORALE",
|
||||
"val" : 1,
|
||||
"valueType" : "BASE_NUMBER",
|
||||
"description" : "@core.arraytxt.125",
|
||||
"limiters": [{ "type" : "CREATURE_ALIGNMENT_LIMITER", "parameters" : ["evil"] }]
|
||||
"limiters": [{ "type" : "CREATURE_ALIGNMENT_LIMITER", "alignment" : "evil" }]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@@ -103,7 +103,7 @@
|
||||
"OPPOSITE_SIDE",
|
||||
{
|
||||
"type" : "HAS_ANOTHER_BONUS_LIMITER",
|
||||
"parameters" : [ "LIVING" ]
|
||||
"bonusType" : "LIVING"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@@ -145,14 +145,8 @@
|
||||
"limiters" : [
|
||||
{
|
||||
"type" : "HAS_ANOTHER_BONUS_LIMITER",
|
||||
"parameters" : [
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"type" : "SPELL_EFFECT",
|
||||
"id" : "spell.bless"
|
||||
}
|
||||
]
|
||||
"bonusSourceType" : "SPELL_EFFECT",
|
||||
"bonusSourceID" : "spell.bless"
|
||||
}
|
||||
],
|
||||
"updater" : "TIMES_HERO_LEVEL_DIVIDE_STACK_LEVEL",
|
||||
|
@@ -13,8 +13,9 @@
|
||||
"base" : {
|
||||
"limiters" : [
|
||||
{
|
||||
"parameters" : [ "psychicElemental", true ],
|
||||
"type" : "CREATURE_TYPE_LIMITER"
|
||||
"type" : "CREATURE_TYPE_LIMITER",
|
||||
"creature" : "psychicElemental",
|
||||
"includeUpgrades" : true
|
||||
}
|
||||
],
|
||||
"type" : "PRIMARY_SKILL",
|
||||
@@ -40,8 +41,9 @@
|
||||
"base" : {
|
||||
"limiters" : [
|
||||
{
|
||||
"parameters" : [ "earthElemental", true ],
|
||||
"type" : "CREATURE_TYPE_LIMITER"
|
||||
"type" : "CREATURE_TYPE_LIMITER",
|
||||
"creature" : "earthElemental",
|
||||
"includeUpgrades" : true
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -78,8 +80,9 @@
|
||||
"base" : {
|
||||
"limiters" : [
|
||||
{
|
||||
"parameters" : [ "fireElemental", true ],
|
||||
"type" : "CREATURE_TYPE_LIMITER"
|
||||
"type" : "CREATURE_TYPE_LIMITER",
|
||||
"creature" : "fireElemental",
|
||||
"includeUpgrades" : true
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -116,8 +119,9 @@
|
||||
"attack" : {
|
||||
"limiters" : [
|
||||
{
|
||||
"parameters" : [ "waterElemental", true ],
|
||||
"type" : "CREATURE_TYPE_LIMITER"
|
||||
"type" : "CREATURE_TYPE_LIMITER",
|
||||
"creature" : "waterElemental",
|
||||
"includeUpgrades" : true
|
||||
}
|
||||
],
|
||||
"subtype" : "primarySkill.attack",
|
||||
@@ -141,8 +145,9 @@
|
||||
"base" : {
|
||||
"limiters" : [
|
||||
{
|
||||
"parameters" : [ "psychicElemental", true ],
|
||||
"type" : "CREATURE_TYPE_LIMITER"
|
||||
"type" : "CREATURE_TYPE_LIMITER",
|
||||
"creature" : "psychicElemental",
|
||||
"includeUpgrades" : true
|
||||
}
|
||||
],
|
||||
"type" : "PRIMARY_SKILL",
|
||||
@@ -168,8 +173,9 @@
|
||||
"base" : {
|
||||
"limiters" : [
|
||||
{
|
||||
"parameters" : [ "earthElemental", true ],
|
||||
"type" : "CREATURE_TYPE_LIMITER"
|
||||
"type" : "CREATURE_TYPE_LIMITER",
|
||||
"creature" : "earthElemental",
|
||||
"includeUpgrades" : true
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -205,8 +211,9 @@
|
||||
"base" : {
|
||||
"limiters" : [
|
||||
{
|
||||
"parameters" : [ "fireElemental", true ],
|
||||
"type" : "CREATURE_TYPE_LIMITER"
|
||||
"type" : "CREATURE_TYPE_LIMITER",
|
||||
"creature" : "fireElemental",
|
||||
"includeUpgrades" : true
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -244,8 +251,9 @@
|
||||
"attack" : {
|
||||
"limiters" : [
|
||||
{
|
||||
"parameters" : [ "waterElemental", true ],
|
||||
"type" : "CREATURE_TYPE_LIMITER"
|
||||
"type" : "CREATURE_TYPE_LIMITER",
|
||||
"creature" : "waterElemental",
|
||||
"includeUpgrades" : true
|
||||
}
|
||||
],
|
||||
"subtype" : "primarySkill.attack",
|
||||
|
@@ -110,8 +110,9 @@
|
||||
"base" : {
|
||||
"limiters" : [
|
||||
{
|
||||
"parameters" : [ "behemoth", true ],
|
||||
"type" : "CREATURE_TYPE_LIMITER"
|
||||
"type" : "CREATURE_TYPE_LIMITER",
|
||||
"creature" : "behemoth",
|
||||
"includeUpgrades" : true
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -149,8 +150,9 @@
|
||||
"base" : {
|
||||
"limiters" : [
|
||||
{
|
||||
"parameters" : [ "blackKnight", true ],
|
||||
"type" : "CREATURE_TYPE_LIMITER"
|
||||
"type" : "CREATURE_TYPE_LIMITER",
|
||||
"creature" : "blackKnight",
|
||||
"includeUpgrades" : true
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -189,8 +191,8 @@
|
||||
"base" : {
|
||||
"limiters" : [
|
||||
{
|
||||
"parameters" : [ "DRAGON_NATURE" ],
|
||||
"type" : "HAS_ANOTHER_BONUS_LIMITER"
|
||||
"type" : "HAS_ANOTHER_BONUS_LIMITER",
|
||||
"bonusType" : "DRAGON_NATURE"
|
||||
}
|
||||
],
|
||||
"type" : "PRIMARY_SKILL",
|
||||
@@ -233,8 +235,8 @@
|
||||
"base" : {
|
||||
"limiters" : [
|
||||
{
|
||||
"parameters" : [ "DRAGON_NATURE" ],
|
||||
"type" : "HAS_ANOTHER_BONUS_LIMITER"
|
||||
"type" : "HAS_ANOTHER_BONUS_LIMITER",
|
||||
"bonusType" : "DRAGON_NATURE"
|
||||
}
|
||||
],
|
||||
"type" : "PRIMARY_SKILL",
|
||||
@@ -306,8 +308,9 @@
|
||||
"base" : {
|
||||
"limiters" : [
|
||||
{
|
||||
"parameters" : [ "devil", true ],
|
||||
"type" : "CREATURE_TYPE_LIMITER"
|
||||
"type" : "CREATURE_TYPE_LIMITER",
|
||||
"creature" : "devil",
|
||||
"includeUpgrades" : true
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@@ -43,7 +43,7 @@
|
||||
{
|
||||
"type" : "array",
|
||||
"minItems" : 1,
|
||||
"additionalItems" : { "type" : "string" }
|
||||
"items" : { "type" : "string" }
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@@ -7,33 +7,166 @@
|
||||
"definitions" :
|
||||
{
|
||||
"nestedLimiter" : {
|
||||
"anyOf" : [
|
||||
"allOf" : [
|
||||
{
|
||||
"type" : "string",
|
||||
"enum" : [ "SHOOTER_ONLY", "DRAGON_NATURE", "IS_UNDEAD", "CREATURE_NATIVE_TERRAIN", "CREATURE_FACTION", "SAME_FACTION", "CREATURES_ONLY", "OPPOSITE_SIDE" ],
|
||||
"description" : "parameterless limiter or boolean operator at start of array"
|
||||
"if" : {
|
||||
"type" : "string"
|
||||
},
|
||||
"then" : {
|
||||
"enum" : [ "allOf", "anyOf", "noneOf", "SHOOTER_ONLY", "DRAGON_NATURE", "IS_UNDEAD", "CREATURE_NATIVE_TERRAIN", "CREATURES_ONLY", "OPPOSITE_SIDE" ],
|
||||
"description" : "parameterless limiter or boolean operator at start of array"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type" : "object",
|
||||
"additionalProperties" : false,
|
||||
"properties" : {
|
||||
"type" : {
|
||||
"type" : "string",
|
||||
"enum" : [ "CREATURE_TYPE_LIMITER", "HAS_ANOTHER_BONUS_LIMITER", "CREATURE_ALIGNMENT_LIMITER", "FACTION_LIMITER", "CREATURE_LEVEL_LIMITER", "CREATURE_TERRAIN_LIMITER", "UNIT_ON_HEXES" ],
|
||||
"description" : "type"
|
||||
},
|
||||
"parameters" : {
|
||||
"type" : "array",
|
||||
"description" : "parameters",
|
||||
"additionalItems" : true
|
||||
"if" : {
|
||||
"type" : "object",
|
||||
"required" : [ "type" ],
|
||||
"properties" : {
|
||||
"type" : { "type" : "string", "const" : "CREATURE_TYPE_LIMITER" }
|
||||
}
|
||||
},
|
||||
"then" : {
|
||||
"additionalProperties" : false,
|
||||
"required" : [ "type", "creature" ],
|
||||
"properties" : {
|
||||
"type" : { "type" : "string", "const" : "CREATURE_TYPE_LIMITER" },
|
||||
"parameters" : { "type" : "array", "description" : "parameters", "additionalItems" : true },
|
||||
"creature" : { "type" : "string" },
|
||||
"includeUpgrades" : { "type" : "boolean" }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type" : "array",
|
||||
"additionalItems" : {
|
||||
"$ref" : "#/definitions/nestedLimiter",
|
||||
"description" : "nested limiters optionally prefixed with boolean operator"
|
||||
"if" : {
|
||||
"type" : "object",
|
||||
"required" : [ "type" ],
|
||||
"properties" : {
|
||||
"type" : { "type" : "string", "const" : "HAS_ANOTHER_BONUS_LIMITER" }
|
||||
}
|
||||
},
|
||||
"then" : {
|
||||
"additionalProperties" : false,
|
||||
"properties" : {
|
||||
"type" : { "type" : "string", "const" : "HAS_ANOTHER_BONUS_LIMITER" },
|
||||
"parameters" : { "type" : "array", "description" : "parameters", "additionalItems" : true },
|
||||
"bonusType" : { "type" : "string" },
|
||||
"bonusSubtype" : { "type" : "string" },
|
||||
"bonusSourceType" : { "type" : "string" },
|
||||
"bonusSourceID" : { "type" : "string" }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"if" : {
|
||||
"type" : "object",
|
||||
"properties" : {
|
||||
"type" : { "type" : "string", "const" : "CREATURE_ALIGNMENT_LIMITER" }
|
||||
}
|
||||
},
|
||||
"then" : {
|
||||
"additionalProperties" : false,
|
||||
"properties" : {
|
||||
"type" : { "type" : "string", "const" : "CREATURE_ALIGNMENT_LIMITER" },
|
||||
"parameters" : { "type" : "array", "description" : "parameters", "additionalItems" : true },
|
||||
"alignment" : { "type" : "string", "enum" : [ "good", "evil", "neutral" ] }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"if" : {
|
||||
"type" : "object",
|
||||
"required" : [ "type" ],
|
||||
"properties" : {
|
||||
"type" : { "type" : "string", "enum" : [ "CREATURE_FACTION_LIMITER", "FACTION_LIMITER" ] }
|
||||
}
|
||||
},
|
||||
"then" : {
|
||||
"additionalProperties" : false,
|
||||
"properties" : {
|
||||
"type" : { "type" : "string", "enum" : [ "CREATURE_FACTION_LIMITER", "FACTION_LIMITER" ] },
|
||||
"parameters" : { "type" : "array", "description" : "parameters", "additionalItems" : true },
|
||||
"faction" : { "type" : "string" }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"if" : {
|
||||
"type" : "object",
|
||||
"required" : [ "type" ],
|
||||
"properties" : {
|
||||
"type" : { "type" : "string", "const" : "CREATURE_LEVEL_LIMITER" }
|
||||
}
|
||||
},
|
||||
"then" : {
|
||||
"additionalProperties" : false,
|
||||
"properties" : {
|
||||
"type" : { "type" : "string", "const" : "CREATURE_LEVEL_LIMITER" },
|
||||
"parameters" : { "type" : "array", "description" : "parameters", "additionalItems" : true },
|
||||
"minLevel" : { "type" : "number" },
|
||||
"maxlevel" : { "type" : "number" }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"if" : {
|
||||
"type" : "object",
|
||||
"required" : [ "type" ],
|
||||
"properties" : {
|
||||
"type" : { "type" : "string", "const" : "CREATURE_TERRAIN_LIMITER" }
|
||||
}
|
||||
},
|
||||
"then" : {
|
||||
"additionalProperties" : false,
|
||||
"properties" : {
|
||||
"type" : { "type" : "string", "const" : "CREATURE_TERRAIN_LIMITER" },
|
||||
"parameters" : { "type" : "array", "description" : "parameters", "additionalItems" : true },
|
||||
"terrain" : { "type" : "string" }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"if" : {
|
||||
"type" : "object",
|
||||
"required" : [ "type" ],
|
||||
"properties" : {
|
||||
"type" : { "type" : "string", "const" : "UNIT_ON_HEXES" }
|
||||
}
|
||||
},
|
||||
"then" : {
|
||||
"additionalProperties" : false,
|
||||
"properties" : {
|
||||
"type" : { "type" : "string", "const" : "UNIT_ON_HEXES" },
|
||||
"parameters" : { "type" : "array", "description" : "parameters", "additionalItems" : true },
|
||||
"hexes" : { "type" : "array", "items" : { "type" : "number" } }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"if" : {
|
||||
"type" : "object",
|
||||
"required" : [ "type" ],
|
||||
"properties" : {
|
||||
"type" : { "type" : "string", "const" : "HAS_CHARGES_LIMITER" }
|
||||
}
|
||||
},
|
||||
"then" : {
|
||||
"additionalProperties" : false,
|
||||
"properties" : {
|
||||
"type" : { "type" : "string", "const" : "HAS_CHARGES_LIMITER" },
|
||||
"parameters" : { "type" : "array", "description" : "parameters", "additionalItems" : true },
|
||||
"cost" : { "type" : "number" }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"if" : {
|
||||
"type" : "array"
|
||||
},
|
||||
"then" : {
|
||||
"items" : {
|
||||
"$ref" : "#/definitions/nestedLimiter",
|
||||
"description" : "nested limiters optionally prefixed with boolean operator"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@@ -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:
|
||||
|
||||

|
||||
|
||||
## 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:
|
||||
|
||||
|
@@ -30,8 +30,6 @@ const std::map<std::string, TLimiterPtr> bonusLimiterMap =
|
||||
{"DRAGON_NATURE", std::make_shared<HasAnotherBonusLimiter>(BonusType::DRAGON_NATURE)},
|
||||
{"IS_UNDEAD", std::make_shared<HasAnotherBonusLimiter>(BonusType::UNDEAD)},
|
||||
{"CREATURE_NATIVE_TERRAIN", std::make_shared<CreatureTerrainLimiter>()},
|
||||
{"CREATURE_FACTION", std::make_shared<AllOfLimiter>(std::initializer_list<TLimiterPtr>{std::make_shared<CreatureLevelLimiter>(), std::make_shared<FactionLimiter>()})},
|
||||
{"SAME_FACTION", std::make_shared<FactionLimiter>()},
|
||||
{"CREATURES_ONLY", std::make_shared<CreatureLevelLimiter>()},
|
||||
{"OPPOSITE_SIDE", std::make_shared<OppositeSideLimiter>()},
|
||||
};
|
||||
|
@@ -486,180 +486,215 @@ std::shared_ptr<Bonus> JsonUtils::parseBonus(const JsonVector & ability_vec)
|
||||
return b;
|
||||
}
|
||||
|
||||
static std::shared_ptr<const ILimiter> parseAggregateLimiter(const JsonNode & limiter)
|
||||
{
|
||||
const JsonVector & subLimiters = limiter.Vector();
|
||||
if(subLimiters.empty())
|
||||
{
|
||||
logMod->warn("Warning: empty limiter list");
|
||||
return std::make_shared<AllOfLimiter>();
|
||||
}
|
||||
std::shared_ptr<AggregateLimiter> result;
|
||||
int offset = 1;
|
||||
// determine limiter type and offset for sub-limiters
|
||||
if(subLimiters[0].getType() == JsonNode::JsonType::DATA_STRING)
|
||||
{
|
||||
const std::string & aggregator = subLimiters[0].String();
|
||||
if(aggregator == AllOfLimiter::aggregator)
|
||||
result = std::make_shared<AllOfLimiter>();
|
||||
else if(aggregator == AnyOfLimiter::aggregator)
|
||||
result = std::make_shared<AnyOfLimiter>();
|
||||
else if(aggregator == NoneOfLimiter::aggregator)
|
||||
result = std::make_shared<NoneOfLimiter>();
|
||||
}
|
||||
if(!result)
|
||||
{
|
||||
// collapse for single limiter without explicit aggregate operator
|
||||
if(subLimiters.size() == 1)
|
||||
return JsonUtils::parseLimiter(subLimiters[0]);
|
||||
// implicit aggregator must be allOf
|
||||
result = std::make_shared<AllOfLimiter>();
|
||||
offset = 0;
|
||||
}
|
||||
if(subLimiters.size() == offset)
|
||||
logMod->warn("Warning: empty sub-limiter list");
|
||||
for(int sl = offset; sl < subLimiters.size(); ++sl)
|
||||
result->add(JsonUtils::parseLimiter(subLimiters[sl]));
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::shared_ptr<const ILimiter> parseCreatureTypeLimiter(const JsonNode & limiter)
|
||||
{
|
||||
auto creatureLimiter = std::make_shared<CCreatureTypeLimiter>();
|
||||
|
||||
const JsonNode & parameters = limiter["parameters"];
|
||||
const JsonNode & creatureNode = limiter.Struct().count("creature") ? limiter["creature"] : parameters[0];
|
||||
const JsonNode & upgradesNode = limiter.Struct().count("includeUpgrades") ? limiter["includeUpgrades"] : parameters[1];
|
||||
|
||||
LIBRARY->identifiers()->requestIdentifier( "creature", creatureNode, [creatureLimiter](si32 creature)
|
||||
{
|
||||
creatureLimiter->setCreature(CreatureID(creature));
|
||||
});
|
||||
|
||||
creatureLimiter->includeUpgrades = upgradesNode.Bool();
|
||||
return creatureLimiter;
|
||||
}
|
||||
|
||||
static std::shared_ptr<const ILimiter> parseHasAnotherBonusLimiter(const JsonNode & limiter)
|
||||
{
|
||||
auto bonusLimiter = std::make_shared<HasAnotherBonusLimiter>();
|
||||
|
||||
static const JsonNode nullNode;
|
||||
const JsonNode & parameters = limiter["parameters"];
|
||||
const JsonNode & jsonType = limiter.Struct().count("bonusType") ? limiter["bonusType"] : parameters[0];
|
||||
const JsonNode & jsonSubtype = limiter.Struct().count("bonusSubtype") ? limiter["bonusSubtype"] : (parameters.Vector().size() > 2 ? parameters[1] : nullNode);
|
||||
const JsonNode & jsonSourceType = limiter.Struct().count("bonusSourceType") ? limiter["bonusSourceType"] : (parameters.Vector().size() > 2 ? parameters[2]["type"] : parameters[1]["type"]);
|
||||
const JsonNode & jsonSourceID = limiter.Struct().count("bonusSourceID") ? limiter["bonusSourceID"] : (parameters.Vector().size() > 2 ? parameters[2]["id"] : parameters[1]["id"]);
|
||||
|
||||
if (!jsonType.isNull())
|
||||
{
|
||||
LIBRARY->identifiers()->requestIdentifier("bonus", jsonType, [bonusLimiter, jsonSubtype](si32 bonusID)
|
||||
{
|
||||
bonusLimiter->type = static_cast<BonusType>(bonusID);
|
||||
if (!jsonSubtype.isNull())
|
||||
loadBonusSubtype(bonusLimiter->subtype, bonusLimiter->type, jsonSubtype);
|
||||
});
|
||||
}
|
||||
|
||||
if(!jsonSourceType.isNull())
|
||||
{
|
||||
auto sourceIt = bonusSourceMap.find(jsonSourceType.String());
|
||||
if(sourceIt != bonusSourceMap.end())
|
||||
{
|
||||
bonusLimiter->source = sourceIt->second;
|
||||
bonusLimiter->isSourceRelevant = true;
|
||||
if(!jsonSourceID.isNull()) {
|
||||
loadBonusSourceInstance(bonusLimiter->sid, bonusLimiter->source, jsonSourceID);
|
||||
bonusLimiter->isSourceIDRelevant = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
logMod->warn("HAS_ANOTHER_BONUS_LIMITER: unknown bonus source type '%s'!", jsonSourceType.String());
|
||||
}
|
||||
|
||||
return bonusLimiter;
|
||||
}
|
||||
|
||||
static std::shared_ptr<const ILimiter> parseCreatureAlignmentLimiter(const JsonNode & limiter)
|
||||
{
|
||||
const JsonNode & parameters = limiter["parameters"];
|
||||
const JsonNode & alignmentNode = limiter.Struct().count("alignment") ? limiter["alignment"] : parameters[0];
|
||||
|
||||
int alignment = vstd::find_pos(GameConstants::ALIGNMENT_NAMES, alignmentNode.String());
|
||||
if(alignment == -1)
|
||||
{
|
||||
logMod->error("Error: invalid alignment %s.", alignmentNode.String());
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
return std::make_shared<CreatureAlignmentLimiter>(static_cast<EAlignment>(alignment));
|
||||
}
|
||||
|
||||
static std::shared_ptr<const ILimiter> parseFactionLimiter(const JsonNode & limiter)
|
||||
{
|
||||
const JsonNode & parameters = limiter["parameters"];
|
||||
const JsonNode & factionNode = limiter.Struct().count("faction") ? limiter["faction"] : parameters[0];
|
||||
|
||||
auto factionLimiter = std::make_shared<FactionLimiter>();
|
||||
LIBRARY->identifiers()->requestIdentifier("faction", factionNode, [=](si32 faction)
|
||||
{
|
||||
factionLimiter->faction = FactionID(faction);
|
||||
});
|
||||
return factionLimiter;
|
||||
}
|
||||
|
||||
static std::shared_ptr<const ILimiter> parseCreatureLevelLimiter(const JsonNode & limiter)
|
||||
{
|
||||
const JsonNode & parameters = limiter["parameters"];
|
||||
const JsonNode & minLevelNode = limiter.Struct().count("minLevel") ? limiter["minLevel"] : parameters[0];
|
||||
const JsonNode & maxLevelNode = limiter.Struct().count("maxlevel") ? limiter["maxlevel"] : parameters[1];
|
||||
|
||||
//If parameters is empty, level limiter works as CREATURES_ONLY limiter
|
||||
auto levelLimiter = std::make_shared<CreatureLevelLimiter>();
|
||||
|
||||
if (!minLevelNode.isNull())
|
||||
levelLimiter->minLevel = minLevelNode.Integer();
|
||||
|
||||
if (!maxLevelNode.isNull())
|
||||
levelLimiter->maxLevel = maxLevelNode.Integer();
|
||||
|
||||
return levelLimiter;
|
||||
}
|
||||
|
||||
static std::shared_ptr<const ILimiter> parseCreatureTerrainLimiter(const JsonNode & limiter)
|
||||
{
|
||||
const JsonNode & parameters = limiter["parameters"];
|
||||
const JsonNode & terrainNode = limiter.Struct().count("terrain") ? limiter["terrain"] : parameters[0];
|
||||
|
||||
auto terrainLimiter = std::make_shared<CreatureTerrainLimiter>();
|
||||
if(!terrainNode.isNull())
|
||||
{
|
||||
LIBRARY->identifiers()->requestIdentifier("terrain", terrainNode, [terrainLimiter](si32 terrain)
|
||||
{
|
||||
terrainLimiter->terrainType = terrain;
|
||||
});
|
||||
}
|
||||
return terrainLimiter;
|
||||
}
|
||||
|
||||
static std::shared_ptr<const ILimiter> parseUnitOnHexLimiter(const JsonNode & limiter)
|
||||
{
|
||||
const JsonNode & parameters = limiter["parameters"];
|
||||
const JsonNode & hexesNode = limiter.Struct().count("hexes") ? limiter["hexes"] : parameters[0];
|
||||
|
||||
auto hexLimiter = std::make_shared<UnitOnHexLimiter>();
|
||||
|
||||
for (const auto & parameter : hexesNode.Vector())
|
||||
hexLimiter->applicableHexes.insert(BattleHex(parameter.Integer()));
|
||||
|
||||
return hexLimiter;
|
||||
}
|
||||
|
||||
static std::shared_ptr<const ILimiter> parseHasChargesLimiter(const JsonNode & limiter)
|
||||
{
|
||||
const JsonNode & parameters = limiter["parameters"];
|
||||
const JsonNode & costNode = limiter.Struct().count("cost") ? limiter["cost"] : parameters[0];
|
||||
auto hasChargesLimiter = std::make_shared<HasChargesLimiter>();
|
||||
|
||||
if (!costNode.isNull())
|
||||
hasChargesLimiter->chargeCost = costNode.Integer();
|
||||
|
||||
return hasChargesLimiter;
|
||||
}
|
||||
|
||||
std::shared_ptr<const ILimiter> JsonUtils::parseLimiter(const JsonNode & limiter)
|
||||
{
|
||||
static const std::map<std::string, std::function<std::shared_ptr<const ILimiter>(const JsonNode & limiter)>> limiterParsers = {
|
||||
{"CREATURE_TYPE_LIMITER", parseCreatureTypeLimiter },
|
||||
{"HAS_ANOTHER_BONUS_LIMITER", parseHasAnotherBonusLimiter },
|
||||
{"CREATURE_ALIGNMENT_LIMITER", parseCreatureAlignmentLimiter},
|
||||
{"FACTION_LIMITER", parseFactionLimiter },
|
||||
{"CREATURE_FACTION_LIMITER", parseFactionLimiter },
|
||||
{"CREATURE_LEVEL_LIMITER", parseCreatureLevelLimiter },
|
||||
{"CREATURE_TERRAIN_LIMITER", parseCreatureTerrainLimiter },
|
||||
{"UNIT_ON_HEXES", parseUnitOnHexLimiter },
|
||||
{"HAS_CHARGES_LIMITER", parseHasChargesLimiter },
|
||||
};
|
||||
|
||||
switch(limiter.getType())
|
||||
{
|
||||
case JsonNode::JsonType::DATA_VECTOR:
|
||||
{
|
||||
const JsonVector & subLimiters = limiter.Vector();
|
||||
if(subLimiters.empty())
|
||||
{
|
||||
logMod->warn("Warning: empty limiter list");
|
||||
return std::make_shared<AllOfLimiter>();
|
||||
}
|
||||
std::shared_ptr<AggregateLimiter> result;
|
||||
int offset = 1;
|
||||
// determine limiter type and offset for sub-limiters
|
||||
if(subLimiters[0].getType() == JsonNode::JsonType::DATA_STRING)
|
||||
{
|
||||
const std::string & aggregator = subLimiters[0].String();
|
||||
if(aggregator == AllOfLimiter::aggregator)
|
||||
result = std::make_shared<AllOfLimiter>();
|
||||
else if(aggregator == AnyOfLimiter::aggregator)
|
||||
result = std::make_shared<AnyOfLimiter>();
|
||||
else if(aggregator == NoneOfLimiter::aggregator)
|
||||
result = std::make_shared<NoneOfLimiter>();
|
||||
}
|
||||
if(!result)
|
||||
{
|
||||
// collapse for single limiter without explicit aggregate operator
|
||||
if(subLimiters.size() == 1)
|
||||
return parseLimiter(subLimiters[0]);
|
||||
// implicit aggregator must be allOf
|
||||
result = std::make_shared<AllOfLimiter>();
|
||||
offset = 0;
|
||||
}
|
||||
if(subLimiters.size() == offset)
|
||||
logMod->warn("Warning: empty sub-limiter list");
|
||||
for(int sl = offset; sl < subLimiters.size(); ++sl)
|
||||
result->add(parseLimiter(subLimiters[sl]));
|
||||
return result;
|
||||
}
|
||||
break;
|
||||
case JsonNode::JsonType::DATA_STRING: //pre-defined limiters
|
||||
return parseByMap(bonusLimiterMap, &limiter, "limiter type ");
|
||||
break;
|
||||
case JsonNode::JsonType::DATA_STRUCT: //customizable limiters
|
||||
case JsonNode::JsonType::DATA_VECTOR:
|
||||
return parseAggregateLimiter(limiter);
|
||||
case JsonNode::JsonType::DATA_STRING: //pre-defined limiters
|
||||
return parseByMap(bonusLimiterMap, &limiter, "limiter type ");
|
||||
case JsonNode::JsonType::DATA_STRUCT: //customizable limiters
|
||||
{
|
||||
std::string limiterType = limiter["type"].String();
|
||||
const JsonNode & parameters = limiter["parameters"];
|
||||
if(limiterType == "CREATURE_TYPE_LIMITER")
|
||||
{
|
||||
auto creatureLimiter = std::make_shared<CCreatureTypeLimiter>();
|
||||
LIBRARY->identifiers()->requestIdentifier("creature", parameters[0], [=](si32 creature)
|
||||
{
|
||||
creatureLimiter->setCreature(CreatureID(creature));
|
||||
});
|
||||
auto includeUpgrades = false;
|
||||
|
||||
if(parameters.Vector().size() > 1)
|
||||
{
|
||||
bool success = true;
|
||||
includeUpgrades = parameters[1].TryBoolFromString(success);
|
||||
|
||||
if(!success)
|
||||
logMod->error("Second parameter of '%s' limiter should be Bool", limiterType);
|
||||
}
|
||||
creatureLimiter->includeUpgrades = includeUpgrades;
|
||||
return creatureLimiter;
|
||||
}
|
||||
else if(limiterType == "HAS_ANOTHER_BONUS_LIMITER")
|
||||
{
|
||||
auto bonusLimiter = std::make_shared<HasAnotherBonusLimiter>();
|
||||
|
||||
static const JsonNode nullNode;
|
||||
const JsonNode & jsonType = parameters[0];
|
||||
const JsonNode & jsonSubtype = parameters.Vector().size() > 2 ? parameters[1] : nullNode;
|
||||
const JsonNode & jsonSource = parameters.Vector().size() > 2 ? parameters[2] : parameters[1];
|
||||
|
||||
if (!jsonType.isNull())
|
||||
{
|
||||
LIBRARY->identifiers()->requestIdentifier("bonus", jsonType, [bonusLimiter, jsonSubtype](si32 bonusID)
|
||||
{
|
||||
bonusLimiter->type = static_cast<BonusType>(bonusID);
|
||||
if (jsonSubtype.isNull())
|
||||
loadBonusSubtype(bonusLimiter->subtype, bonusLimiter->type, jsonSubtype);
|
||||
});
|
||||
}
|
||||
|
||||
if(!jsonSource.isNull())
|
||||
{
|
||||
auto sourceIt = bonusSourceMap.find(jsonSource["type"].String());
|
||||
if(sourceIt != bonusSourceMap.end())
|
||||
{
|
||||
bonusLimiter->source = sourceIt->second;
|
||||
bonusLimiter->isSourceRelevant = true;
|
||||
if(!jsonSource["id"].isNull()) {
|
||||
loadBonusSourceInstance(bonusLimiter->sid, bonusLimiter->source, jsonSource["id"]);
|
||||
bonusLimiter->isSourceIDRelevant = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
logMod->warn("HAS_ANOTHER_BONUS_LIMITER: unknown bonus source type '%s'!", jsonSource["type"].String());
|
||||
}
|
||||
|
||||
return bonusLimiter;
|
||||
}
|
||||
else if(limiterType == "CREATURE_ALIGNMENT_LIMITER")
|
||||
{
|
||||
int alignment = vstd::find_pos(GameConstants::ALIGNMENT_NAMES, parameters[0].String());
|
||||
if(alignment == -1)
|
||||
logMod->error("Error: invalid alignment %s.", parameters[0].String());
|
||||
else
|
||||
return std::make_shared<CreatureAlignmentLimiter>(static_cast<EAlignment>(alignment));
|
||||
}
|
||||
else if(limiterType == "FACTION_LIMITER" || limiterType == "CREATURE_FACTION_LIMITER") //Second name is deprecated, 1.2 compat
|
||||
{
|
||||
auto factionLimiter = std::make_shared<FactionLimiter>();
|
||||
LIBRARY->identifiers()->requestIdentifier("faction", parameters[0], [=](si32 faction)
|
||||
{
|
||||
factionLimiter->faction = FactionID(faction);
|
||||
});
|
||||
return factionLimiter;
|
||||
}
|
||||
else if(limiterType == "CREATURE_LEVEL_LIMITER")
|
||||
{
|
||||
auto levelLimiter = std::make_shared<CreatureLevelLimiter>();
|
||||
if(!parameters.Vector().empty()) //If parameters is empty, level limiter works as CREATURES_ONLY limiter
|
||||
{
|
||||
levelLimiter->minLevel = parameters[0].Integer();
|
||||
if(parameters[1].isNumber())
|
||||
levelLimiter->maxLevel = parameters[1].Integer();
|
||||
}
|
||||
return levelLimiter;
|
||||
}
|
||||
else if(limiterType == "CREATURE_TERRAIN_LIMITER")
|
||||
{
|
||||
auto terrainLimiter = std::make_shared<CreatureTerrainLimiter>();
|
||||
if(!parameters.Vector().empty())
|
||||
{
|
||||
LIBRARY->identifiers()->requestIdentifier("terrain", parameters[0], [terrainLimiter](si32 terrain)
|
||||
{
|
||||
terrainLimiter->terrainType = terrain;
|
||||
});
|
||||
}
|
||||
return terrainLimiter;
|
||||
}
|
||||
else if(limiterType == "UNIT_ON_HEXES") {
|
||||
auto hexLimiter = std::make_shared<UnitOnHexLimiter>();
|
||||
if(!parameters.Vector().empty())
|
||||
{
|
||||
for (const auto & parameter : parameters.Vector()){
|
||||
if(parameter.isNumber())
|
||||
hexLimiter->applicableHexes.insert(BattleHex(parameter.Integer()));
|
||||
}
|
||||
}
|
||||
return hexLimiter;
|
||||
}
|
||||
else if(limiterType == "HAS_CHARGES_LIMITER")
|
||||
{
|
||||
auto hasChargesLimiter = std::make_shared<HasChargesLimiter>();
|
||||
if(!parameters.Vector().empty())
|
||||
{
|
||||
if(parameters.Vector().size() == 1 && parameters.Vector().front().isNumber())
|
||||
hasChargesLimiter->chargeCost = parameters.Vector().front().Integer();
|
||||
}
|
||||
return hasChargesLimiter;
|
||||
}
|
||||
if (limiterParsers.count(limiterType))
|
||||
return limiterParsers.at(limiterType)(limiter);
|
||||
else
|
||||
{
|
||||
logMod->error("Error: invalid customizable limiter type %s.", limiterType);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@@ -306,28 +306,6 @@ bool JsonNode::isCompact() const
|
||||
}
|
||||
}
|
||||
|
||||
bool JsonNode::TryBoolFromString(bool & success) const
|
||||
{
|
||||
success = true;
|
||||
if(getType() == JsonNode::JsonType::DATA_BOOL)
|
||||
return Bool();
|
||||
|
||||
success = getType() == JsonNode::JsonType::DATA_STRING;
|
||||
if(success)
|
||||
{
|
||||
auto boolParamStr = String();
|
||||
boost::algorithm::trim(boolParamStr);
|
||||
boost::algorithm::to_lower(boolParamStr);
|
||||
success = boolParamStr == "true";
|
||||
|
||||
if(success)
|
||||
return true;
|
||||
|
||||
success = boolParamStr == "false";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void JsonNode::clear()
|
||||
{
|
||||
setType(JsonType::DATA_NULL);
|
||||
|
@@ -109,9 +109,6 @@ public:
|
||||
/// removes all data from node and sets type to null
|
||||
void clear();
|
||||
|
||||
/// returns bool or bool equivalent of string value if 'success' is true, or false otherwise
|
||||
bool TryBoolFromString(bool & success) const;
|
||||
|
||||
/// non-const accessors, node will change type on type mismatch
|
||||
bool & Bool();
|
||||
double & Float();
|
||||
|
Reference in New Issue
Block a user