1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-06-23 00:28:08 +02:00

- console logger by default uses same format as previously (no extra data)

- a lot of changes in configs;
- - update to creature format - abilities are now json structure
- - multiple bugfixes revealed by validation
- made schemas a bit more strict
- creatures data can be replaced via mods
- it is possible to validate vcmi configs using schemas (disabled)
This commit is contained in:
Ivan Savenko
2013-04-11 19:24:14 +00:00
parent f10ba48c77
commit 0cf969d508
36 changed files with 2315 additions and 717 deletions

View File

@ -133,7 +133,7 @@ endif()
# For apple this files will be already inside vcmiclient bundle # For apple this files will be already inside vcmiclient bundle
if (NOT APPLE) if (NOT APPLE)
# copy whole directory but .svn control files and user-specific settings.json # copy whole directory but .svn control files and user-specific settings.json
install(DIRECTORY config DESTINATION ${DATA_DIR} PATTERN ".svn" EXCLUDE PATTERN "settings.json" EXCLUDE) install(DIRECTORY config DESTINATION ${DATA_DIR} PATTERN ".svn" EXCLUDE)
# copy vcmi mod along with all its content # copy vcmi mod along with all its content
install(DIRECTORY Mods/vcmi DESTINATION ${DATA_DIR}/Mods PATTERN ".svn" EXCLUDE) install(DIRECTORY Mods/vcmi DESTINATION ${DATA_DIR}/Mods PATTERN ".svn" EXCLUDE)
# copy only mod.json for WoG # copy only mod.json for WoG

View File

@ -139,8 +139,7 @@ bool CDefenceAnimation::init()
int attackerAnimType = owner->creAnims[attacker->ID]->getType(); int attackerAnimType = owner->creAnims[attacker->ID]->getType();
if( ( attackerAnimType == CCreatureAnim::ATTACK_UP || if( ( attackerAnimType == CCreatureAnim::ATTACK_UP ||
attackerAnimType == CCreatureAnim::ATTACK_FRONT || attackerAnimType == CCreatureAnim::ATTACK_FRONT ||
attackerAnimType == CCreatureAnim::ATTACK_DOWN ) && attackerAnimType == CCreatureAnim::ATTACK_DOWN ) )
owner->creAnims[attacker->ID]->getFrame() < attacker->getCreature()->animation.attackClimaxFrame )
return false; return false;
} }

View File

@ -2194,7 +2194,7 @@
"valueType" : "BASE_NUMBER" "valueType" : "BASE_NUMBER"
}, },
{ {
"additionalInfo" : 2, "addInfo" : 2,
"subtype" : "spell.lightningBolt", "subtype" : "spell.lightningBolt",
"type" : "ENCHANTER", "type" : "ENCHANTER",
"val" : 0, "val" : 0,
@ -2256,28 +2256,28 @@
"valueType" : "PERCENT_TO_BASE" "valueType" : "PERCENT_TO_BASE"
}, },
{ {
"additionalInfo" : 1, "addInfo" : 1,
"subtype" : "spell.age", "subtype" : "spell.age",
"type" : "SPELL_BEFORE_ATTACK", "type" : "SPELL_BEFORE_ATTACK",
"val" : 50, "val" : 50,
"valueType" : "BASE_NUMBER" "valueType" : "BASE_NUMBER"
}, },
{ {
"additionalInfo" : 1, "addInfo" : 1,
"subtype" : "spell.berserk", "subtype" : "spell.berserk",
"type" : "SPELL_AFTER_ATTACK", "type" : "SPELL_AFTER_ATTACK",
"val" : 50, "val" : 50,
"valueType" : "BASE_NUMBER" "valueType" : "BASE_NUMBER"
}, },
{ {
"additionalInfo" : 1, "addInfo" : 1,
"subtype" : "spell.poison", "subtype" : "spell.poison",
"type" : "SPELL_AFTER_ATTACK", "type" : "SPELL_AFTER_ATTACK",
"val" : 50, "val" : 50,
"valueType" : "BASE_NUMBER" "valueType" : "BASE_NUMBER"
}, },
{ {
"additionalInfo" : 1, "addInfo" : 1,
"subtype" : "spell.disruptingRay", "subtype" : "spell.disruptingRay",
"type" : "SPELL_AFTER_ATTACK", "type" : "SPELL_AFTER_ATTACK",
"val" : 50, "val" : 50,
@ -2363,7 +2363,12 @@
[ [
{ {
"level": 6, "level": 6,
"bonus": ["PRIMARY_SKILL", 1, "primSkill.attack", 0] "bonus":
{
"type" : "PRIMARY_SKILL",
"subtype" : "primSkill.attack",
"val" : 1
}
} }
] ]
} }
@ -2385,7 +2390,11 @@
[ [
{ {
"level": 1, "level": 1,
"bonus": ["STACK_HEALTH", 1, 0, 0] "bonus":
{
"type" : "STACK_HEALTH",
"val" : 1
}
} }
] ]
} }
@ -2408,7 +2417,11 @@
[ [
{ {
"level": 1, "level": 1,
"bonus": ["CREATURE_DAMAGE", 1, 0, 0] "bonus":
{
"type" : "CREATURE_DAMAGE",
"val" : 1
}
} }
] ]
} }
@ -2435,7 +2448,11 @@
[ [
{ {
"level": 10, "level": 10,
"bonus": ["CREATURE_ENCHANT_POWER", 1, 0, 0] "bonus":
{
"type" : "CREATURE_ENCHANT_POWER",
"val" : 1
}
} }
] ]
} }
@ -2457,7 +2474,11 @@
[ [
{ {
"level": 10, "level": 10,
"bonus": ["STACKS_SPEED", 1, 0, 0] "bonus":
{
"type" : "STACKS_SPEED",
"val" : 1
}
} }
] ]
} }
@ -2468,20 +2489,28 @@
"type" : ["COMMANDER"], "type" : ["COMMANDER"],
"growing": "growing":
{ {
"id": 152, //bow of seeking
"thresholdBonuses": "thresholdBonuses":
[ [
{ {
"level": 5, "level": 5,
"bonus": ["SHOOTER", 0, 0, 0] "bonus":
{
"type" : "SHOOTER"
}
}, },
{ {
"level": 25, "level": 25,
"bonus": ["NO_WALL_PENALTY", 0, 0, 0] "bonus":
{
"type" : "NO_WALL_PENALTY"
}
}, },
{ {
"level": 50, "level": 50,
"bonus": ["NO_DISTANCE_PENALTY", 0, 0, 0] "bonus":
{
"type" : "NO_DISTANCE_PENALTY"
}
} }
] ]
} }
@ -2505,12 +2534,16 @@
"type" : ["COMMANDER"], "type" : ["COMMANDER"],
"growing": "growing":
{ {
"id": 153, //hardened shield
"bonusesPerLevel": "bonusesPerLevel":
[ [
{ {
"level": 6, "level": 6,
"bonus": ["PRIMARY_SKILL", 1, "primSkill.defence", 0] "bonus":
{
"type" : "PRIMARY_SKILL",
"subtype" : "primSkill.defence",
"val" : 1
}
} }
] ]
} }

View File

@ -5,7 +5,13 @@
"level": 1, "level": 1,
"faction": "castle", "faction": "castle",
"upgrades": ["halberdier"], "upgrades": ["halberdier"],
"abilities": [ [ "CHARGE_IMMUNITY", 0, 0, 0 ] ], //pikeman immunity to Champion charge bonus "abilities":
{
"cavalryChargeImmunity" :
{
"type" : "CHARGE_IMMUNITY"
}
},
"graphics" : "graphics" :
{ {
"animation": "CPKMAN.DEF" "animation": "CPKMAN.DEF"
@ -24,7 +30,13 @@
"id": 1, "id": 1,
"level": 1, "level": 1,
"faction": "castle", "faction": "castle",
"abilities": [ [ "CHARGE_IMMUNITY", 0, 0, 0 ] ], //halberdier immunity to Champion charge bonus "abilities":
{
"cavalryChargeImmunity" :
{
"type" : "CHARGE_IMMUNITY"
}
},
"graphics" : "graphics" :
{ {
"animation": "CHALBD.DEF" "animation": "CHALBD.DEF"
@ -50,8 +62,7 @@
"animation": "CLCBOW.DEF", "animation": "CLCBOW.DEF",
"missile" : "missile" :
{ {
"projectile": "PLCBOWX.DEF", "projectile": "PLCBOWX.DEF"
"spinning": false
} }
}, },
"sound" : "sound" :
@ -69,20 +80,20 @@
"id": 3, "id": 3,
"level": 2, "level": 2,
"faction": "castle", "faction": "castle",
"abilities": [ "abilities": {
"extraAttack" :
{ {
"type": "ADDITIONAL_ATTACK", "type": "ADDITIONAL_ATTACK",
"val" : 1, "val" : 1,
"effectRange": "ONLY_DISTANCE_FIGHT" "effectRange": "ONLY_DISTANCE_FIGHT"
} }
], },
"graphics" : "graphics" :
{ {
"animation": "CHCBOW.DEF", "animation": "CHCBOW.DEF",
"missile" : "missile" :
{ {
"projectile": "PLCBOWX.DEF", "projectile": "PLCBOWX.DEF"
"spinning": false
} }
}, },
"sound" : "sound" :
@ -100,7 +111,14 @@
"id": 4, "id": 4,
"level": 3, "level": 3,
"faction": "castle", "faction": "castle",
"abilities": [ [ "ADDITIONAL_RETALIATION", 1, 0, 0 ] ], //griffins retaliate twice "abilities":
{
"extraRetaliation" :
{
"type" : "ADDITIONAL_RETALIATION",
"val" : 1
}
},
"upgrades": ["royalGriffin"], "upgrades": ["royalGriffin"],
"hasDoubleWeek": true, "hasDoubleWeek": true,
"graphics" : "graphics" :
@ -121,7 +139,13 @@
"id": 5, "id": 5,
"level": 3, "level": 3,
"faction": "castle", "faction": "castle",
"abilities": [ [ "UNLIMITED_RETALIATIONS", 0, 0, 0 ] ], //royal griffins retaliate always "abilities":
{
"unlimitedRetaliation" :
{
"type" : "UNLIMITED_RETALIATIONS"
}
},
"graphics" : "graphics" :
{ {
"animation": "CRGRIF.DEF" "animation": "CRGRIF.DEF"
@ -159,7 +183,14 @@
"id": 7, "id": 7,
"level": 4, "level": 4,
"faction": "castle", "faction": "castle",
"abilities": [ [ "ADDITIONAL_ATTACK", 1, 0, 0 ] ], "abilities":
{
"extraAttack" :
{
"type" : "ADDITIONAL_ATTACK",
"val" : 1
}
},
"graphics" : "graphics" :
{ {
"animation": "CCRUSD.DEF" "animation": "CCRUSD.DEF"
@ -184,8 +215,7 @@
"animation": "CMONKK.DEF", "animation": "CMONKK.DEF",
"missile" : "missile" :
{ {
"projectile": "CPRZEAX.DEF", "projectile": "CPRZEAX.DEF"
"spinning": false
} }
}, },
"sound" : "sound" :
@ -208,8 +238,7 @@
"animation": "CZEALT.DEF", "animation": "CZEALT.DEF",
"missile" : "missile" :
{ {
"projectile": "CPRZEAX.DEF", "projectile": "CPRZEAX.DEF"
"spinning": false
} }
}, },
"sound" : "sound" :
@ -265,10 +294,20 @@
"level": 7, "level": 7,
"faction": "castle", "faction": "castle",
"abilities": "abilities":
[ {
["HATE", 50, "creature.archDevil", 0], //angels hate archdevils "hateDevils" :
["HATE", 50, "creature.devil", 0] //angels hate devil {
], "type" : "HATE",
"subtype" : "creature.devil",
"val" : 50
},
"hateArchDevils" :
{
"type" : "HATE",
"subtype" : "creature.archDevil",
"val" : 50
}
},
"upgrades": ["archangel"], "upgrades": ["archangel"],
"graphics" : "graphics" :
{ {
@ -289,13 +328,36 @@
"level": 7, "level": 7,
"faction": "castle", "faction": "castle",
"abilities": "abilities":
[ {
["SPECIFIC_SPELL_POWER", 100, "spell.resurrection", 0], // 100 hp per Archangel "resurrection100hp" :
["SPELLCASTER", 0, "spell.resurrection", 0 ], //archangels cast resurrection {
["HATE", 50, "creature.archDevil", 0], //archangels hate archdevils "type" : "SPECIFIC_SPELL_POWER",
["HATE", 50, "creature.devil", 0] , //archangels hate devils "subtype" : "spell.resurrection",
["CASTS", 1, 0, 0] "val" : 100
], },
"resurrects" :
{
"type" : "SPELLCASTER",
"subtype" : "spell.resurrection"
},
"spellpoints" :
{
"type" : "CASTS",
"val" : 1
},
"hateDevils" :
{
"type" : "HATE",
"subtype" : "creature.devil",
"val" : 50
},
"hateArchDevils" :
{
"type" : "HATE",
"subtype" : "creature.archDevil",
"val" : 50
}
},
"graphics" : "graphics" :
{ {
"animation": "CRANGL.DEF" "animation": "CRANGL.DEF"

View File

@ -6,13 +6,33 @@
"extraNames": [ "airElementals" ], "extraNames": [ "airElementals" ],
"faction": "conflux", "faction": "conflux",
"abilities": "abilities":
[ {
["MIND_IMMUNITY", 0, 0, 0], //air elementals are immune to mind spells "nonLiving" :
["SPELL_IMMUNITY", 0, "spell.meteorShower", 0], //air elementals are immune to meteor shower {
["NON_LIVING", 0, 0, 0 ], //air elementals are non-living "type" : "NON_LIVING"
["MORE_DAMAGE_FROM_SPELL", 100, "spell.chainLightning", 0],//air elementals are vulnerable to chain lightning },
["MORE_DAMAGE_FROM_SPELL", 100, "spell.lightningBolt", 0] //air elementals are vulnerable to lightning bolt "immuneToMind" :
], {
"type" : "MIND_IMMUNITY"
},
"meteorShowerImmunity" :
{
"type" : "SPELL_IMMUNITY",
"subtype" : "spell.meteorShower"
},
"lightingVulnerablity" :
{
"type" : "MORE_DAMAGE_FROM_SPELL",
"subtype" : "spell.lightningBolt",
"val" : 100
},
"chainLightingVulnerablity" :
{
"type" : "MORE_DAMAGE_FROM_SPELL",
"subtype" : "spell.chainLightning",
"val" : 100
}
},
"upgrades": ["stormElemental"], "upgrades": ["stormElemental"],
"graphics" : "graphics" :
{ {
@ -33,13 +53,32 @@
"level": 5, "level": 5,
"faction": "conflux", "faction": "conflux",
"abilities": "abilities":
[ {
["MIND_IMMUNITY", 0, 0, 0], //earth elementals are immune to mind spells "nonLiving" :
["SPELL_IMMUNITY", 0, "spell.chainLightning", 0],//earth elementals are immune to chain lightning {
["SPELL_IMMUNITY", 0, "spell.lightningBolt", 0], //earth elementals are immune to lightning bolt "type" : "NON_LIVING"
["NON_LIVING", 0, 0, 0], },
[ "MORE_DAMAGE_FROM_SPELL", 100, "spell.meteorShower", 0 ] //earth elementals are vulnerable to meteor shower "immuneToMind" :
], {
"type" : "MIND_IMMUNITY"
},
"meteorShowerVulnerability" :
{
"type" : "MORE_DAMAGE_FROM_SPELL",
"subtype" : "spell.meteorShower",
"val" : 100
},
"lightingImmunity" :
{
"type" : "SPELL_IMMUNITY",
"subtype" : "spell.lightningBolt"
},
"chainLightingImmunity" :
{
"type" : "SPELL_IMMUNITY",
"subtype" : "spell.chainLightning"
}
},
"upgrades": ["magmaElemental"], "upgrades": ["magmaElemental"],
"graphics" : "graphics" :
{ {
@ -60,12 +99,32 @@
"level": 4, "level": 4,
"faction": "conflux", "faction": "conflux",
"abilities": "abilities":
[ {
["MIND_IMMUNITY", 0, 0, 0],//fire elementals are immune to mind spells "nonLiving" :
["NON_LIVING", 0, 0, 0 ], //fire elementals are non-living {
[ "MORE_DAMAGE_FROM_SPELL", 100, "spell.frostRing", 0 ], //fire elementals are vulnerable to frost ring "type" : "NON_LIVING"
[ "MORE_DAMAGE_FROM_SPELL", 100, "spell.iceBolt", 0 ], //fire elementals are vulnerable to ice bolt },
[ "FIRE_IMMUNITY", 0, 0, 0 ] ], //fire elementals are immune to fire spells "immuneToMind" :
{
"type" : "MIND_IMMUNITY"
},
"immuneToFire" :
{
"type" : "FIRE_IMMUNITY"
},
"frostRingVulnerablity" :
{
"type" : "MORE_DAMAGE_FROM_SPELL",
"subtype" : "spell.frostRing",
"val" : 100
},
"iceBoltVulnerablity" :
{
"type" : "MORE_DAMAGE_FROM_SPELL",
"subtype" : "spell.iceBolt",
"val" : 100
}
},
"upgrades": ["energyElemental"], "upgrades": ["energyElemental"],
"graphics" : "graphics" :
{ {
@ -86,17 +145,52 @@
"level": 3, "level": 3,
"extraNames": [ "waterElementals" ], "extraNames": [ "waterElementals" ],
"faction": "conflux", "faction": "conflux",
"abilities": [ "abilities":
["MIND_IMMUNITY", 0, 0, 0],//water elementals are immune to mind spells {
["SPELL_IMMUNITY", 0, "spell.frostRing", 0 ],//water elementals are immune to frost ring "nonLiving" :
["SPELL_IMMUNITY", 0, "spell.iceBolt", 0 ],//water elementals are immune to ice bolt {
["NON_LIVING", 0, 0, 0 ], //water elementals are non-living "type" : "NON_LIVING"
["MORE_DAMAGE_FROM_SPELL", 100, "spell.fireShield", 0 ], //water elementals are vulnerable to fire shield },
["MORE_DAMAGE_FROM_SPELL", 100, "spell.inferno", 0 ], //water elementals are vulnerable to inferno "immuneToMind" :
["MORE_DAMAGE_FROM_SPELL", 100, "spell.fireball", 0 ], //water elementals are vulnerable to fireball {
["MORE_DAMAGE_FROM_SPELL", 100, "spell.fireWall", 0 ], //water elementals are vulnerable to fire wall "type" : "MIND_IMMUNITY"
["DOUBLE_WIDE", 0, 0, 0 ] },
], "fireShieldVulnerablity" :
{
"type" : "MORE_DAMAGE_FROM_SPELL",
"subtype" : "spell.fireShield",
"val" : 100
},
"infernoVulnerablity" :
{
"type" : "MORE_DAMAGE_FROM_SPELL",
"subtype" : "spell.inferno",
"val" : 100
},
"fireballVulnerablity" :
{
"type" : "MORE_DAMAGE_FROM_SPELL",
"subtype" : "spell.fireball",
"val" : 100
},
"fireWallVulnerablity" :
{
"type" : "MORE_DAMAGE_FROM_SPELL",
"subtype" : "spell.fireWall",
"val" : 100
},
"iceBoltImmunity" :
{
"type" : "SPELL_IMMUNITY",
"subtype" : "spell.iceBolt"
},
"frostRingImmunity" :
{
"type" : "SPELL_IMMUNITY",
"subtype" : "spell.frostRing"
}
},
"doubleWide" : true,
"upgrades": ["iceElemental"], "upgrades": ["iceElemental"],
"graphics" : "graphics" :
{ {
@ -154,8 +248,14 @@
"id": 120, "id": 120,
"level": 6, "level": 6,
"faction": "conflux", "faction": "conflux",
"abilities": [ [ "NON_LIVING", 0, 0, 0 ] ], //magic elementals shouldn't get morale "abilities":
"ability_remove": [ "DOUBLE_WIDE" ], {
"nonLiving" :
{
"type" : "NON_LIVING"
}
},
"doubleWide" : false,
"upgrades": ["magicElemental"], "upgrades": ["magicElemental"],
"graphics" : "graphics" :
{ {
@ -175,9 +275,19 @@
"id": 121, "id": 121,
"level": 6, "level": 6,
"faction": "conflux", "faction": "conflux",
"abilities": [ [ "NON_LIVING", 0, 0, 0 ], //ice elementals shouldn't get morale "abilities":
[ "LEVEL_SPELL_IMMUNITY", 5, 0, 0 ] ], //magic elementals are immune to all spells {
"ability_remove": [ "DOUBLE_WIDE" ], "nonLiving" :
{
"type" : "NON_LIVING"
},
"magicImmunity" :
{
"type" : "LEVEL_SPELL_IMMUNITY",
"val" : 5
}
},
"doubleWide" : false,
"graphics" : "graphics" :
{ {
"animation": "CMAGEL.DEF" "animation": "CMAGEL.DEF"
@ -196,18 +306,36 @@
"id": 123, "id": 123,
"level": 3, "level": 3,
"faction": "conflux", "faction": "conflux",
"abilities": [ [ "NON_LIVING", 0, 0, 0 ], "abilities":
[ "DOUBLE_WIDE", 0, 0, 0 ], //ice elemental should be treated as double-wide {
[ "CREATURE_ENCHANT_POWER", 6, 0, 0 ], "nonLiving" :
[ "CASTS", 3, 0, 0 ], {
[ "SPELLCASTER", 2, "spell.protectWater", 0 ]], "type" : "NON_LIVING"
},
"spellPower" :
{
"type" : "CREATURE_ENCHANT_POWER",
"val" : 6
},
"spellPoints" :
{
"type" : "CASTS",
"val" : 3
},
"spellcaster":
{
"type" : "SPELLCASTER",
"subtype" : "spell.protectWater",
"val" : 2
}
},
"doubleWide" : true,
"graphics" : "graphics" :
{ {
"animation": "CICEE.DEF", "animation": "CICEE.DEF",
"missile" : "missile" :
{ {
"projectile": "PICEE.DEF", "projectile": "PICEE.DEF"
"spinning": false
} }
}, },
"sound" : "sound" :
@ -225,10 +353,29 @@
"id": 125, "id": 125,
"level": 5, "level": 5,
"faction": "conflux", "faction": "conflux",
"abilities": [ [ "NON_LIVING", 0, 0, 0 ], //magma elementals shouldn't get morale "abilities":
[ "CREATURE_ENCHANT_POWER", 6, 0, 0 ], {
[ "CASTS", 3, 0, 0 ], "nonLiving" :
[ "SPELLCASTER", 2, "spell.protectEarth", 0 ]], {
"type" : "NON_LIVING"
},
"spellPower" :
{
"type" : "CREATURE_ENCHANT_POWER",
"val" : 6
},
"spellPoints" :
{
"type" : "CASTS",
"val" : 3
},
"spellcaster":
{
"type" : "SPELLCASTER",
"subtype" : "spell.protectEarth",
"val" : 2
}
},
"graphics" : "graphics" :
{ {
"animation": "CSTONE.DEF" "animation": "CSTONE.DEF"
@ -247,17 +394,35 @@
"id": 127, "id": 127,
"level": 2, "level": 2,
"faction": "conflux", "faction": "conflux",
"abilities": [ [ "NON_LIVING", 0, 0, 0 ], //storm elementals shouldn't get morale "abilities":
[ "CREATURE_ENCHANT_POWER", 6, 0, 0 ], {
[ "CASTS", 3, 0, 0 ], "nonLiving" :
[ "SPELLCASTER", 2, "spell.protectAir", 0 ]], {
"type" : "NON_LIVING"
},
"spellPower" :
{
"type" : "CREATURE_ENCHANT_POWER",
"val" : 6
},
"spellPoints" :
{
"type" : "CASTS",
"val" : 3
},
"spellcaster":
{
"type" : "SPELLCASTER",
"subtype" : "spell.protectAir",
"val" : 2
}
},
"graphics" : "graphics" :
{ {
"animation": "CSTORM.DEF", "animation": "CSTORM.DEF",
"missile" : "missile" :
{ {
"projectile": "CPRGTIX.DEF", "projectile": "CPRGTIX.DEF"
"spinning": false
} }
}, },
"sound" : "sound" :
@ -275,10 +440,29 @@
"id": 129, "id": 129,
"level": 4, "level": 4,
"faction": "conflux", "faction": "conflux",
"abilities": [ [ "NON_LIVING", 0, 0, 0 ] , //energy elementals shouldn't get morale "abilities":
[ "CREATURE_ENCHANT_POWER", 6, 0, 0 ], {
[ "CASTS", 3, 0, 0 ], "nonLiving" :
[ "SPELLCASTER", 2, "spell.protectFire", 0 ]], {
"type" : "NON_LIVING"
},
"spellPower" :
{
"type" : "CREATURE_ENCHANT_POWER",
"val" : 6
},
"spellPoints" :
{
"type" : "CASTS",
"val" : 3
},
"spellcaster":
{
"type" : "SPELLCASTER",
"subtype" : "spell.protectFire",
"val" : 2
}
},
"graphics" : "graphics" :
{ {
"animation": "CNRG.DEF" "animation": "CNRG.DEF"
@ -298,7 +482,13 @@
"level": 7, "level": 7,
"faction": "conflux", "faction": "conflux",
"upgrades": ["phoenix"], "upgrades": ["phoenix"],
"abilities": [ ["FIRE_IMMUNITY", 0, 0, 0] ], "abilities":
{
"immuneToFire" :
{
"type" : "FIRE_IMMUNITY"
},
},
"graphics" : "graphics" :
{ {
"animation": "CFBIRD.DEF" "animation": "CFBIRD.DEF"
@ -317,9 +507,23 @@
"id": 131, "id": 131,
"level": 7, "level": 7,
"faction": "conflux", "faction": "conflux",
"abilities": [ [ "CASTS", 1, 0, 0 ], //Phoenix rebirths once "abilities":
["FIRE_IMMUNITY", 0, 0, 0], {
[ "REBIRTH", 20, 0, 0 ] ], //20% of stack is resurrected "rebirthOnce" :
{
"type" : "CASTS",
"val" : 1
},
"immuneToFire" :
{
"type" : "FIRE_IMMUNITY"
},
"rebirth" :
{
"type" : "REBIRTH",
"val" : 20
}
},
"graphics" : "graphics" :
{ {
"animation": "CPHX.DEF" "animation": "CPHX.DEF"

View File

@ -4,7 +4,14 @@
"id": 70, "id": 70,
"level": 1, "level": 1,
"faction": "dungeon", "faction": "dungeon",
"abilities": [ [ "SPELL_IMMUNITY", 0, "spell.blind", 0 ] ], //troglodytes are immune to blind "abilities":
{
"blindImmunity" :
{
"type" : "SPELL_IMMUNITY",
"subtype" : "spell.blind"
}
},
"upgrades": ["infernalTroglodyte"], "upgrades": ["infernalTroglodyte"],
"hasDoubleWeek": true, "hasDoubleWeek": true,
"graphics" : "graphics" :
@ -25,7 +32,14 @@
"id": 71, "id": 71,
"level": 1, "level": 1,
"faction": "dungeon", "faction": "dungeon",
"abilities": [ [ "SPELL_IMMUNITY", 0, "spell.blind", 0 ] ], //infernal troglodytes are immune to blind "abilities":
{
"blindImmunity" :
{
"type" : "SPELL_IMMUNITY",
"subtype" : "spell.blind"
}
},
"graphics" : "graphics" :
{ {
"animation": "CITROG.DEF" "animation": "CITROG.DEF"
@ -44,7 +58,13 @@
"id": 72, "id": 72,
"level": 2, "level": 2,
"faction": "dungeon", "faction": "dungeon",
"abilities": [ [ "RETURN_AFTER_STRIKE", 0, 0, 0 ] ], //Harpies return after attack "abilities":
{
"strikeAndReturn" :
{
"type" : "RETURN_AFTER_STRIKE"
}
},
"upgrades": ["harpyHag"], "upgrades": ["harpyHag"],
"hasDoubleWeek": true, "hasDoubleWeek": true,
"graphics" : "graphics" :
@ -66,8 +86,17 @@
"id": 73, "id": 73,
"level": 2, "level": 2,
"faction": "dungeon", "faction": "dungeon",
"abilities": [ [ "RETURN_AFTER_STRIKE", 0, 0, 0 ], //Harpy Hags return after attack "abilities":
[ "BLOCKS_RETALIATION", 0, 0, 0 ] ], //Harpy Hags {
"strikeAndReturn" :
{
"type" : "RETURN_AFTER_STRIKE"
},
"noRetaliation" :
{
"type" : "BLOCKS_RETALIATION"
}
},
"graphics" : "graphics" :
{ {
"animation": "CHARPH.DEF" "animation": "CHARPH.DEF"
@ -93,8 +122,7 @@
"animation": "CBEHOL.DEF", "animation": "CBEHOL.DEF",
"missile" : "missile" :
{ {
"projectile": "SMBALX.DEF", "projectile": "SMBALX.DEF"
"spinning": false
} }
}, },
"sound" : "sound" :
@ -104,8 +132,7 @@
"killed": "BHDRKILL.wav", "killed": "BHDRKILL.wav",
"move": "BHDRMOVE.wav", "move": "BHDRMOVE.wav",
"shoot": "BHDRSHOT.wav", "shoot": "BHDRSHOT.wav",
"wince": "BHDRWNCE.wav", "wince": "BHDRWNCE.wav"
"ext1": "BHDRDETH.wav"
} }
}, },
"evilEye" : "evilEye" :
@ -118,8 +145,7 @@
"animation": "CEVEYE.DEF", "animation": "CEVEYE.DEF",
"missile" : "missile" :
{ {
"projectile": "SMBALX.DEF", "projectile": "SMBALX.DEF"
"spinning": false
} }
}, },
"sound" : "sound" :
@ -129,8 +155,7 @@
"killed": "EVLIKILL.wav", "killed": "EVLIKILL.wav",
"move": "EVLIMOVE.wav", "move": "EVLIMOVE.wav",
"shoot": "EVLISHOT.wav", "shoot": "EVLISHOT.wav",
"wince": "EVLIWNCE.wav", "wince": "EVLIWNCE.wav"
"ext1": "EVLIDETH.wav"
} }
}, },
"medusa" : "medusa" :
@ -138,15 +163,23 @@
"id": 76, "id": 76,
"level": 4, "level": 4,
"faction": "dungeon", "faction": "dungeon",
"abilities": [ [ "SPELL_AFTER_ATTACK", 20, "spell.stoneGaze", 2000 ] ], "abilities":
{
"petrification" :
{
"type" : "SPELL_AFTER_ATTACK",
"subtype" : "spell.stoneGaze",
"val" : 20,
"addInfo" : 2000 // FIXME: replace with range field?
}
},
"upgrades": ["medusaQueen"], "upgrades": ["medusaQueen"],
"graphics" : "graphics" :
{ {
"animation": "CMEDUS.DEF", "animation": "CMEDUS.DEF",
"missile" : "missile" :
{ {
"projectile": "PMEDUSX.DEF", "projectile": "PMEDUSX.DEF"
"spinning": false
} }
}, },
"sound" : "sound" :
@ -164,14 +197,22 @@
"id": 77, "id": 77,
"level": 4, "level": 4,
"faction": "dungeon", "faction": "dungeon",
"abilities": [ [ "SPELL_AFTER_ATTACK", 20, "spell.stoneGaze", 2000 ] ], "abilities":
{
"petrification" :
{
"type" : "SPELL_AFTER_ATTACK",
"subtype" : "spell.stoneGaze",
"val" : 20,
"addInfo" : 2000 // FIXME: replace with range?
}
},
"graphics" : "graphics" :
{ {
"animation": "CMEDUQ.DEF", "animation": "CMEDUQ.DEF",
"missile" : "missile" :
{ {
"projectile": "PMEDUSX.DEF", "projectile": "PMEDUSX.DEF"
"spinning": false
} }
}, },
"sound" : "sound" :
@ -189,7 +230,13 @@
"id": 78, "id": 78,
"level": 5, "level": 5,
"faction": "dungeon", "faction": "dungeon",
"abilities": [ [ "SELF_MORALE", 0, 0, 0 ] ], "abilities":
{
"fearless" :
{
"type" : "SELF_MORALE"
}
},
"upgrades": ["minotaurKing"], "upgrades": ["minotaurKing"],
"graphics" : "graphics" :
{ {
@ -209,7 +256,13 @@
"id": 79, "id": 79,
"level": 5, "level": 5,
"faction": "dungeon", "faction": "dungeon",
"abilities": [ [ "SELF_MORALE", 0, 0, 0 ] ], "abilities":
{
"fearless" :
{
"type" : "SELF_MORALE"
}
},
"graphics" : "graphics" :
{ {
"animation": "CMINOK.DEF" "animation": "CMINOK.DEF"
@ -249,7 +302,15 @@
"id": 81, "id": 81,
"level": 6, "level": 6,
"faction": "dungeon", "faction": "dungeon",
"abilities": [ [ "SPELL_AFTER_ATTACK", 20, "spell.paralyze", 0 ] ], "abilities":
{
"paralize" :
{
"type" : "SPELL_AFTER_ATTACK",
"subtype" : "spell.paralyze",
"val" : 20
}
},
"graphics" : "graphics" :
{ {
"animation": "CCMCOR.DEF" "animation": "CCMCOR.DEF"
@ -269,9 +330,22 @@
"id": 82, "id": 82,
"level": 7, "level": 7,
"faction": "dungeon", "faction": "dungeon",
"abilities": [ [ "DRAGON_NATURE", 0, 0, 0 ], //red dragon is a dragon "abilities":
[ "TWO_HEX_ATTACK_BREATH", 0, 0, 0 ], //Red Dragon has breath attack {
[ "LEVEL_SPELL_IMMUNITY", 3, 0, 0 ] ], //red dragon's spell immunity "dragon" :
{
"type" : "DRAGON_NATURE"
},
"fireBreath" :
{
"type" : "TWO_HEX_ATTACK_BREATH"
},
"spellImmunity" :
{
"type" : "LEVEL_SPELL_IMMUNITY",
"val" : 3
}
},
"upgrades": ["blackDragon"], "upgrades": ["blackDragon"],
"graphics" : "graphics" :
{ {
@ -291,11 +365,34 @@
"id": 83, "id": 83,
"level": 7, "level": 7,
"faction": "dungeon", "faction": "dungeon",
"abilities": [ [ "DRAGON_NATURE", 0, 0, 0 ], //black dragon is a dragon "abilities":
[ "TWO_HEX_ATTACK_BREATH", 0, 0, 0 ], //Black Dragon has breath attack {
[ "HATE", 50, "creature.titan", 0 ], //Hate Titans "dragon" :
[ "HATE", 50, "creature.giant", 0 ], //Hate Giants {
[ "LEVEL_SPELL_IMMUNITY", 5, 0, 0 ] ], //black dragon's spell immunity "type" : "DRAGON_NATURE"
},
"fireBreath" :
{
"type" : "TWO_HEX_ATTACK_BREATH"
},
"spellImmunity" :
{
"type" : "LEVEL_SPELL_IMMUNITY",
"val" : 5
},
"hateGiants" :
{
"type" : "HATE",
"subtype" : "creature.giant",
"val" : 50
},
"hateTitans" :
{
"type" : "HATE",
"subtype" : "creature.titan",
"val" : 50
}
},
"graphics" : "graphics" :
{ {
"animation": "CBDRGN.DEF" "animation": "CBDRGN.DEF"

View File

@ -49,8 +49,7 @@
"animation": "CPLIZA.DEF", "animation": "CPLIZA.DEF",
"missile" : "missile" :
{ {
"projectile": "PPLIZAX.DEF", "projectile": "PPLIZAX.DEF"
"spinning": false
} }
}, },
"sound" : "sound" :
@ -73,8 +72,7 @@
"animation": "CALIZA.DEF", "animation": "CALIZA.DEF",
"missile" : "missile" :
{ {
"projectile": "PPLIZAX.DEF", "projectile": "PPLIZAX.DEF"
"spinning": false
} }
}, },
"sound" : "sound" :
@ -111,7 +109,14 @@
"id": 103, "id": 103,
"level": 5, "level": 5,
"faction": "fortress", "faction": "fortress",
"abilities": [ [ "DEATH_STARE", 10, 0, 0 ] ], //mighty gorgons "abilities":
{
"deathStare" :
{
"type" : "DEATH_STARE",
"val" : 10
}
},
"graphics" : "graphics" :
{ {
"animation": "CBGOG.DEF" "animation": "CBGOG.DEF"
@ -131,7 +136,15 @@
"level": 3, "level": 3,
"extraNames": [ "dragonFly" ], "extraNames": [ "dragonFly" ],
"faction": "fortress", "faction": "fortress",
"abilities": [ [ "SPELL_AFTER_ATTACK", 100, "spell.dispelHelpful", 0 ] ], "abilities":
{
"dispellHelpful" :
{
"type" : "SPELL_AFTER_ATTACK",
"subtype" : "spell.dispelHelpful",
"val" : 100
}
},
"upgrades": ["fireDragonFly"], "upgrades": ["fireDragonFly"],
"hasDoubleWeek": true, "hasDoubleWeek": true,
"graphics" : "graphics" :
@ -152,8 +165,21 @@
"id": 105, "id": 105,
"level": 3, "level": 3,
"faction": "fortress", "faction": "fortress",
"abilities": [ [ "SPELL_AFTER_ATTACK", 100, "spell.dispelHelpful", 0 ], "abilities":
[ "SPELL_AFTER_ATTACK", 100, "spell.weakness", 0 ] ], {
"dispellHelpful" :
{
"type" : "SPELL_AFTER_ATTACK",
"subtype" : "spell.dispelHelpful",
"val" : 100
},
"castWeakness" :
{
"type" : "SPELL_AFTER_ATTACK",
"subtype" : "spell.weakness",
"val" : 100
}
},
"graphics" : "graphics" :
{ {
"animation": "CDRFIR.DEF" "animation": "CDRFIR.DEF"
@ -173,7 +199,15 @@
"id": 106, "id": 106,
"level": 4, "level": 4,
"faction": "fortress", "faction": "fortress",
"abilities": [ [ "SPELL_AFTER_ATTACK", 20, "spell.stoneGaze", 0 ] ], "abilities":
{
"petrify" :
{
"type" : "SPELL_AFTER_ATTACK",
"subtype" : "spell.stoneGaze",
"val" : 20
}
},
"upgrades": ["greaterBasilisk"], "upgrades": ["greaterBasilisk"],
"graphics" : "graphics" :
{ {
@ -193,7 +227,15 @@
"id": 107, "id": 107,
"level": 4, "level": 4,
"faction": "fortress", "faction": "fortress",
"abilities": [ [ "SPELL_AFTER_ATTACK", 20, "spell.stoneGaze", 0 ] ], "abilities":
{
"petrify" :
{
"type" : "SPELL_AFTER_ATTACK",
"subtype" : "spell.stoneGaze",
"val" : 20
}
},
"graphics" : "graphics" :
{ {
"animation": "CGBASI.DEF" "animation": "CGBASI.DEF"
@ -231,7 +273,15 @@
"id": 109, "id": 109,
"level": 6, "level": 6,
"faction": "fortress", "faction": "fortress",
"abilities": [ [ "SPELL_AFTER_ATTACK", 50, "spell.poison", 0 ] ], //50% probability (from FizMiG) "abilities":
{
"petrify" :
{
"type" : "SPELL_AFTER_ATTACK",
"subtype" : "spell.stoneGaze",
"val" : 50
}
},
"graphics" : "graphics" :
{ {
"animation": "CWYVMN.DEF" "animation": "CWYVMN.DEF"
@ -250,8 +300,17 @@
"id": 110, "id": 110,
"level": 7, "level": 7,
"faction": "fortress", "faction": "fortress",
"abilities": [ [ "BLOCKS_RETALIATION", 0, 0, 0 ], "abilities":
[ "ATTACKS_ALL_ADJACENT", 0, 0, 0 ] ], {
"noRetaliate" :
{
"type" : "BLOCKS_RETALIATION"
},
"attackAll" :
{
"type" : "ATTACKS_ALL_ADJACENT"
}
},
"upgrades": ["chaosHydra"], "upgrades": ["chaosHydra"],
"graphics" : "graphics" :
{ {
@ -271,8 +330,17 @@
"id": 111, "id": 111,
"level": 7, "level": 7,
"faction": "fortress", "faction": "fortress",
"abilities": [ [ "BLOCKS_RETALIATION", 0, 0, 0 ], "abilities":
[ "ATTACKS_ALL_ADJACENT", 0, 0, 0 ] ], {
"noRetaliate" :
{
"type" : "BLOCKS_RETALIATION"
},
"attackAll" :
{
"type" : "ATTACKS_ALL_ADJACENT"
}
},
"graphics" : "graphics" :
{ {
"animation": "CCHYDR.DEF" "animation": "CCHYDR.DEF"

View File

@ -23,7 +23,14 @@
"id": 43, "id": 43,
"level": 1, "level": 1,
"faction": "inferno", "faction": "inferno",
"abilities": [ [ "MANA_CHANNELING", 20, 0, 0 ] ], //familiars "abilities":
{
"manaChannel" :
{
"type" : "MANA_CHANNELING",
"val" : 20
}
},
"graphics" : "graphics" :
{ {
"animation": "CFAMIL.DEF" "animation": "CFAMIL.DEF"
@ -49,8 +56,7 @@
"animation": "CGOG.DEF", "animation": "CGOG.DEF",
"missile" : "missile" :
{ {
"projectile": "CPRGOGX.DEF", "projectile": "CPRGOGX.DEF"
"spinning": false
} }
}, },
"sound" : "sound" :
@ -60,8 +66,7 @@
"killed": "GOGGKILL.wav", "killed": "GOGGKILL.wav",
"move": "GOGGMOVE.wav", "move": "GOGGMOVE.wav",
"shoot": "GOGGSHOT.wav", "shoot": "GOGGSHOT.wav",
"wince": "GOGGWNCE.wav", "wince": "GOGGWNCE.wav"
"ext1": "GOGFLAME.wav"
} }
}, },
"magog" : "magog" :
@ -69,14 +74,20 @@
"id": 45, "id": 45,
"level": 2, "level": 2,
"faction": "inferno", "faction": "inferno",
"abilities": [ [ "SPELL_LIKE_ATTACK", 0, 21, 0 ] ], //magogs fire with fireballs "abilities":
{
"fireball" :
{
"type" : "SPELL_LIKE_ATTACK",
"subtype" : "spell.fireball"
}
},
"graphics" : "graphics" :
{ {
"animation": "CMAGOG.DEF", "animation": "CMAGOG.DEF",
"missile" : "missile" :
{ {
"projectile": "CPRGOGX.DEF", "projectile": "CPRGOGX.DEF"
"spinning": false
} }
}, },
"sound" : "sound" :
@ -86,8 +97,7 @@
"killed": "MGOGKILL.wav", "killed": "MGOGKILL.wav",
"move": "MGOGMOVE.wav", "move": "MGOGMOVE.wav",
"shoot": "MGOGSHOT.wav", "shoot": "MGOGSHOT.wav",
"wince": "MGOGWNCE.wav", "wince": "MGOGWNCE.wav"
"ext1": "GOGFLAME.wav"
} }
}, },
"hellHound" : "hellHound" :
@ -96,7 +106,10 @@
"level": 3, "level": 3,
"faction": "inferno", "faction": "inferno",
"upgrades": ["cerberus"], "upgrades": ["cerberus"],
"ability_remove": [ "FLYING" ], //hell hound doesn't fly "abilities":
{
"FLYING_ARMY" : null //hell hound doesn't fly
},
"graphics" : "graphics" :
{ {
"animation": "CHHOUN.DEF" "animation": "CHHOUN.DEF"
@ -115,9 +128,18 @@
"id": 47, "id": 47,
"level": 3, "level": 3,
"faction": "inferno", "faction": "inferno",
"abilities": [ [ "THREE_HEADED_ATTACK", 0, 0, 0 ], "abilities":
[ "BLOCKS_RETALIATION", 0, 0, 0 ] ], {
"ability_remove": [ "FLYING" ], //cerberus doesn't fly "threeHeads" :
{
"type" : "THREE_HEADED_ATTACK"
},
"noRetaliation" :
{
"type" : "BLOCKS_RETALIATION"
},
"FLYING_ARMY" : null //cerberus doesn't fly
},
"graphics" : "graphics" :
{ {
"animation": "CCERBU.DEF" "animation": "CCERBU.DEF"
@ -192,8 +214,20 @@
"id": 51, "id": 51,
"level": 5, "level": 5,
"faction": "inferno", "faction": "inferno",
"abilities": [ [ "DAEMON_SUMMONING", 50, 48, 0 ], "abilities":
[ "CASTS", 1, 0, 0] ], //pit lord {
"demonSummon" :
{
"type" : "DAEMON_SUMMONING",
"subtype" : "creature.demon",
"val" : 50
},
"castsAmount" :
{
"type" : "CASTS",
"val" : 1
}
},
"graphics" : "graphics" :
{ {
"animation": "CPFOE.DEF" "animation": "CPFOE.DEF"
@ -212,10 +246,29 @@
"id": 52, "id": 52,
"level": 6, "level": 6,
"faction": "inferno", "faction": "inferno",
"abilities": [ [ "HATE", 50, 37, 0 ], "abilities":
[ "HATE", 50, 36, 0 ], {
[ "FLYING", 0, 0, 0 ], //efreeti hate master genies "hateGenies" :
[ "FIRE_IMMUNITY", 0, 0, 0 ] ], //efreeti hate genies {
"type" : "HATE",
"subtype" : "creature.genie",
"val" : 50
},
"hateMasterGenies" :
{
"type" : "HATE",
"subtype" : "creature.masterGenie",
"val" : 50
},
"canFly" :
{
"type" : "FLYING"
},
"immuneToFire" :
{
"type" : "FIRE_IMMUNITY"
}
},
"upgrades": ["efreetSultan"], "upgrades": ["efreetSultan"],
"graphics" : "graphics" :
{ {
@ -235,11 +288,34 @@
"id": 53, "id": 53,
"level": 6, "level": 6,
"faction": "inferno", "faction": "inferno",
"abilities": [ [ "HATE", 50, 37, 0 ], "abilities":
[ "HATE", 50, 36, 0 ], {
[ "FLYING", 0, 0, 0 ], //efreet sultans hate master genies "hateGenies" :
[ "FIRE_SHIELD", 0, 36, 0 ], //efreet sultans hate genies {
[ "FIRE_IMMUNITY", 0, 0, 0 ] ], //efreet sultan //Efreet Sultan "type" : "HATE",
"subtype" : "creature.genie",
"val" : 50
},
"hateMasterGenies" :
{
"type" : "HATE",
"subtype" : "creature.masterGenie",
"val" : 50
},
"canFly" :
{
"type" : "FLYING"
},
"immuneToFire" :
{
"type" : "FIRE_IMMUNITY"
},
"fireShield" :
{
"type" : "FIRE_SHIELD",
"subtype" : 36 //FIXME: what is this magic number for?
}
},
"graphics" : "graphics" :
{ {
"animation": "CEFRES.DEF" "animation": "CEFRES.DEF"
@ -259,12 +335,36 @@
"id": 54, "id": 54,
"level": 7, "level": 7,
"faction": "inferno", "faction": "inferno",
"ability_remove": [ "FLYING" ], //use teleport instead "abilities":
"abilities": [ [ "HATE", 50, 13, 0 ], {
[ "FLYING", 0, 1, 0], //teleport "hateAngels" :
[ "HATE", 50, 12, 0 ], {
[ "ENEMY_LUCK_DECREASING", 1, 0, 0 ], //devils //devils hate archangles "type" : "HATE",
[ "BLOCKS_RETALIATION", 0, 0, 0 ] ], //devils //devils hate angels "subtype" : "creature.angel",
"val" : 50
},
"hateArchAngels" :
{
"type" : "HATE",
"subtype" : "creature.angel",
"val" : 50
},
"FLYING_ARMY" :
{
// type loaded from crtraits
"subtype" : 1 // teleports
},
"descreaseLuck" :
{
"type" : "LUCK",
"effectRange" : "ONLY_ENEMY_ARMY",
"val" : -1
},
"blockRetaliation" :
{
"type" : "BLOCKS_RETALIATION"
}
},
"upgrades": ["archDevil"], "upgrades": ["archDevil"],
"graphics" : "graphics" :
{ {
@ -277,8 +377,8 @@
"killed": "DEVLKILL.wav", "killed": "DEVLKILL.wav",
"move": "DEVLMOVE.wav", "move": "DEVLMOVE.wav",
"wince": "DEVLWNCE.wav", "wince": "DEVLWNCE.wav",
"ext1": "DEVLEXT1.wav", "startMoving": "DEVLEXT1.wav",
"ext2": "DEVLEXT2.wav" "endMoving": "DEVLEXT2.wav"
} }
}, },
"archDevil" : "archDevil" :
@ -286,14 +386,39 @@
"id": 55, "id": 55,
"level": 7, "level": 7,
"faction": "inferno", "faction": "inferno",
"ability_remove": [ "FLYING" ], //use teleport instead "abilities" :
"abilities": [ [ "HATE", 50, 13, 0 ], {
[ "HATE", 50, 12, 0 ], "hateAngels" :
[ "FLYING", 0, 1, 0], {
[ "ENEMY_LUCK_DECREASING", 1, 0, 0 ], //archdevils //archdevils hate archangles "type" : "HATE",
[ "BLOCKS_RETALIATION", 0, 0, 0 ] ], //archdevils //archdevils hate angels "subtype" : "creature.angel",
"val" : 50
},
"hateArchAngels" :
{
"type" : "HATE",
"subtype" : "creature.angel",
"val" : 50
},
"FLYING_ARMY" :
{
// type loaded from crtraits
"subtype" : 1 // teleports
},
"descreaseLuck" :
{
"type" : "LUCK",
"effectRange" : "ONLY_ENEMY_ARMY",
"val" : -1
},
"blockRetaliation" :
{
"type" : "BLOCKS_RETALIATION"
}
},
"graphics" : "graphics" :
{ {
"missile" : null,
"animation": "CADEVL.DEF" "animation": "CADEVL.DEF"
}, },
"sound" : "sound" :
@ -304,7 +429,7 @@
"move": "ADVLMOVE.wav", "move": "ADVLMOVE.wav",
"wince": "ADVLWNCE.wav", "wince": "ADVLWNCE.wav",
"startMoving": "ADVLEXT1.wav", "startMoving": "ADVLEXT1.wav",
"stopMoving": "ADVLEXT2.wav" "endMoving": "ADVLEXT2.wav"
} }
} }
} }

View File

@ -79,7 +79,14 @@
"id": 60, "id": 60,
"level": 3, "level": 3,
"faction": "necropolis", "faction": "necropolis",
"abilities": [ [ "FULL_HP_REGENERATION", 0, 1, 0 ] ], "abilities":
{
"regenerate" :
{
"type" : "FULL_HP_REGENERATION",
"subtype" : 1
}
},
"upgrades": ["wraith"], "upgrades": ["wraith"],
"hasDoubleWeek": true, "hasDoubleWeek": true,
"graphics" : "graphics" :
@ -100,8 +107,19 @@
"id": 61, "id": 61,
"level": 3, "level": 3,
"faction": "necropolis", "faction": "necropolis",
"abilities": [ [ "FULL_HP_REGENERATION", 0, 1, 0 ], "abilities":
[ "MANA_DRAIN", 2, 0, 0 ] ], {
"regenerate" :
{
"type" : "FULL_HP_REGENERATION",
"subtype" : 1
},
"drainsMana" :
{
"type" : "MANA_DRAIN",
"val" : 2
}
},
"graphics" : "graphics" :
{ {
"animation": "CWRAIT.DEF" "animation": "CWRAIT.DEF"
@ -120,7 +138,14 @@
"id": 62, "id": 62,
"level": 4, "level": 4,
"faction": "necropolis", "faction": "necropolis",
"abilities": [ [ "BLOCKS_RETALIATION", 0, 0, 0 ] ], "abilities":
{
"noRetalitation" :
{
"type" : "BLOCKS_RETALIATION",
"subtype" : 1
}
},
"upgrades": ["vampireLord"], "upgrades": ["vampireLord"],
"graphics" : "graphics" :
{ {
@ -134,7 +159,7 @@
"move": "VAMPMOVE.wav", "move": "VAMPMOVE.wav",
"wince": "VAMPWNCE.wav", "wince": "VAMPWNCE.wav",
"startMoving": "VAMPEXT1.wav", "startMoving": "VAMPEXT1.wav",
"stopMoving": "VAMPEXT2.wav" "endMoving": "VAMPEXT2.wav"
} }
}, },
"vampireLord" : "vampireLord" :
@ -142,8 +167,19 @@
"id": 63, "id": 63,
"level": 4, "level": 4,
"faction": "necropolis", "faction": "necropolis",
"abilities": [ [ "LIFE_DRAIN", 100, 0, 0 ], //drain 100% of damage dealt "abilities":
[ "BLOCKS_RETALIATION", 0, 0, 0 ] ], {
"noRetalitation" :
{
"type" : "BLOCKS_RETALIATION",
"subtype" : 1
},
"drainsLife" :
{
"type" : "LIFE_DRAIN",
"val" : 100
}
},
"graphics" : "graphics" :
{ {
"animation": "CNOSFE.DEF" "animation": "CNOSFE.DEF"
@ -156,8 +192,8 @@
"move": "NOSFMOVE.wav", "move": "NOSFMOVE.wav",
"shoot": "NOSFSHOT.wav", "shoot": "NOSFSHOT.wav",
"wince": "NOSFWNCE.wav", "wince": "NOSFWNCE.wav",
"ext1": "NOSFEXT1.wav", "startMoving": "NOSFEXT1.wav",
"ext2": "NOSFEXT2.wav" "endMoving": "NOSFEXT2.wav"
} }
}, },
"lich" : "lich" :
@ -165,15 +201,21 @@
"id": 64, "id": 64,
"level": 5, "level": 5,
"faction": "necropolis", "faction": "necropolis",
"abilities": [ [ "SPELL_LIKE_ATTACK", 0, "spell.deathCloud", 0 ] ], "abilities":
{
"deathCloud" :
{
"type" : "SPELL_LIKE_ATTACK",
"subtype" : "spell.deathCloud"
}
},
"upgrades": ["powerLich"], "upgrades": ["powerLich"],
"graphics" : "graphics" :
{ {
"animation": "CLICH.DEF", "animation": "CLICH.DEF",
"missile" : "missile" :
{ {
"projectile": "PLICH.DEF", "projectile": "PLICH.DEF"
"spinning": false
} }
}, },
"sound" : "sound" :
@ -183,8 +225,7 @@
"killed": "LICHKILL.wav", "killed": "LICHKILL.wav",
"move": "LICHMOVE.wav", "move": "LICHMOVE.wav",
"shoot": "LICHSHOT.wav", "shoot": "LICHSHOT.wav",
"wince": "LICHWNCE.wav", "wince": "LICHWNCE.wav"
"ext1": "LICHATK2.wav"
} }
}, },
"powerLich" : "powerLich" :
@ -192,14 +233,20 @@
"id": 65, "id": 65,
"level": 5, "level": 5,
"faction": "necropolis", "faction": "necropolis",
"abilities": [ [ "SPELL_LIKE_ATTACK", 0, "spell.deathCloud", 0 ] ], //power liches "abilities":
{
"deathCloud" :
{
"type" : "SPELL_LIKE_ATTACK",
"subtype" : "spell.deathCloud"
}
},
"graphics" : "graphics" :
{ {
"animation": "CPLICH.DEF", "animation": "CPLICH.DEF",
"missile" : "missile" :
{ {
"projectile": "PLICH.DEF", "projectile": "PLICH.DEF"
"spinning": false
} }
}, },
"sound" : "sound" :
@ -217,7 +264,15 @@
"id": 66, "id": 66,
"level": 6, "level": 6,
"faction": "necropolis", "faction": "necropolis",
"abilities": [ [ "SPELL_AFTER_ATTACK", 20, "spell.curse", 0 ] ], "abilities":
{
"curses" :
{
"type" : "SPELL_AFTER_ATTACK",
"subtype" : "spell.curse",
"val" : 20
}
},
"upgrades": ["dreadKnight"], "upgrades": ["dreadKnight"],
"graphics" : "graphics" :
{ {
@ -237,8 +292,20 @@
"id": 67, "id": 67,
"level": 6, "level": 6,
"faction": "necropolis", "faction": "necropolis",
"abilities": [ [ "SPELL_AFTER_ATTACK", 20, "spell.curse", 0 ], "abilities":
[ "DOUBLE_DAMAGE_CHANCE", 20, 0, 0 ] ], {
"curses" :
{
"type" : "SPELL_AFTER_ATTACK",
"subtype" : "spell.curse",
"val" : 20
},
"deathStrike" :
{
"type" : "DOUBLE_DAMAGE_CHANCE",
"val" : 20
}
},
"graphics" : "graphics" :
{ {
"animation": "CBLORD.DEF" "animation": "CBLORD.DEF"
@ -257,7 +324,13 @@
"id": 68, "id": 68,
"level": 7, "level": 7,
"faction": "necropolis", "faction": "necropolis",
"abilities": [ [ "DRAGON_NATURE", 0, 0, 0 ] ], //bone dragon is a dragon "abilities" :
{
"dragon" :
{
"type" : "DRAGON_NATURE"
}
},
"upgrades": ["ghostDragon"], "upgrades": ["ghostDragon"],
"graphics" : "graphics" :
{ {
@ -277,8 +350,19 @@
"id": 69, "id": 69,
"level": 7, "level": 7,
"faction": "necropolis", "faction": "necropolis",
"abilities": [ [ "DRAGON_NATURE", 0, 0, 0 ], //ghost dragon is a dragon "abilities":
[ "SPELL_AFTER_ATTACK", 20, "spell.age", 0 ] ], {
"dragon" :
{
"type" : "DRAGON_NATURE"
},
"age" :
{
"type" : "SPELL_AFTER_ATTACK",
"subtype" : "spell.age",
"val" : 20
}
},
"graphics" : "graphics" :
{ {
"animation": "CHDRGN.DEF" "animation": "CHDRGN.DEF"

View File

@ -5,8 +5,19 @@
"id": 116, "id": 116,
"level": 4, "level": 4,
"faction": "neutral", "faction": "neutral",
"abilities": [ [ "SPELL_DAMAGE_REDUCTION", 85, -1, 0 ], //gold golems reduce dmg from spells "abilities":
[ "NON_LIVING", 0, 0, 0 ] ], //diamond golems are non-living {
"magicResistance" :
{
"type" : "SPELL_DAMAGE_REDUCTION",
"subtype" : -1,
"val" : 85
},
"nonliving" :
{
"type" : "NON_LIVING"
}
},
"graphics" : "graphics" :
{ {
"animation": "CGGOLE.DEF" "animation": "CGGOLE.DEF"
@ -25,8 +36,19 @@
"id": 117, "id": 117,
"level": 5, "level": 5,
"faction": "neutral", "faction": "neutral",
"abilities": [ [ "SPELL_DAMAGE_REDUCTION", 95, -1, 0 ], //diamond golems reduce dmg from spells "abilities":
[ "NON_LIVING", 0, 0, 0 ] ], {
"magicResistance" :
{
"type" : "SPELL_DAMAGE_REDUCTION",
"subtype" : -1,
"val" : 95
},
"nonliving" :
{
"type" : "NON_LIVING"
}
},
"graphics" : "graphics" :
{ {
"animation": "CDGOLE.DEF" "animation": "CDGOLE.DEF"
@ -46,11 +68,30 @@
"id": 132, "id": 132,
"level": 10, "level": 10,
"faction": "neutral", "faction": "neutral",
"abilities": [ [ "DRAGON_NATURE", 0, 0, 0 ], "abilities":
[ "TWO_HEX_ATTACK_BREATH", 0, 0, 0 ], //azure dragon's breath {
[ "FEARLESS", 0, 0, 0 ], //azure dragon is immune to fear "dragon" :
[ "LEVEL_SPELL_IMMUNITY", 3, 0, 0 ], //immunity spell levels 1-3 {
[ "FEAR", 0, 0, 0]], //azure dragon is a dragon "type" : "DRAGON_NATURE"
},
"fireBreath" :
{
"type" : "TWO_HEX_ATTACK_BREATH"
},
"spellImmunity" :
{
"type" : "LEVEL_SPELL_IMMUNITY",
"val" : 3
},
"fearless" :
{
"type" : "FEARLESS"
},
"fear" :
{
"type" : "FEAR"
}
},
"graphics" : "graphics" :
{ {
"animation": "CADRGN.DEF" "animation": "CADRGN.DEF"
@ -70,8 +111,14 @@
"id": 133, "id": 133,
"level": 10, "level": 10,
"faction": "neutral", "faction": "neutral",
"abilities": [ [ "DRAGON_NATURE", 0, 0, 0 ] ], //crystal dragon is a dragon "abilities":
"ability_remove": [ "FLYING" ], //Crystal Dragons do not fly {
"dragon" :
{
"type" : "DRAGON_NATURE"
},
"FLYING" : null
},
"graphics" : "graphics" :
{ {
"animation": "CCDRGN.DEF" "animation": "CCDRGN.DEF"
@ -91,18 +138,84 @@
"id": 134, "id": 134,
"level": 8, "level": 8,
"faction": "neutral", "faction": "neutral",
"abilities": [ [ "DRAGON_NATURE", 0, 0, 0 ], //faerie dragon is a dragon "abilities":
[ "MAGIC_MIRROR", 30, 0, 0 ], {
[ "CASTS", 5, 0, 0 ], "dragon" :
[ "CREATURE_SPELL_POWER", 500, 0, 0], //5 spell power per dragon {
[ "SPELLCASTER", 2, "spell.magicArrow", 10 ], "type" : "DRAGON_NATURE",
[ "SPELLCASTER", 2, "spell.iceBolt", 22 ], },
[ "SPELLCASTER", 2, "spell.lightningBolt", 22 ], "mirror" :
[ "SPELLCASTER", 2, "spell.chainLightning", 5 ], {
[ "SPELLCASTER", 2, "spell.frostRing", 10 ], "type" : "MAGIC_MIRROR",
[ "SPELLCASTER", 2, "spell.fireball", 21 ], "val" : 30
[ "SPELLCASTER", 2, "spell.inferno", 5 ], },
[ "SPELLCASTER", 2, "spell.meteorShower", 5 ]], "casts" :
{
"type" : "CASTS",
"val" : 5
},
"spellpower" :
{
"type" : "CREATURE_SPELL_POWER",
"val" : 500
},
"castsMagicArrow" :
{
"type" : "SPELLCASTER",
"subtype" : "spell.magicArrow",
"addInfo" : 22,
"val" : 2
},
"castsIceBolt" :
{
"type" : "SPELLCASTER",
"subtype" : "spell.iceBolt",
"addInfo" : 22,
"val" : 2
},
"castsLightningBolt" :
{
"type" : "SPELLCASTER",
"subtype" : "spell.lightningBolt",
"addInfo" : 22,
"val" : 2
},
"castsChainLightning" :
{
"type" : "SPELLCASTER",
"subtype" : "spell.chainLightning",
"addInfo" : 5,
"val" : 2
},
"castsFrostRing" :
{
"type" : "SPELLCASTER",
"subtype" : "spell.frostRing",
"addInfo" : 10,
"val" : 2
},
"castsFireball" :
{
"type" : "SPELLCASTER",
"subtype" : "spell.fireball",
"addInfo" : 21,
"val" : 2
},
"castsInferno" :
{
"type" : "SPELLCASTER",
"subtype" : "spell.inferno",
"addInfo" : 5,
"val" : 2
},
"castsMeteorShower" :
{
"type" : "SPELLCASTER",
"subtype" : "spell.meteorShower",
"addInfo" : 5,
"val" : 2
}
},
"graphics" : "graphics" :
{ {
"animation": "CFDRGN.DEF" "animation": "CFDRGN.DEF"
@ -123,9 +236,25 @@
"id": 135, "id": 135,
"level": 10, "level": 10,
"faction": "neutral", "faction": "neutral",
"abilities": [ [ "SPELL_AFTER_ATTACK", 100, 80, 0 ], //always reduce defense "abilities":
[ "ACID_BREATH", 25, 0, 20 ], //20% chance to do 25 damage {
[ "DRAGON_NATURE", 0, 0, 0 ] ], //rust dragon is a dragon "dragon" :
{
"type" : "DRAGON_NATURE"
},
"acidBreath" :
{
"type" : "ACID_BREATH",
"val" : 25,
"addInfo" : 20
},
"reduceDefence" :
{
"type" : "SPELL_AFTER_ATTACK",
"subtype" : "spell.acidBreath",
"val" : 100
}
},
"graphics" : "graphics" :
{ {
"animation": "CRSDGN.DEF" "animation": "CRSDGN.DEF"
@ -146,21 +275,67 @@
"level": 6, "level": 6,
"extraNames": [ "enchanters" ], "extraNames": [ "enchanters" ],
"faction": "neutral", "faction": "neutral",
"abilities": [ [ "NO_WALL_PENALTY", 0, 0, 0 ], "abilities":
[ "ENCHANTER", 3, "spell.airShield", 3], {
[ "ENCHANTER", 3, "spell.bless", 3], "noPenalty" :
[ "ENCHANTER", 3, "spell.weakness", 3], {
[ "ENCHANTER", 3, "spell.stoneSkin", 3], "type" : "NO_WALL_PENALTY"
[ "ENCHANTER", 3, "spell.slow", 3], },
[ "ENCHANTER", 3, "spell.haste", 3], "casts" :
[ "CASTS", 5, 0, 0]], {
"type" : "CASTS",
"val" : 5
},
"castsAirShield" :
{
"type" : "ENCHANTER",
"subtype" : "spell.airShield",
"val" : 3,
"addInfo" : 3
},
"castsBless" :
{
"type" : "ENCHANTER",
"subtype" : "spell.bless",
"val" : 3,
"addInfo" : 3
},
"castsWeakness" :
{
"type" : "ENCHANTER",
"subtype" : "spell.weakness",
"val" : 3,
"addInfo" : 3
},
"castsStoneSkin" :
{
"type" : "ENCHANTER",
"subtype" : "spell.stoneSkin",
"val" : 3,
"addInfo" : 3
},
"castsSlow" :
{
"type" : "ENCHANTER",
"subtype" : "spell.slow",
"val" : 3,
"addInfo" : 3
},
"castsHaste" :
{
"type" : "ENCHANTER",
"subtype" : "spell.haste",
"val" : 3,
"addInfo" : 3
}
},
"graphics" : "graphics" :
{ {
"animation": "CENCH.DEF", "animation": "CGTITA.DEF",
"missile" : "missile" :
{ {
"projectile": "CPRZEAX.DEF", "projectile": "CPRZEAX.DEF"
"spinning": false
} }
}, },
"sound" : "sound" :
@ -180,15 +355,23 @@
"level": 4, "level": 4,
"extraNames": [ "sharpshooters" ], "extraNames": [ "sharpshooters" ],
"faction": "neutral", "faction": "neutral",
"abilities": [ [ "NO_WALL_PENALTY", 0, 0, 0 ], "abilities":
[ "NO_DISTANCE_PENALTY", 0, 0, 0 ] ], {
"noPenalty" :
{
"type" : "NO_WALL_PENALTY"
},
"noDistancePenalty" :
{
"type" : "NO_DISTANCE_PENALTY"
}
},
"graphics" : "graphics" :
{ {
"animation": "CSHARP.DEF", "animation": "CSHARP.DEF",
"missile" : "missile" :
{ {
"projectile": "PELFX.DEF", "projectile": "PELFX.DEF"
"spinning": false
} }
}, },
"sound" : "sound" :
@ -211,8 +394,7 @@
"animation": "CHALF.DEF", "animation": "CHALF.DEF",
"missile" : "missile" :
{ {
"projectile": "PHALF.DEF", "projectile": "PHALF.DEF"
"spinning": true
} }
}, },
"sound" : "sound" :
@ -248,7 +430,7 @@
"id": 140, "id": 140,
"level": 2, "level": 2,
"faction": "neutral", "faction": "neutral",
"abilities": [ [ "DOUBLE_WIDE", 0, 0, 0 ] ], //boar should be treated as double-wide "doubleWide" : true,
"graphics" : "graphics" :
{ {
"animation": "CBOAR.DEF" "animation": "CBOAR.DEF"
@ -267,7 +449,13 @@
"id": 141, "id": 141,
"level": 3, "level": 3,
"faction": "neutral", "faction": "neutral",
"abilities": [ [ "UNDEAD", 0, 0, 0 ] ], "abilities":
{
"undead" :
{
"type" : "UNDEAD"
}
},
"graphics" : "graphics" :
{ {
"animation": "CMUMMY.DEF" "animation": "CMUMMY.DEF"
@ -286,7 +474,7 @@
"id": 142, "id": 142,
"level": 3, "level": 3,
"faction": "neutral", "faction": "neutral",
"abilities": [ [ "DOUBLE_WIDE", 0, 0, 0 ] ], //nomads should be treated as double-wide "doubleWide" : true,
"graphics" : "graphics" :
{ {
"animation": "CNOMAD.DEF" "animation": "CNOMAD.DEF"
@ -323,7 +511,13 @@
"id": 144, "id": 144,
"level": 5, "level": 5,
"faction": "neutral", "faction": "neutral",
"abilities": [ [ "FULL_HP_REGENERATION", 0, 0, 0 ] ], "abilities":
{
"regenerates" :
{
"type" : "FULL_HP_REGENERATION"
}
},
"graphics" : "graphics" :
{ {
"animation": "CTROLL.DEF" "animation": "CTROLL.DEF"

View File

@ -8,6 +8,7 @@
"hasDoubleWeek": true, "hasDoubleWeek": true,
"graphics" : "graphics" :
{ {
"missile" : null,
"animation": "CCENTR.DEF" "animation": "CCENTR.DEF"
}, },
"sound" : "sound" :
@ -27,6 +28,7 @@
"faction": "rampart", "faction": "rampart",
"graphics" : "graphics" :
{ {
"missile" : null,
"animation": "CECENT.DEF" "animation": "CECENT.DEF"
}, },
"sound" : "sound" :
@ -43,7 +45,14 @@
"id": 16, "id": 16,
"level": 2, "level": 2,
"faction": "rampart", "faction": "rampart",
"abilities": [ [ "MAGIC_RESISTANCE", 20, 0, 0 ] ], //dwarf's magic resistance 20% "abilities":
{
"magicResistance" :
{
"type" : "MAGIC_RESISTANCE",
"val" : 20
}
},
"upgrades": ["battleDwarf"], "upgrades": ["battleDwarf"],
"graphics" : "graphics" :
{ {
@ -63,7 +72,14 @@
"id": 17, "id": 17,
"level": 2, "level": 2,
"faction": "rampart", "faction": "rampart",
"abilities": [ [ "MAGIC_RESISTANCE", 40, 0, 0 ] ], //battle dwarf's magic resistance 40% "abilities":
{
"magicResistance" :
{
"type" : "MAGIC_RESISTANCE",
"val" : 40
}
},
"graphics" : "graphics" :
{ {
"animation": "CBDWAR.DEF" "animation": "CBDWAR.DEF"
@ -88,8 +104,7 @@
"animation": "CELF.DEF", "animation": "CELF.DEF",
"missile" : "missile" :
{ {
"projectile": "PELFX.DEF", "projectile": "PELFX.DEF"
"spinning": false
} }
}, },
"sound" : "sound" :
@ -107,20 +122,21 @@
"id": 19, "id": 19,
"level": 3, "level": 3,
"faction": "rampart", "faction": "rampart",
"abilities": [ "abilities":
{
"doubleShot" :
{ {
"type": "ADDITIONAL_ATTACK", "type": "ADDITIONAL_ATTACK",
"val" : 1, "val" : 1,
"effectRange": "ONLY_DISTANCE_FIGHT" "effectRange": "ONLY_DISTANCE_FIGHT"
} }
], },
"graphics" : "graphics" :
{ {
"animation": "CGRELF.DEF", "animation": "CGRELF.DEF",
"missile" : "missile" :
{ {
"projectile": "PELFX.DEF", "projectile": "PELFX.DEF"
"spinning": false
} }
}, },
"sound" : "sound" :
@ -138,7 +154,14 @@
"id": 20, "id": 20,
"level": 4, "level": 4,
"faction": "rampart", "faction": "rampart",
"abilities": [ [ "CHANGES_SPELL_COST_FOR_ENEMY", 2, 0, 0 ] ], //pegasus makes spell cost higher for enemy mage "abilities":
{
"increaseManaCost" :
{
"type" : "CHANGES_SPELL_COST_FOR_ENEMY",
"val" : 2
}
},
"upgrades": ["silverPegasus"], "upgrades": ["silverPegasus"],
"hasDoubleWeek": true, "hasDoubleWeek": true,
"graphics" : "graphics" :
@ -159,7 +182,14 @@
"id": 21, "id": 21,
"level": 4, "level": 4,
"faction": "rampart", "faction": "rampart",
"abilities": [ [ "CHANGES_SPELL_COST_FOR_ENEMY", 2, 0, 0 ] ], //silver pegasus makes spell cost higher for enemy mage "abilities":
{
"increaseManaCost" :
{
"type" : "CHANGES_SPELL_COST_FOR_ENEMY",
"val" : 2
}
},
"graphics" : "graphics" :
{ {
"animation": "CAPEGS.DEF" "animation": "CAPEGS.DEF"
@ -178,7 +208,15 @@
"id": 22, "id": 22,
"level": 5, "level": 5,
"faction": "rampart", "faction": "rampart",
"abilities": [ [ "SPELL_AFTER_ATTACK", 100, "spell.bind", 0 ] ], //dendroids cast bind "abilities":
{
"binds" :
{
"type" : "SPELL_AFTER_ATTACK",
"subtype" : "spell.bind",
"val" : 100
}
},
"upgrades": ["dendroidSoldier"], "upgrades": ["dendroidSoldier"],
"graphics" : "graphics" :
{ {
@ -198,7 +236,15 @@
"id": 23, "id": 23,
"level": 5, "level": 5,
"faction": "rampart", "faction": "rampart",
"abilities": [ [ "SPELL_AFTER_ATTACK", 100, "spell.bind", 0 ] ], //dendroid guards cast bind "abilities":
{
"binds" :
{
"type" : "SPELL_AFTER_ATTACK",
"subtype" : "spell.bind",
"val" : 100
}
},
"graphics" : "graphics" :
{ {
"animation": "CBTREE.DEF" "animation": "CBTREE.DEF"
@ -217,8 +263,20 @@
"id": 24, "id": 24,
"level": 6, "level": 6,
"faction": "rampart", "faction": "rampart",
"abilities": [ [ "SPELL_RESISTANCE_AURA", 0, 55, 0 ], //unicorn "abilities":
[ "SPELL_AFTER_ATTACK", 20, "spell.blind", 0 ] ], //unicorns cast blind with 20% probability {
"spellResistAura" :
{
"type" : "SPELL_RESISTANCE_AURA",
"val" : 20
},
"blinds" :
{
"type" : "SPELL_AFTER_ATTACK",
"subtype" : "spell.blind",
"val" : 20
}
},
"upgrades": ["warUnicorn"], "upgrades": ["warUnicorn"],
"graphics" : "graphics" :
{ {
@ -238,8 +296,20 @@
"id": 25, "id": 25,
"level": 6, "level": 6,
"faction": "rampart", "faction": "rampart",
"abilities": [ [ "SPELL_RESISTANCE_AURA", 20, 55, 0 ], //war unicorn "abilities":
[ "SPELL_AFTER_ATTACK", 20, "spell.blind", 0 ] ], //war unicorns cast blind with 20% probability {
"spellResistAura" :
{
"type" : "SPELL_RESISTANCE_AURA",
"val" : 20
},
"blinds" :
{
"type" : "SPELL_AFTER_ATTACK",
"subtype" : "spell.blind",
"val" : 20
}
},
"graphics" : "graphics" :
{ {
"animation": "CWUNIC.DEF" "animation": "CWUNIC.DEF"
@ -259,9 +329,22 @@
"id": 26, "id": 26,
"level": 7, "level": 7,
"faction": "rampart", "faction": "rampart",
"abilities": [ [ "DRAGON_NATURE", 0, 0, 0 ], //green dragon is a dragon "abilities":
[ "TWO_HEX_ATTACK_BREATH", 0, 0, 0 ], //green dragon's breath {
[ "LEVEL_SPELL_IMMUNITY", 3, 0, 0 ] ], //green dragon's spell immunity "dragon" :
{
"type" : "DRAGON_NATURE"
},
"fireBreath" :
{
"type" : "TWO_HEX_ATTACK_BREATH"
},
"spellImmunity" :
{
"type" : "LEVEL_SPELL_IMMUNITY",
"val" : 3
}
},
"upgrades": ["goldDragon"], "upgrades": ["goldDragon"],
"graphics" : "graphics" :
{ {
@ -281,9 +364,22 @@
"id": 27, "id": 27,
"level": 7, "level": 7,
"faction": "rampart", "faction": "rampart",
"abilities": [ [ "DRAGON_NATURE", 0, 0, 0 ], //gold dragon is a dragon "abilities":
[ "TWO_HEX_ATTACK_BREATH", 0, 0, 0 ], //gold dragon's breath {
[ "LEVEL_SPELL_IMMUNITY", 4, 0, 0 ] ], //gold dragon's spell immunity "dragon" :
{
"type" : "DRAGON_NATURE"
},
"fireBreath" :
{
"type" : "TWO_HEX_ATTACK_BREATH"
},
"spellImmunity" :
{
"type" : "LEVEL_SPELL_IMMUNITY",
"val" : 4
}
},
"graphics" : "graphics" :
{ {
"animation": "CDDRAG.DEF" "animation": "CDDRAG.DEF"

View File

@ -4,25 +4,29 @@
"unused122" : "unused122" :
{ {
"faction": "neutral", "faction": "neutral",
"special" : true, "disabled" : true,
"graphics" : null,
"id" : 122 "id" : 122
}, },
"unused124" : "unused124" :
{ {
"faction": "neutral", "faction": "neutral",
"special" : true, "disabled" : true,
"graphics" : null,
"id" : 124 "id" : 124
}, },
"unused126" : "unused126" :
{ {
"faction": "neutral", "faction": "neutral",
"special" : true, "disabled" : true,
"graphics" : null,
"id" : 126 "id" : 126
}, },
"unused128" : "unused128" :
{ {
"faction": "neutral", "faction": "neutral",
"special" : true, "disabled" : true,
"graphics" : null,
"id" : 128 "id" : 128
}, },
@ -37,8 +41,7 @@
"animation": "SMCATA.DEF", "animation": "SMCATA.DEF",
"missile" : "missile" :
{ {
"projectile": "SMCATX.DEF", "projectile": "SMCATX.DEF"
"spinning": true
} }
}, },
"sound" : "sound" :
@ -59,8 +62,7 @@
"animation": "SMBAL.DEF", "animation": "SMBAL.DEF",
"missile" : "missile" :
{ {
"projectile": "SMBALX.DEF", "projectile": "SMBALX.DEF"
"spinning": false
} }
}, },
"sound" : "sound" :
@ -76,7 +78,7 @@
"id": 147, "id": 147,
"level": 0, "level": 0,
"faction": "neutral", "faction": "neutral",
"abilities": [ [ "HEALER", 0, 0, 0 ] ], "abilities": { "heals" : { "type" : "HEALER" } },
"graphics" : "graphics" :
{ {
"animation": "SMTENT.DEF" "animation": "SMTENT.DEF"
@ -93,7 +95,7 @@
"id": 148, "id": 148,
"level": 0, "level": 0,
"faction": "neutral", "faction": "neutral",
"abilities": [ [ "NOT_ACTIVE", 0, 0, 0 ] ], "abilities": { "inactive" : { "type" : "NOT_ACTIVE" } },
"graphics" : "graphics" :
{ {
"animation": "SMCART.DEF" "animation": "SMCART.DEF"
@ -110,13 +112,11 @@
"id": 149, "id": 149,
"level": 0, "level": 0,
"faction": "neutral", "faction": "neutral",
"abilities": [ [ "SHOOTER", 0, 0, 0 ] ], "abilities": { "shooter" : { "type" : "SHOOTER" } },
"graphics" : "graphics" :
{ {
"missile" : "animation" : "This should never be used"
{ },
"projectile": "SMBALX.DEF", //workaround for crash "sound": {}
}
}
} }
} }

View File

@ -63,7 +63,14 @@
"id": 87, "id": 87,
"level": 2, "level": 2,
"faction": "stronghold", "faction": "stronghold",
"abilities": [ [ "ADDITIONAL_ATTACK", 1, 0, 0 ] ], "abilities":
{
"extraAttack" :
{
"type" : "ADDITIONAL_ATTACK",
"val" : 1
}
},
"graphics" : "graphics" :
{ {
"animation": "CUWLFR.DEF" "animation": "CUWLFR.DEF"
@ -88,8 +95,7 @@
"animation": "CORC.DEF", "animation": "CORC.DEF",
"missile" : "missile" :
{ {
"projectile": "PORCHX.DEF", "projectile": "PORCHX.DEF"
"spinning": true
} }
}, },
"sound" : "sound" :
@ -112,8 +118,7 @@
"animation": "CORCCH.DEF", "animation": "CORCCH.DEF",
"missile" : "missile" :
{ {
"projectile": "PORCHX.DEF", "projectile": "PORCHX.DEF"
"spinning": true
} }
}, },
"sound" : "sound" :
@ -150,9 +155,25 @@
"id": 91, "id": 91,
"level": 4, "level": 4,
"faction": "stronghold", "faction": "stronghold",
"abilities": [ [ "SPELLCASTER", 2, "spell.bloodlust", 0 ], "abilities":
[ "CASTS", 3, 0, 0], {
[ "CREATURE_ENCHANT_POWER", 3, 0, 0]], "castsBloodlust" :
{
"type" : "SPELLCASTER",
"subtype" : "spell.bloodlust",
"val" : 2
},
"castsCount" :
{
"type" : "CASTS",
"val" : 3
},
"castLength" :
{
"type" : "CREATURE_ENCHANT_POWER",
"val" : 3
}
},
"graphics" : "graphics" :
{ {
"animation": "COGMAG.DEF" "animation": "COGMAG.DEF"
@ -191,8 +212,21 @@
"id": 93, "id": 93,
"level": 5, "level": 5,
"faction": "stronghold", "faction": "stronghold",
"abilities": [ [ "SPECIFIC_SPELL_POWER", 10, "spell.thunderbolt", 0 ], //10 damage per unit "abilities":
[ "SPELL_AFTER_ATTACK", 20, "spell.thunderbolt", 0 ] ], {
"thunderStrength" :
{
"type" : "SPECIFIC_SPELL_POWER",
"subtype" : "spell.thunderbolt",
"val" : 10
},
"thunderOnAttack" :
{
"type" : "SPELL_AFTER_ATTACK",
"subtype" : "spell.thunderbolt",
"val" : 20
}
},
"graphics" : "graphics" :
{ {
"animation": "CTBIRD.DEF" "animation": "CTBIRD.DEF"
@ -217,8 +251,7 @@
"animation": "CCYCLR.DEF", "animation": "CCYCLR.DEF",
"missile" : "missile" :
{ {
"projectile": "PCYCLBX.DEF", "projectile": "PCYCLBX.DEF"
"spinning": true
} }
}, },
"sound" : "sound" :
@ -241,8 +274,7 @@
"animation": "CCYCLLOR.DEF", "animation": "CCYCLLOR.DEF",
"missile" : "missile" :
{ {
"projectile": "PCYCLBX.DEF", "projectile": "PCYCLBX.DEF"
"spinning": true
} }
}, },
"sound" : "sound" :
@ -260,7 +292,14 @@
"id": 96, "id": 96,
"level": 7, "level": 7,
"faction": "stronghold", "faction": "stronghold",
"abilities": [ [ "ENEMY_DEFENCE_REDUCTION", 40, 0, 0 ] ], "abilities":
{
"reduceDefence" :
{
"type" : "ENEMY_DEFENCE_REDUCTION",
"val" : 40
}
},
"upgrades": ["ancientBehemoth"], "upgrades": ["ancientBehemoth"],
"graphics" : "graphics" :
{ {
@ -280,7 +319,14 @@
"id": 97, "id": 97,
"level": 7, "level": 7,
"faction": "stronghold", "faction": "stronghold",
"abilities": [ [ "ENEMY_DEFENCE_REDUCTION", 80, 0, 0 ] ], "abilities":
{
"reduceDefence" :
{
"type" : "ENEMY_DEFENCE_REDUCTION",
"val" : 80
}
},
"graphics" : "graphics" :
{ {
"animation": "CABEHE.DEF" "animation": "CABEHE.DEF"

View File

@ -31,8 +31,7 @@
"animation": "CGREMM.DEF", "animation": "CGREMM.DEF",
"missile" : "missile" :
{ {
"projectile": "CPRGRE.DEF", "projectile": "CPRGRE.DEF"
"spinning": false
} }
}, },
"sound" : "sound" :
@ -50,7 +49,13 @@
"id": 30, "id": 30,
"level": 2, "level": 2,
"faction": "tower", "faction": "tower",
"abilities": [ [ "NON_LIVING", 0, 0, 0 ] ], //stone gargoyles are non-living "abilities":
{
"nonliving" :
{
"type" : "NON_LIVING"
}
},
"upgrades": ["obsidianGargoyle"], "upgrades": ["obsidianGargoyle"],
"graphics" : "graphics" :
{ {
@ -70,7 +75,13 @@
"id": 31, "id": 31,
"level": 2, "level": 2,
"faction": "tower", "faction": "tower",
"abilities": [ [ "NON_LIVING", 0, 0, 0 ] ], //obsidian gargoyles are non-living "abilities":
{
"nonliving" :
{
"type" : "NON_LIVING"
}
},
"graphics" : "graphics" :
{ {
"animation": "COGARG.DEF" "animation": "COGARG.DEF"
@ -89,8 +100,19 @@
"id": 32, "id": 32,
"level": 3, "level": 3,
"faction": "tower", "faction": "tower",
"abilities": [ [ "SPELL_DAMAGE_REDUCTION", 50, -1, 0 ], //stone golems reduce dmg from spells "abilities":
[ "NON_LIVING", 0, 0, 0 ] ], //stone golems are non-living {
"magicResistance" :
{
"type" : "SPELL_DAMAGE_REDUCTION",
"subtype" : -1,
"val" : 50
},
"nonliving" :
{
"type" : "NON_LIVING"
}
},
"upgrades": ["stoneGolem"], "upgrades": ["stoneGolem"],
"graphics" : "graphics" :
{ {
@ -110,8 +132,19 @@
"id": 33, "id": 33,
"level": 3, "level": 3,
"faction": "tower", "faction": "tower",
"abilities": [ [ "SPELL_DAMAGE_REDUCTION", 75, -1, 0 ], //iron golems reduce dmg from spells "abilities" :
[ "NON_LIVING", 0, 0, 0 ] ], //iron golems are non-living {
"magicResistance" :
{
"type" : "SPELL_DAMAGE_REDUCTION",
"subtype" : -1,
"val" : 75
},
"nonliving" :
{
"type" : "NON_LIVING"
}
},
"graphics" : "graphics" :
{ {
"animation": "CIGOLE.DEF" "animation": "CIGOLE.DEF"
@ -130,15 +163,21 @@
"id": 34, "id": 34,
"level": 4, "level": 4,
"faction": "tower", "faction": "tower",
"abilities": [ [ "CHANGES_SPELL_COST_FOR_ALLY", 2, 0, 0 ] ], //mages reduce spell cost "abilities":
{
"reduceSpellCost" :
{
"type" : "CHANGES_SPELL_COST_FOR_ALLY",
"val" : 2
}
},
"upgrades": ["archMage"], "upgrades": ["archMage"],
"graphics" : "graphics" :
{ {
"animation": "CMAGE.DEF", "animation": "CMAGE.DEF",
"missile" : "missile" :
{ {
"projectile": "PMAGEX.DEF", "projectile": "PMAGEX.DEF"
"spinning": false
} }
}, },
"sound" : "sound" :
@ -156,14 +195,20 @@
"id": 35, "id": 35,
"level": 4, "level": 4,
"faction": "tower", "faction": "tower",
"abilities": [ [ "CHANGES_SPELL_COST_FOR_ALLY", 2, 0, 0 ]], //archmages reduce spell cost "abilities":
{
"reduceSpellCost" :
{
"type" : "CHANGES_SPELL_COST_FOR_ALLY",
"val" : 2
}
},
"graphics" : "graphics" :
{ {
"animation": "CAMAGE.DEF", "animation": "CAMAGE.DEF",
"missile" : "missile" :
{ {
"projectile": "PMAGEX.DEF", "projectile": "PMAGEX.DEF"
"spinning": false
} }
}, },
"sound" : "sound" :
@ -181,8 +226,21 @@
"id": 36, "id": 36,
"level": 5, "level": 5,
"faction": "tower", "faction": "tower",
"abilities": [ [ "HATE", 50, 53, 0 ], //master genies hate efreets "abilities":
[ "HATE", 50, 52, 0 ] ], //genies hate efreet sultans {
"hateAngels" :
{
"type" : "HATE",
"subtype" : "creature.efreet",
"val" : 50
},
"hateArchAngels" :
{
"type" : "HATE",
"subtype" : "creature.efreetSultan",
"val" : 50
}
},
"upgrades": ["masterGenie"], "upgrades": ["masterGenie"],
"graphics" : "graphics" :
{ {
@ -202,11 +260,36 @@
"id": 37, "id": 37,
"level": 5, "level": 5,
"faction": "tower", "faction": "tower",
"abilities": [ [ "CREATURE_ENCHANT_POWER", 5, 0, 0 ], //spells last 5 turns "abilities":
[ "RANDOM_SPELLCASTER", 2, 0, 0 ], //master genies cast spells on advanced level {
[ "CASTS", 3, 0, 0], "hateAngels" :
[ "HATE", 50, 53, 0 ], {
[ "HATE", 50, 52, 0 ] ], //master genies hate efreet sultans "type" : "HATE",
"subtype" : "creature.efreet",
"val" : 50
},
"hateArchAngels" :
{
"type" : "HATE",
"subtype" : "creature.efreetSultan",
"val" : 50
},
"spellsLength" :
{
"type" : "CREATURE_ENCHANT_POWER",
"val" : 5
},
"randomSpellcaster" :
{
"type" : "RANDOM_SPELLCASTER",
"val" : 2
},
"casts" :
{
"type" : "CASTS",
"val" : 3
}
},
"graphics" : "graphics" :
{ {
"animation": "CSULTA.DEF" "animation": "CSULTA.DEF"
@ -226,7 +309,13 @@
"id": 38, "id": 38,
"level": 6, "level": 6,
"faction": "tower", "faction": "tower",
"abilities": [ [ "BLOCKS_RETALIATION", 0, 0, 0 ] ], //nagas block retaliation "abilities" :
{
"noRetaliation" :
{
"type" : "BLOCKS_RETALIATION"
}
},
"upgrades": ["nagaQueen"], "upgrades": ["nagaQueen"],
"graphics" : "graphics" :
{ {
@ -246,7 +335,13 @@
"id": 39, "id": 39,
"level": 6, "level": 6,
"faction": "tower", "faction": "tower",
"abilities": [ [ "BLOCKS_RETALIATION", 0, 0, 0 ] ], //naga queens block retaliation "abilities" :
{
"noRetaliation" :
{
"type" : "BLOCKS_RETALIATION"
}
},
"graphics" : "graphics" :
{ {
"animation": "CNAGAG.DEF" "animation": "CNAGAG.DEF"
@ -265,7 +360,13 @@
"id": 40, "id": 40,
"level": 7, "level": 7,
"faction": "tower", "faction": "tower",
"abilities": [ ["MIND_IMMUNITY", 0, 0, 0] ], //giants are immune to mind spells "abilities" :
{
"immuneToMind" :
{
"type" : "MIND_IMMUNITY"
}
},
"upgrades": ["titan"], "upgrades": ["titan"],
"graphics" : "graphics" :
{ {
@ -285,15 +386,25 @@
"id": 41, "id": 41,
"level": 7, "level": 7,
"faction": "tower", "faction": "tower",
"abilities": [ ["MIND_IMMUNITY", 0, 0, 0], //Titans are immune to mind spells "abilities" :
[ "HATE", 50, "creature.blackDragon", 0 ] ], //titans hate black dragons {
"immuneToMind" :
{
"type" : "MIND_IMMUNITY"
},
"hateArchAngels" :
{
"type" : "HATE",
"subtype" : "creature.blackDragon",
"val" : 50
}
},
"graphics" : "graphics" :
{ {
"animation": "CGTITA.DEF", "animation": "CGTITA.DEF",
"missile" : "missile" :
{ {
"projectile": "CPRGTIX.DEF", "projectile": "CPRGTIX.DEF"
"spinning": false
} }
}, },
"sound" : "sound" :

View File

@ -22,7 +22,13 @@
"id": 151, "id": 151,
"level": 8, "level": 8,
"faction": "rampart", "faction": "rampart",
"abilities": [ [ "DRAGON_NATURE", 0, 0, 0 ] ], //diamond dragon is a dragon "abilities":
{
"dragon" :
{
"type" : "DRAGON_NATURE"
}
},
"graphics" : "graphics" :
{ {
"animation": "ZM151Z.DEF" "animation": "ZM151Z.DEF"
@ -46,8 +52,7 @@
"animation": "ZM152Z.DEF", "animation": "ZM152Z.DEF",
"missile" : "missile" :
{ {
"projectile": "CPRGTIX.DEF", "projectile": "CPRGTIX.DEF"
"spinning": false
} }
}, },
"sound" : "sound" :
@ -65,9 +70,17 @@
"id": 153, "id": 153,
"level": 8, "level": 8,
"faction": "inferno", "faction": "inferno",
"abilities": [ [ "FLYING", 0, 1, 0 ] ], "abilities":
{
"teleport" :
{
"type" : "FLYING",
"subtype" : 1
}
},
"graphics" : "graphics" :
{ {
"missile" : null,
"animation": "ZM153Z.DEF" "animation": "ZM153Z.DEF"
}, },
"sound" : "sound" :
@ -78,7 +91,7 @@
"move": "ADVLMOVE.wav", "move": "ADVLMOVE.wav",
"wince": "ADVLWNCE.wav", "wince": "ADVLWNCE.wav",
"startMoving": "ADVLEXT1.wav", "startMoving": "ADVLEXT1.wav",
"stopMoving": "ADVLEXT2.wav" "endMoving": "ADVLEXT2.wav"
} }
}, },
"bloodDragon" : "bloodDragon" :
@ -86,8 +99,18 @@
"id": 154, "id": 154,
"level": 8, "level": 8,
"faction": "necropolis", "faction": "necropolis",
"abilities": [ [ "LIFE_DRAIN", 40, 0, 0 ], //40% "abilities":
[ "DRAGON_NATURE", 0, 0, 0 ] ], //blood dragon is a dragon {
"drainsLife" :
{
"type" : "LIFE_DRAIN",
"val" : 40
},
"dragon" :
{
"type" : "DRAGON_NATURE"
}
},
"graphics" : "graphics" :
{ {
"animation": "ZM154Z.DEF" "animation": "ZM154Z.DEF"
@ -106,7 +129,13 @@
"id": 155, "id": 155,
"level": 8, "level": 8,
"faction": "dungeon", "faction": "dungeon",
"abilities": [ [ "DRAGON_NATURE", 0, 0, 0 ] ], //darkness dragon is a dragon "abilities":
{
"dragon" :
{
"type" : "DRAGON_NATURE"
}
},
"graphics" : "graphics" :
{ {
"animation": "ZM155Z.DEF" "animation": "ZM155Z.DEF"
@ -143,7 +172,10 @@
"id": 157, "id": 157,
"level": 8, "level": 8,
"faction": "fortress", "faction": "fortress",
"ability_remove": [ "SHOOTER" ], //Hell Hydra certainly does not shoot "abilities" :
{
"SHOOTER" : null
},
"graphics" : "graphics" :
{ {
"animation": "ZM157Z.DEF" "animation": "ZM157Z.DEF"
@ -195,7 +227,7 @@
}, },
"godWar" : "godWar" :
{ {
"special" : true, "disabled" : true,
"id": 160, "id": 160,
"level": 0, "level": 0,
"faction": "neutral", "faction": "neutral",
@ -206,7 +238,7 @@
}, },
"godPeace" : "godPeace" :
{ {
"special" : true, "disabled" : true,
"id": 161, "id": 161,
"level": 0, "level": 0,
"faction": "neutral", "faction": "neutral",
@ -217,7 +249,7 @@
}, },
"godMana" : "godMana" :
{ {
"special" : true, "disabled" : true,
"id": 162, "id": 162,
"level": 0, "level": 0,
"faction": "neutral", "faction": "neutral",
@ -228,7 +260,7 @@
}, },
"godLore" : "godLore" :
{ {
"special" : true, "disabled" : true,
"id": 163, "id": 163,
"level": 0, "level": 0,
"faction": "neutral", "faction": "neutral",
@ -314,7 +346,13 @@
"id": 168, "id": 168,
"level": 0, "level": 0,
"faction": "neutral", "faction": "neutral",
"abilities": [ [ "FLYING", 0, 0, 0 ] ], //Gorynyches fly "abilities":
{
"canFly" :
{
"type" : "FLYING"
}
},
"graphics" : "graphics" :
{ {
"animation": "ZM168DG.DEF" "animation": "ZM168DG.DEF"
@ -338,8 +376,7 @@
"animation": "ZM169ZL.DEF", "animation": "ZM169ZL.DEF",
"missile" : "missile" :
{ {
"projectile": "CPRZEAX.DEF", "projectile": "CPRZEAX.DEF"
"spinning": false
} }
}, },
"sound" : "sound" :
@ -362,8 +399,7 @@
"animation": "ZM170SW.DEF", "animation": "ZM170SW.DEF",
"missile" : "missile" :
{ {
"projectile": "PLCBOWX.DEF", "projectile": "PLCBOWX.DEF"
"spinning": false
} }
}, },
"sound" : "sound" :
@ -386,8 +422,7 @@
"animation": "ZM171SR.DEF", "animation": "ZM171SR.DEF",
"missile" : "missile" :
{ {
"projectile": "PLCBOWX.DEF", "projectile": "PLCBOWX.DEF"
"spinning": false
} }
}, },
"sound" : "sound" :
@ -425,12 +460,11 @@
"faction": "neutral", "faction": "neutral",
"graphics" : "graphics" :
{ {
"animation": "ZM173M.DEF", "animation": "ZM173M.DEF"
"missile" : //"missile" :
{ //{
"projectile": "CPRGRE.DEF", // "projectile": "CPRGRE.DEF"
"spinning": true //}
}
}, },
"sound" : "sound" :
{ {
@ -460,7 +494,7 @@
"projectile": "PLCBOWX.DEF" "projectile": "PLCBOWX.DEF"
} }
}, },
"sounds" : "sound" :
{ {
"attack": "CRUSATTK.wav", "attack": "CRUSATTK.wav",
"defend": "CRUSDFND.wav", "defend": "CRUSDFND.wav",
@ -475,11 +509,35 @@
"id": 175, "id": 175,
"level": 0, "level": 0,
"faction": "neutral", "faction": "neutral",
"abilities": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ], "abilities":
[ "CASTS", 1, 0, 0 ] , {
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] , "magicResistance" :
[ "CREATURE_SPELL_POWER", 100, 0, 0 ] , {
[ "SPELLCASTER", 3, "spell.shield", 0 ] ], //expert shield "type" : "MAGIC_RESISTANCE",
"val" : 5
},
"castsAmount" :
{
"type" : "CASTS",
"val" : 1
},
"enchant" :
{
"type" : "CREATURE_ENCHANT_POWER",
"val" : 1
},
"spellpower" :
{
"type" : "CREATURE_SPELL_POWER",
"val" : 100
},
"canCast" :
{
"type" : "SPELLCASTER",
"subtype" : "spell.shield",
"val" : 3
}
},
"graphics" : "graphics" :
{ {
"animation": "ZM175NPC.DEF", "animation": "ZM175NPC.DEF",
@ -488,7 +546,7 @@
"projectile": "CPRZEAX.DEF" "projectile": "CPRZEAX.DEF"
} }
}, },
"sounds" : "sound" :
{ {
"attack": "MONKATTK.wav", "attack": "MONKATTK.wav",
"defend": "MONKDFND.wav", "defend": "MONKDFND.wav",
@ -504,11 +562,35 @@
"id": 176, "id": 176,
"level": 0, "level": 0,
"faction": "neutral", "faction": "neutral",
"abilities": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ], "abilities":
[ "CASTS", 1, 0, 0 ] , {
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] , "magicResistance" :
[ "CREATURE_SPELL_POWER", 100, 0, 0 ] , {
[ "SPELLCASTER", 3, "spell.precision", 0 ] ], //expert precision "type" : "MAGIC_RESISTANCE",
"val" : 5
},
"castsAmount" :
{
"type" : "CASTS",
"val" : 1
},
"enchant" :
{
"type" : "CREATURE_ENCHANT_POWER",
"val" : 1
},
"spellpower" :
{
"type" : "CREATURE_SPELL_POWER",
"val" : 100
},
"canCast" :
{
"type" : "SPELLCASTER",
"subtype" : "spell.precision",
"val" : 3
}
},
"graphics" : "graphics" :
{ {
"animation": "ZM176NPC.DEF", "animation": "ZM176NPC.DEF",
@ -517,15 +599,14 @@
"projectile": "PLCBOWX.DEF" "projectile": "PLCBOWX.DEF"
} }
}, },
"sounds" : "sound" :
{ {
"attack": "LICHATTK.wav", "attack": "LICHATTK.wav",
"defend": "LICHDFND.wav", "defend": "LICHDFND.wav",
"killed": "LICHKILL.wav", "killed": "LICHKILL.wav",
"move": "LICHMOVE.wav", "move": "LICHMOVE.wav",
"shoot": "LICHSHOT.wav", "shoot": "LICHSHOT.wav",
"wince": "LICHWNCE.wav", "wince": "LICHWNCE.wav"
"ext1": "LICHATK2.wav"
} }
}, },
"succubus1" : "succubus1" :
@ -534,11 +615,35 @@
"id": 177, "id": 177,
"level": 0, "level": 0,
"faction": "neutral", "faction": "neutral",
"abilities": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ], "abilities":
[ "CASTS", 1, 0, 0 ] , {
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] , "magicResistance" :
[ "CREATURE_SPELL_POWER", 100, 0, 0 ] , {
[ "SPELLCASTER", 3, "spell.fireShield", 0 ] ], //expert fire shield "type" : "MAGIC_RESISTANCE",
"val" : 5
},
"castsAmount" :
{
"type" : "CASTS",
"val" : 1
},
"enchant" :
{
"type" : "CREATURE_ENCHANT_POWER",
"val" : 1
},
"spellpower" :
{
"type" : "CREATURE_SPELL_POWER",
"val" : 100
},
"canCast" :
{
"type" : "SPELLCASTER",
"subtype" : "spell.fireShield",
"val" : 3
}
},
"graphics" : "graphics" :
{ {
"animation": "ZM177NPC.DEF", "animation": "ZM177NPC.DEF",
@ -547,7 +652,7 @@
"projectile": "PLCBOWX.DEF" "projectile": "PLCBOWX.DEF"
} }
}, },
"sounds" : "sound" :
{ {
"attack": "SGRGATTK.wav", "attack": "SGRGATTK.wav",
"defend": "SGRGDFND.wav", "defend": "SGRGDFND.wav",
@ -562,11 +667,35 @@
"id": 178, "id": 178,
"level": 0, "level": 0,
"faction": "neutral", "faction": "neutral",
"abilities": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ], "abilities":
[ "CASTS", 1, 0, 0 ] , {
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] , "magicResistance" :
[ "CREATURE_SPELL_POWER", 100, 0, 0 ] , {
[ "SPELLCASTER", 3, "spell.animateDead", 0 ] ], //expert animate dead "type" : "MAGIC_RESISTANCE",
"val" : 5
},
"castsAmount" :
{
"type" : "CASTS",
"val" : 1
},
"enchant" :
{
"type" : "CREATURE_ENCHANT_POWER",
"val" : 1
},
"spellpower" :
{
"type" : "CREATURE_SPELL_POWER",
"val" : 100
},
"canCast" :
{
"type" : "SPELLCASTER",
"subtype" : "spell.animateDead",
"val" : 3
}
},
"graphics" : "graphics" :
{ {
"animation": "ZM178NPC.DEF", "animation": "ZM178NPC.DEF",
@ -575,7 +704,7 @@
"projectile": "PLCBOWX.DEF" "projectile": "PLCBOWX.DEF"
} }
}, },
"sounds" : "sound" :
{ {
"attack": "GNOLATTK.wav", "attack": "GNOLATTK.wav",
"defend": "GNOLDFND.wav", "defend": "GNOLDFND.wav",
@ -590,11 +719,35 @@
"id": 179, "id": 179,
"level": 0, "level": 0,
"faction": "neutral", "faction": "neutral",
"abilities": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ], "abilities":
[ "CASTS", 1, 0, 0 ] , {
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] , "magicResistance" :
[ "CREATURE_SPELL_POWER", 100, 0, 0 ] , {
[ "SPELLCASTER", 3, "spell.stoneSkin", 0 ] ], //expert stone skin "type" : "MAGIC_RESISTANCE",
"val" : 5
},
"castsAmount" :
{
"type" : "CASTS",
"val" : 1
},
"enchant" :
{
"type" : "CREATURE_ENCHANT_POWER",
"val" : 1
},
"spellpower" :
{
"type" : "CREATURE_SPELL_POWER",
"val" : 100
},
"canCast" :
{
"type" : "SPELLCASTER",
"subtype" : "spell.stoneSkin",
"val" : 3
}
},
"graphics" : "graphics" :
{ {
"animation": "ZM179NPC.DEF", "animation": "ZM179NPC.DEF",
@ -603,7 +756,7 @@
"projectile": "PLCBOWX.DEF" "projectile": "PLCBOWX.DEF"
} }
}, },
"sounds" : "sound" :
{ {
"attack": "PFOEATTK.wav", "attack": "PFOEATTK.wav",
"defend": "PFOEDFND.wav", "defend": "PFOEDFND.wav",
@ -618,11 +771,35 @@
"id": 180, "id": 180,
"level": 0, "level": 0,
"faction": "neutral", "faction": "neutral",
"abilities": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ], "abilities":
[ "CASTS", 1, 0, 0 ] , {
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] , "magicResistance" :
[ "CREATURE_SPELL_POWER", 100, 0, 0 ] , {
[ "SPELLCASTER", 3, "spell.cure", 0 ] ], //expert cure "type" : "MAGIC_RESISTANCE",
"val" : 5
},
"castsAmount" :
{
"type" : "CASTS",
"val" : 1
},
"enchant" :
{
"type" : "CREATURE_ENCHANT_POWER",
"val" : 1
},
"spellpower" :
{
"type" : "CREATURE_SPELL_POWER",
"val" : 100
},
"canCast" :
{
"type" : "SPELLCASTER",
"subtype" : "spell.cure",
"val" : 3
}
},
"graphics" : "graphics" :
{ {
"animation": "ZM180NPC.DEF", "animation": "ZM180NPC.DEF",
@ -631,7 +808,7 @@
"projectile": "PLCBOWX.DEF" "projectile": "PLCBOWX.DEF"
} }
}, },
"sounds" : "sound" :
{ {
"attack": "TRLLATTK.wav", "attack": "TRLLATTK.wav",
"defend": "TRLLDFND.wav", "defend": "TRLLDFND.wav",
@ -646,11 +823,35 @@
"id": 181, "id": 181,
"level": 0, "level": 0,
"faction": "neutral", "faction": "neutral",
"abilities": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ], "abilities":
[ "CASTS", 1, 0, 0 ] , {
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] , "magicResistance" :
[ "CREATURE_SPELL_POWER", 100, 0, 0 ] , {
[ "SPELLCASTER", 3, "spell.haste", 0 ] ], //expert haste "type" : "MAGIC_RESISTANCE",
"val" : 5
},
"castsAmount" :
{
"type" : "CASTS",
"val" : 1
},
"enchant" :
{
"type" : "CREATURE_ENCHANT_POWER",
"val" : 1
},
"spellpower" :
{
"type" : "CREATURE_SPELL_POWER",
"val" : 100
},
"canCast" :
{
"type" : "SPELLCASTER",
"subtype" : "spell.haste",
"val" : 3
}
},
"graphics" : "graphics" :
{ {
"animation": "ZM181NPC.DEF", "animation": "ZM181NPC.DEF",
@ -659,7 +860,7 @@
"projectile": "PLCBOWX.DEF" "projectile": "PLCBOWX.DEF"
} }
}, },
"sounds" : "sound" :
{ {
"attack": "AMAGATTK.wav", "attack": "AMAGATTK.wav",
"defend": "AMAGDFND.wav", "defend": "AMAGDFND.wav",
@ -675,11 +876,35 @@
"id": 182, "id": 182,
"level": 0, "level": 0,
"faction": "neutral", "faction": "neutral",
"abilities": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ], "abilities":
[ "CASTS", 1, 0, 0 ] , {
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] , "magicResistance" :
[ "CREATURE_SPELL_POWER", 100, 0, 0 ] , {
[ "SPELLCASTER", 3, "spell.counterstrike", 0 ] ], //expert counterstrike "type" : "MAGIC_RESISTANCE",
"val" : 5
},
"castsAmount" :
{
"type" : "CASTS",
"val" : 1
},
"enchant" :
{
"type" : "CREATURE_ENCHANT_POWER",
"val" : 1
},
"spellpower" :
{
"type" : "CREATURE_SPELL_POWER",
"val" : 100
},
"canCast" :
{
"type" : "SPELLCASTER",
"subtype" : "spell.counterstrike",
"val" : 3
}
},
"graphics" : "graphics" :
{ {
"animation": "ZM182NPC.DEF", "animation": "ZM182NPC.DEF",
@ -688,7 +913,7 @@
"projectile": "PLCBOWX.DEF" "projectile": "PLCBOWX.DEF"
} }
}, },
"sounds" : "sound" :
{ {
"attack": "GENIATTK.wav", "attack": "GENIATTK.wav",
"defend": "GENIDFND.wav", "defend": "GENIDFND.wav",
@ -705,95 +930,139 @@
"faction": "neutral", "faction": "neutral",
"graphics" : "graphics" :
{ {
"animation": "ZM174NPC.DEF" "animation": "ZM174NPC.DEF",
"missile" :
{
"projectile": "PLCBOWX.DEF"
}
} }
}, },
"hierophant2" : "hierophant2" :
{ {
"special" : true, "special" : true,
"disabled" : true,
"id": 184, "id": 184,
"level": 0, "level": 0,
"faction": "neutral", "faction": "neutral",
"graphics" : "graphics" :
{ {
"animation": "ZM175NPC.DEF" "animation": "ZM175NPC.DEF",
"missile" :
{
"projectile": "CPRZEAX.DEF"
}
} }
}, },
"templeGuardian2" : "templeGuardian2" :
{ {
"special" : true, "special" : true,
"disabled" : true,
"id": 185, "id": 185,
"level": 0, "level": 0,
"faction": "neutral", "faction": "neutral",
"graphics" : "graphics" :
{ {
"animation": "ZM176NPC.DEF" "animation": "ZM176NPC.DEF",
"missile" :
{
"projectile": "PLCBOWX.DEF"
}
} }
}, },
"succubus2" : "succubus2" :
{ {
"special" : true, "special" : true,
"disabled" : true,
"id": 186, "id": 186,
"level": 0, "level": 0,
"faction": "neutral", "faction": "neutral",
"graphics" : "graphics" :
{ {
"animation": "ZM177NPC.DEF" "animation": "ZM177NPC.DEF",
"missile" :
{
"projectile": "PLCBOWX.DEF"
}
} }
}, },
"soulEater2" : "soulEater2" :
{ {
"special" : true, "special" : true,
"disabled" : true,
"id": 187, "id": 187,
"level": 0, "level": 0,
"faction": "neutral", "faction": "neutral",
"graphics" : "graphics" :
{ {
"animation": "ZM178NPC.DEF" "animation": "ZM178NPC.DEF",
"missile" :
{
"projectile": "PLCBOWX.DEF"
}
} }
}, },
"brute2" : "brute2" :
{ {
"special" : true, "special" : true,
"disabled" : true,
"id": 188, "id": 188,
"level": 0, "level": 0,
"faction": "neutral", "faction": "neutral",
"graphics" : "graphics" :
{ {
"animation": "ZM179NPC.DEF" "animation": "ZM179NPC.DEF",
"missile" :
{
"projectile": "PLCBOWX.DEF"
}
} }
}, },
"ogreLeader2" : "ogreLeader2" :
{ {
"special" : true, "special" : true,
"disabled" : true,
"id": 189, "id": 189,
"level": 0, "level": 0,
"faction": "neutral", "faction": "neutral",
"graphics" : "graphics" :
{ {
"animation": "ZM180NPC.DEF" "animation": "ZM180NPC.DEF",
"missile" :
{
"projectile": "PLCBOWX.DEF"
}
} }
}, },
"shaman2" : "shaman2" :
{ {
"special" : true, "special" : true,
"disabled" : true,
"id": 190, "id": 190,
"level": 0, "level": 0,
"faction": "neutral", "faction": "neutral",
"graphics" : "graphics" :
{ {
"animation": "ZM181NPC.DEF" "animation": "ZM181NPC.DEF",
"missile" :
{
"projectile": "PLCBOWX.DEF"
}
} }
}, },
"astralSpirit2" : "astralSpirit2" :
{ {
"special" : true, "special" : true,
"disabled" : true,
"id": 191, "id": 191,
"level": 0, "level": 0,
"faction": "neutral", "faction": "neutral",
"graphics" : "graphics" :
{ {
"animation": "ZM182NPC.DEF" "animation": "ZM182NPC.DEF",
"missile" :
{
"projectile": "PLCBOWX.DEF"
}
} }
}, },
"sylvanCentaur" : "sylvanCentaur" :
@ -806,8 +1075,7 @@
"animation": "ZM192Z.DEF", "animation": "ZM192Z.DEF",
"missile" : "missile" :
{ {
"projectile": "PELFX.DEF", "projectile": "PELFX.DEF"
"spinning": true
} }
}, },
"sound" : "sound" :
@ -830,8 +1098,7 @@
"animation": "ZM193Z.DEF", "animation": "ZM193Z.DEF",
"missile" : "missile" :
{ {
"projectile": "CPRZEAX.DEF", "projectile": "CPRZEAX.DEF"
"spinning": false
} }
}, },
"sound" : "sound" :
@ -878,20 +1145,40 @@
"id": 196, "id": 196,
"level": 10, "level": 10,
"faction": "neutral", "faction": "neutral",
"abilities": [ [ "DRAGON_NATURE", 0, 0, 0 ], "abilities":
[ "TWO_HEX_ATTACK_BREATH", 0, 0, 0 ], {
[ "DRAGON_NATURE", 0, 0, 0 ], "dragon" :
[ "UNDEAD", 0, 0, 0 ], {
[ "FLYING", 0, 0, 0 ], "type" : "DRAGON_NATURE",
[ "SPELL_LIKE_ATTACK", 0, "spell.deathCloud", 0 ], },
[ "SHOOTER", 0, 0, 0 ] ], "dragonBreath" :
{
"type" : "TWO_HEX_ATTACK_BREATH"
},
"undead" :
{
"type" : "UNDEAD"
},
"canFly" :
{
"type" : "FLYING"
},
"deathCloud" :
{
"type" : "SPELL_LIKE_ATTACK",
"subtype" : "spell.deathCloud"
},
"canShoot" :
{
"type" : "SHOOTER"
}
},
"graphics" : "graphics" :
{ {
"animation": "ZM196Z.DEF", "animation": "ZM196Z.DEF",
"missile" : "missile" :
{ {
"projectile": "ZSHOT195.DEF", "projectile": "ZSHOT195.DEF"
"spinning": false
} }
}, },
"sound" : "sound" :

View File

@ -1,6 +1,7 @@
{ {
"neutral" : "neutral" :
{ {
"name" : "Neutral",
"index" : 9, "index" : 9,
"alignment" : "neutral", "alignment" : "neutral",
"creatureBackground" : "creatureBackground" :

View File

@ -4,6 +4,24 @@
"title" : "VCMI artifact format", "title" : "VCMI artifact format",
"description" : "Format used to define new artifacts in VCMI", "description" : "Format used to define new artifacts in VCMI",
"required" : [ "class", "graphics", "text", "type", "value" ], "required" : [ "class", "graphics", "text", "type", "value" ],
"definitions" : {
"growingBonusList" : {
"type" : "array",
"items" : {
"type" : "object",
"additionalProperties" : false,
"properties" : {
"level" : {
"type" : "number"
},
"bonus" : { "$ref" : "vcmi:bonus" }
}
}
}
},
"additionalProperties" : false,
"properties":{ "properties":{
"bonuses": { "bonuses": {
"type":"array", "type":"array",
@ -15,6 +33,10 @@
"enum" : [ "SPECIAL", "TREASURE", "MINOR", "MAJOR", "RELIC" ], "enum" : [ "SPECIAL", "TREASURE", "MINOR", "MAJOR", "RELIC" ],
"description": "Artifact class, treasure, minor, major or relic" "description": "Artifact class, treasure, minor, major or relic"
}, },
"id" : {
"type" : "number",
"description" : "Private field to break things, do not use."
},
"components": { "components": {
"type":"array", "type":"array",
"description": "Optional, list of components for combinational artifacts", "description": "Optional, list of components for combinational artifacts",
@ -22,8 +44,10 @@
}, },
"graphics": { "graphics": {
"type":"object", "type":"object",
"additionalProperties" : false,
"description": "Graphical files associated with the artifact", "description": "Graphical files associated with the artifact",
"required" : [ "iconIndex", "image", "map" ], //"required" : [ "iconIndex", "image", "map" ],
"required" : [ "iconIndex" ],
"properties":{ "properties":{
"iconIndex": { "iconIndex": {
"type":"number", "type":"number",
@ -43,12 +67,30 @@
} }
} }
}, },
"growing" : {
"type" : "object",
"additionalProperties" : false,
"properties" : {
"bonusesPerLevel" : { "$ref" : "#/definitions/growingBonusList"},
"thresholdBonuses" : { "$ref" : "#/definitions/growingBonusList"}
}
},
"slot": { "slot": {
"type":"string", "description": "Slot to which this artifact can be put, if applicable",
"description": "Slot to which this artifact can be put, if applicable" "oneOf" : [
{
"type":"string"
},
{
"type" : "array",
"minItems" : 1,
"additionalItems" : { "type" : "string" }
}
]
}, },
"text": { "text": {
"type":"object", "type":"object",
"additionalProperties" : false,
"description": "Texts associated with artifact", "description": "Texts associated with artifact",
"required" : [ "description", "event", "name" ], "required" : [ "description", "event", "name" ],
"properties":{ "properties":{

View File

@ -4,6 +4,8 @@
"title" : "VCMI bonus system format", "title" : "VCMI bonus system format",
"description" : "Subsection of several formats, used to add generic bonuses to objects", "description" : "Subsection of several formats, used to add generic bonuses to objects",
"required": ["type"], "required": ["type"],
"additionalProperties" : false,
"properties":{ "properties":{
"addInfo": { "addInfo": {
"anyOf" : [ "anyOf" : [
@ -28,7 +30,10 @@
"type":"array", "type":"array",
"description": "limiters", "description": "limiters",
"items": { "items": {
"oneOf" : [
{
"type":"object", "type":"object",
"additionalProperties" : false,
"properties" : { "properties" : {
"parameters": { "parameters": {
"type":"array", "type":"array",
@ -40,6 +45,11 @@
"description": "type", "description": "type",
} }
} }
},
{
"type" : "string"
}
]
} }
}, },
"propagator": { "propagator": {

View File

@ -3,14 +3,25 @@
"$schema": "http://json-schema.org/draft-04/schema", "$schema": "http://json-schema.org/draft-04/schema",
"title" : "VCMI creature format", "title" : "VCMI creature format",
"description": "Json format for defining new creatures in VCMI", "description": "Json format for defining new creatures in VCMI",
"required" : [ "faction" ],
"anyOf" : [
{
"disabled" : { "enum" : [ true ] }
},
{
"required" : [ "required" : [
"name", "faction", "cost", "level", "fightValue", "aiValue", "name", "cost", "level", "fightValue", "aiValue",
"attack", "defense", "hitPoints", "speed", "damage", "advMapAmount", "attack", "defense", "hitPoints", "speed", "damage", "advMapAmount",
"graphics", "sound" "graphics", "sound"
]
}
], ],
"additionalProperties" : false,
"properties":{ "properties":{
"name": { "name": {
"type":"object", "type":"object",
"additionalProperties" : false,
"description": "Translatable names for this creature", "description": "Translatable names for this creature",
"required" : [ "singular", "plural" ], "required" : [ "singular", "plural" ],
"properties":{ "properties":{
@ -24,12 +35,26 @@
} }
} }
}, },
"abilityText" : {
"type" : "string",
"description" : "Text version of creature abilities. Used only with original creature window"
},
"id" : {
"type" : "number",
"description" : "Private field to break things, do not use."
},
"extraNames" : {
"type" : "array",
"items" : { "type" : "string" },
"description" : "Private field to break things, do not use."
},
"faction": { "faction": {
"type":"string", "type":"string",
"description": "Faction this creature belongs to. Examples: castle, rampart" "description": "Faction this creature belongs to. Examples: castle, rampart"
}, },
"cost": { "cost": {
"type":"object", "type":"object",
"additionalProperties" : false,
"description": "Cost to recruit this creature", "description": "Cost to recruit this creature",
"properties":{ "properties":{
"wood": { "type":"number"}, "wood": { "type":"number"},
@ -45,6 +70,10 @@
"type":"boolean", "type":"boolean",
"description": "Marks this object as special and not available by default" "description": "Marks this object as special and not available by default"
}, },
"disabled": {
"type":"boolean",
"description": "Object is competely disabled and may not be even loaded in-game"
},
"level": { "type":"number"}, "level": { "type":"number"},
"fightValue": { "fightValue": {
"type":"number", "type":"number",
@ -70,6 +99,7 @@
"damage": { "damage": {
"type":"object", "type":"object",
"additionalProperties" : false,
"properties":{ "properties":{
"max": { "type":"number" }, "max": { "type":"number" },
"min": { "type":"number" } "min": { "type":"number" }
@ -81,6 +111,7 @@
}, },
"advMapAmount": { "advMapAmount": {
"type":"object", "type":"object",
"additionalProperties" : false,
"description" : "Initial size of random stacks on adventure map", "description" : "Initial size of random stacks on adventure map",
"properties":{ "properties":{
"min": { "type":"number" }, "min": { "type":"number" },
@ -101,15 +132,18 @@
"description": "creature may receive \"week of\" events" "description": "creature may receive \"week of\" events"
}, },
"abilities": { "abilities": {
"type":"array",
"description": "Creature abilities described using Bonus system", "description": "Creature abilities described using Bonus system",
"items": { "$ref" : "vcmi:bonus" } "type":"object",
"additionalProperties": {
"$ref" : "vcmi:bonus"
}
}, },
"stackExperience": { "stackExperience": {
"type":"array", "type":"array",
"description": "Stack experience, using bonus system", "description": "Stack experience, using bonus system",
"items":{ "items":{
"type":"object", "type":"object",
"additionalProperties" : false,
"required" : [ "bonus", "values" ], "required" : [ "bonus", "values" ],
"description": "0", "description": "0",
"properties":{ "properties":{
@ -119,7 +153,6 @@
"minItems" : 10, "minItems" : 10,
"maxItems" : 10, "maxItems" : 10,
"description": "Strength of the bonus", "description": "Strength of the bonus",
"additionalItems" : true,
"anyof" : [ "anyof" : [
{ "items": { "type" : "number" } }, { "items": { "type" : "number" } },
{ "items": { "type" : "boolean" } } { "items": { "type" : "boolean" } }
@ -130,14 +163,16 @@
}, },
"graphics": { "graphics": {
"type":"object", "type":"object",
"additionalProperties" : false,
"description": "Describes how this creature looks like during battles", "description": "Describes how this creature looks like during battles",
"required" : [ "required" : [
"animationTime", "iconLarge", "iconSmall", "iconIndex", "animationTime", "iconIndex",
"map", "animation", "attackClimaxFrame", "timeBetweenFidgets" "map", "animation", "timeBetweenFidgets"
], ],
"properties":{ "properties":{
"animationTime": { "animationTime": {
"type":"object", "type":"object",
"additionalProperties" : false,
"required" : [ "attack", "flight", "walk" ], "required" : [ "attack", "flight", "walk" ],
"description": "Length of several animations", "description": "Length of several animations",
"properties":{ "properties":{
@ -176,13 +211,10 @@
"type":"string", "type":"string",
"description": ".def file with animation of this creature in battles" "description": ".def file with animation of this creature in battles"
}, },
"attackClimaxFrame": {
"type":"number",
"description": "Frame from attack animation during which creature deals damage"
},
"missile": { "missile": {
"type":"object", "type":"object",
"required" : [ "projectile", "frameAngles", "offset" ], "additionalProperties" : false,
"required" : [ "projectile", "frameAngles", "offset", "attackClimaxFrame" ],
"description": "Missile description for archers", "description": "Missile description for archers",
"properties":{ "properties":{
"projectile": { "projectile": {
@ -201,6 +233,7 @@
}, },
"offset": { "offset": {
"type":"object", "type":"object",
"additionalProperties" : false,
"required" : [ "lowerX", "lowerY", "middleX", "middleY", "upperX", "upperY" ], "required" : [ "lowerX", "lowerY", "middleX", "middleY", "upperX", "upperY" ],
"description": "Position where projectile image appears during shooting in specific direction", "description": "Position where projectile image appears during shooting in specific direction",
"properties":{ "properties":{
@ -211,6 +244,10 @@
"upperX": { "type":"number" }, "upperX": { "type":"number" },
"upperY": { "type":"number" } "upperY": { "type":"number" }
} }
},
"attackClimaxFrame": {
"type":"number",
"description": "Frame from attack animation during which creature deals damage"
} }
} }
}, },
@ -226,18 +263,17 @@
}, },
"sound": { "sound": {
"type":"object", "type":"object",
"additionalProperties" : false,
"description": "Various sound files associated with this creature", "description": "Various sound files associated with this creature",
"properties":{ "properties":{
"attack": { "type":"string" }, "attack": { "type":"string" },
"defend": { "type":"string" }, "defend": { "type":"string" },
"killed": { "type":"string" }, "killed": { "type":"string" },
"moveEnd": { "type":"string" }, "startMoving": { "type":"string" },
"moveStart": { "type":"string" }, "endMoving": { "type":"string" },
"move": { "type":"string" }, "move": { "type":"string" },
"shoot": { "type":"string" }, "shoot": { "type":"string" },
"wince": { "type":"string" }, "wince": { "type":"string" }
"ext1": { "type":"string" },
"ext2": { "type":"string" }
} }
} }
} }

View File

@ -7,11 +7,17 @@
"dependencies" : { "dependencies" : {
"town" : [ "puzzleMap", "commander" ] "town" : [ "puzzleMap", "commander" ]
}, },
"additionalProperties" : false,
"properties":{ "properties":{
"name" : { "name" : {
"type" : "string", "type" : "string",
"description" : "Translatable name of town" "description" : "Translatable name of town"
}, },
"index" : {
"type" : "number",
"description" : "Private field to break things, do not use."
},
"alignment": { "alignment": {
"type":"string", "type":"string",
"enum" : [ "good", "neutral", "evil" ], "enum" : [ "good", "neutral", "evil" ],
@ -23,6 +29,7 @@
}, },
"creatureBackground": { "creatureBackground": {
"type":"object", "type":"object",
"additionalProperties" : false,
"required" : [ "120px", "130px" ], "required" : [ "120px", "130px" ],
"description": "Backgrounds for creature info card", "description": "Backgrounds for creature info card",
"properties":{ "properties":{
@ -42,6 +49,7 @@
}, },
"puzzleMap": { "puzzleMap": {
"type":"object", "type":"object",
"additionalProperties" : false,
"required" : [ "prefix", "pieces" ], "required" : [ "prefix", "pieces" ],
"description": "Puzzle map from obelisks for this town. Must contain 48 pieces", "description": "Puzzle map from obelisks for this town. Must contain 48 pieces",
"properties":{ "properties":{
@ -52,6 +60,7 @@
"maxItems" : 48, "maxItems" : 48,
"items": { "items": {
"type":"object", "type":"object",
"additionalProperties" : false,
"properties":{ "properties":{
"index": { "type":"number", "description" : "Order in which images will be opened" }, "index": { "type":"number", "description" : "Order in which images will be opened" },
"x": { "type":"number", "description" : "X coordinate on screen" }, "x": { "type":"number", "description" : "X coordinate on screen" },
@ -67,15 +76,17 @@
}, },
"town": { "town": {
"type":"object", "type":"object",
"additionalProperties" : false,
"required" : [ "required" : [
"adventureMap", "buildingsIcons", "buildings", "creatures", "guildWindow", "names", "adventureMap", "buildingsIcons", "buildings", "creatures", "guildWindow", "names",
"hallBackground", "hallSlots", "horde", "icons", "mageGuild", "moatDamage", "hallBackground", "hallSlots", "horde", "icons", "mageGuild", "moatDamage",
"musicTheme", "siege", "structures", "townBackground", "warMachine", "primaryResource" "musicTheme", "siege", "structures", "townBackground", "warMachine"
], ],
"description": "town", "description": "town",
"properties":{ "properties":{
"adventureMap": { "adventureMap": {
"type":"object", "type":"object",
"additionalProperties" : false,
"description": "Paths to images of object on adventure map", "description": "Paths to images of object on adventure map",
"required" : [ "capitol", "castle", "village" ], "required" : [ "capitol", "castle", "village" ],
"properties":{ "properties":{
@ -96,6 +107,7 @@
"description" : "Dwellings on adventure map", "description" : "Dwellings on adventure map",
"items" : { "items" : {
"type" : "object", "type" : "object",
"additionalProperties" : false,
"properties" : { "properties" : {
"name": { "type":"string" }, "name": { "type":"string" },
"graphics": { "type":"string" } "graphics": { "type":"string" }
@ -176,11 +188,13 @@
}, },
"icons": { "icons": {
"type":"object", "type":"object",
"additionalProperties" : false,
"description": "Town icons", "description": "Town icons",
"required" : [ "fort", "village" ], "required" : [ "fort", "village" ],
"properties":{ "properties":{
"fort": { "fort": {
"type":"object", "type":"object",
"additionalProperties" : false,
"required" : [ "normal", "built" ], "required" : [ "normal", "built" ],
"description": "Icons for town with built fort", "description": "Icons for town with built fort",
"properties":{ "properties":{
@ -196,6 +210,7 @@
}, },
"village": { "village": {
"type":"object", "type":"object",
"additionalProperties" : false,
"required" : [ "normal", "built" ], "required" : [ "normal", "built" ],
"description": "Icons for town without fort", "description": "Icons for town without fort",
"properties":{ "properties":{

View File

@ -4,6 +4,8 @@
"title" : "VCMI hero format", "title" : "VCMI hero format",
"description" : "Format used to define new heroes in VCMI", "description" : "Format used to define new heroes in VCMI",
"required": [ "army", "class", "images", "skills", "texts" ], "required": [ "army", "class", "images", "skills", "texts" ],
"additionalProperties" : false,
"properties":{ "properties":{
"army": { "army": {
"type":"array", "type":"array",
@ -12,6 +14,7 @@
"maxItems" : 3, "maxItems" : 3,
"items": { "items": {
"type":"object", "type":"object",
"additionalProperties" : false,
"required" : [ "creature", "min", "max" ], "required" : [ "creature", "min", "max" ],
"properties":{ "properties":{
"creature": { "creature": {
@ -29,6 +32,10 @@
} }
} }
}, },
"id" : {
"type" : "number",
"description" : "Private field to break things, do not use."
},
"special": { "special": {
"type":"boolean", "type":"boolean",
"description": "Marks this object as special and not available by default" "description": "Marks this object as special and not available by default"
@ -43,8 +50,9 @@
}, },
"images": { "images": {
"type":"object", "type":"object",
"additionalProperties" : false,
"description": "images", "description": "images",
"required": [ "index", "large", "small", "specialtyLarge", "specialtySmall" ], "required": [ "index" ],
"properties":{ "properties":{
"index": { "index": {
"type":"number", "type":"number",
@ -74,6 +82,7 @@
"maxItems" : 8, "maxItems" : 8,
"items": { "items": {
"type":"object", "type":"object",
"additionalProperties" : false,
"required" : [ "level", "skill" ], "required" : [ "level", "skill" ],
"properties":{ "properties":{
"level": { "level": {
@ -88,11 +97,18 @@
} }
} }
}, },
"specialties" :
{
"type" : "array",
"description" : "Specialty format used for OH3 heroes. Use \"specialty\" instead",
"additionalItems" : true
},
"specialty": { "specialty": {
"type":"array", "type":"array",
"description": "Description of hero specialty using bonus system", "description": "Description of hero specialty using bonus system",
"items": { "items": {
"type":"object", "type":"object",
"additionalProperties" : false,
"required" : [ "bonuses" ], "required" : [ "bonuses" ],
"properties":{ "properties":{
"growsWithLevel" : { "growsWithLevel" : {
@ -114,6 +130,7 @@
}, },
"texts": { "texts": {
"type":"object", "type":"object",
"additionalProperties" : false,
"description": "All translatable texts related to hero", "description": "All translatable texts related to hero",
"required" : [ "biography", "name", "specialty" ], "required" : [ "biography", "name", "specialty" ],
"properties":{ "properties":{
@ -127,6 +144,7 @@
}, },
"specialty": { "specialty": {
"type":"object", "type":"object",
"additionalProperties" : false,
"description": "Hero specialty information", "description": "Hero specialty information",
"required" : [ "description", "name", "tooltip" ], "required" : [ "description", "name", "tooltip" ],
"properties":{ "properties":{

View File

@ -7,14 +7,18 @@
"animation", "faction", "highLevelChance", "lowLevelChance", "animation", "faction", "highLevelChance", "lowLevelChance",
"name", "primarySkills", "secondarySkills", "tavern" "name", "primarySkills", "secondarySkills", "tavern"
], ],
"additionalProperties" : false,
"properties":{ "properties":{
"animation": { "animation": {
"type":"object", "type":"object",
"additionalProperties" : false,
"description": "Files related to hero animation", "description": "Files related to hero animation",
"required": [ "battle", "map" ], "required": [ "battle", "map" ],
"properties":{ "properties":{
"battle": { "battle": {
"type":"object", "type":"object",
"additionalProperties" : false,
"description": "Hero animations for battle", "description": "Hero animations for battle",
"required": [ "female", "male" ], "required": [ "female", "male" ],
"properties":{ "properties":{
@ -30,6 +34,7 @@
}, },
"map": { "map": {
"type":"object", "type":"object",
"additionalProperties" : false,
"description": "Hero animations for adventure map", "description": "Hero animations for adventure map",
"required": [ "female", "male" ], "required": [ "female", "male" ],
"properties":{ "properties":{
@ -45,6 +50,10 @@
} }
} }
}, },
"id" : {
"type" : "number",
"description" : "Private field to break things, do not use."
},
"faction": { "faction": {
"type":"string", "type":"string",
"description": "Faction this hero class belongs to" "description": "Faction this hero class belongs to"

View File

@ -4,8 +4,9 @@
"title" : "VCMI mod file format", "title" : "VCMI mod file format",
"description" : "Format used to define main mod file (mod.json) in VCMI", "description" : "Format used to define main mod file (mod.json) in VCMI",
"required" : [ "name", "description" ], "required" : [ "name", "description" ],
"properties":{
"additionalProperties" : false,
"properties":{
"name": { "name": {
"type":"string", "type":"string",
"description": "Short name of your mod. No more than 2-3 words" "description": "Short name of your mod. No more than 2-3 words"
@ -60,6 +61,7 @@
"description" : "list of data sources attached to this mount point", "description" : "list of data sources attached to this mount point",
"items": { "items": {
"type":"object", "type":"object",
"additionalProperties" : false,
"properties":{ "properties":{
"path": { "path": {
"type":"string", "type":"string",

View File

@ -10,11 +10,13 @@
"enum" : [ "trace", "debug", "info", "warn", "error" ] "enum" : [ "trace", "debug", "info", "warn", "error" ]
} }
}, },
"additionalProperties" : false,
"properties": "properties":
{ {
"general" : { "general" : {
"type" : "object", "type" : "object",
"default": {}, "default": {},
"additionalProperties" : false,
"required" : [ "classicCreatureWindow", "playerName", "showfps", "music", "sound" ], "required" : [ "classicCreatureWindow", "playerName", "showfps", "music", "sound" ],
"properties" : { "properties" : {
"classicCreatureWindow" : { "classicCreatureWindow" : {
@ -41,11 +43,13 @@
}, },
"video" : { "video" : {
"type" : "object", "type" : "object",
"additionalProperties" : false,
"default": {}, "default": {},
"required" : [ "screenRes", "bitsPerPixel", "fullscreen" ], "required" : [ "screenRes", "bitsPerPixel", "fullscreen" ],
"properties" : { "properties" : {
"screenRes" : { "screenRes" : {
"type" : "object", "type" : "object",
"additionalProperties" : false,
"required" : [ "width", "height" ], "required" : [ "width", "height" ],
"properties" : { "properties" : {
"width" : { "type" : "number" }, "width" : { "type" : "number" },
@ -65,6 +69,7 @@
}, },
"adventure" : { "adventure" : {
"type" : "object", "type" : "object",
"additionalProperties" : false,
"default": {}, "default": {},
"required" : [ "heroSpeed", "enemySpeed", "scrollSpeed", "heroReminder" ], "required" : [ "heroSpeed", "enemySpeed", "scrollSpeed", "heroReminder" ],
"properties" : { "properties" : {
@ -88,6 +93,7 @@
}, },
"battle" : { "battle" : {
"type" : "object", "type" : "object",
"additionalProperties" : false,
"default": {}, "default": {},
"required" : [ "animationSpeed", "mouseShadow", "cellBorders", "stackRange", "showQueue" ], "required" : [ "animationSpeed", "mouseShadow", "cellBorders", "stackRange", "showQueue" ],
"properties" : { "properties" : {
@ -115,6 +121,7 @@
}, },
"server" : { "server" : {
"type" : "object", "type" : "object",
"additionalProperties" : false,
"default": {}, "default": {},
"required" : [ "server", "port", "localInformation", "playerAI", "neutralAI" ], "required" : [ "server", "port", "localInformation", "playerAI", "neutralAI" ],
"properties" : { "properties" : {
@ -142,6 +149,7 @@
}, },
"logging" : { "logging" : {
"type" : "object", "type" : "object",
"additionalProperties" : false,
"default" : {}, "default" : {},
"required" : [ "console", "file", "loggers" ], "required" : [ "console", "file", "loggers" ],
"properties" : { "properties" : {
@ -152,7 +160,7 @@
"properties" : { "properties" : {
"format" : { "format" : {
"type" : "string", "type" : "string",
"default" : "%l %n [%t] - %m" "default" : "%m"
}, },
"threshold" : { "threshold" : {
"$ref" : "#/definitions/logLevelEnum", "$ref" : "#/definitions/logLevelEnum",
@ -173,6 +181,7 @@
], ],
"items" : { "items" : {
"type" : "object", "type" : "object",
"additionalProperties" : false,
"default" : {}, "default" : {},
"required" : [ "domain", "level", "color" ], "required" : [ "domain", "level", "color" ],
"properties" : { "properties" : {
@ -186,6 +195,7 @@
}, },
"file" : { "file" : {
"type" : "object", "type" : "object",
"additionalProperties" : false,
"default" : {}, "default" : {},
"required" : [ "format" ], "required" : [ "format" ],
"properties" : { "properties" : {
@ -200,6 +210,7 @@
"default" : [ { "domain" : "global", "level" : "info" } ], "default" : [ { "domain" : "global", "level" : "info" } ],
"items" : { "items" : {
"type" : "object", "type" : "object",
"additionalProperties" : false,
"required" : [ "level", "domain" ], "required" : [ "level", "domain" ],
"properties" : { "properties" : {
"domain" : { "type" : "string" }, "domain" : { "type" : "string" },

View File

@ -1,5 +1,6 @@
{ {
"type":"object", "type":"object",
"additionalProperties" : false,
"$schema": "http://json-schema.org/draft-04/schema", "$schema": "http://json-schema.org/draft-04/schema",
"title" : "VCMI town building format", "title" : "VCMI town building format",
"description" : "Format used to define town buildings in VCMI", "description" : "Format used to define town buildings in VCMI",
@ -35,6 +36,7 @@
}, },
"cost": { "cost": {
"type":"object", "type":"object",
"additionalProperties" : false,
"description": "Cost to build this building", "description": "Cost to build this building",
"properties":{ "properties":{
"wood": { "type":"number"}, "wood": { "type":"number"},

View File

@ -1,5 +1,6 @@
{ {
"type":"object", "type":"object",
"additionalProperties" : false,
"$schema": "http://json-schema.org/draft-04/schema", "$schema": "http://json-schema.org/draft-04/schema",
"title" : "VCMI siege screen format", "title" : "VCMI siege screen format",
"description" : "Format used to define town siege screen in VCMI", "description" : "Format used to define town siege screen in VCMI",
@ -12,6 +13,7 @@
{ {
"point" : { "point" : {
"type" : "object", "type" : "object",
"additionalProperties" : false,
"required" : [ "x", "y" ], "required" : [ "x", "y" ],
"properties":{ "properties":{
"x": { "type":"number" }, "x": { "type":"number" },
@ -20,6 +22,7 @@
}, },
"tower" : { "tower" : {
"type" : "object", "type" : "object",
"additionalProperties" : false,
"required" : [ "battlement", "creature", "tower" ], "required" : [ "battlement", "creature", "tower" ],
"properties":{ "properties":{
"battlement": { "battlement": {
@ -41,6 +44,7 @@
"properties":{ "properties":{
"gate": { "gate": {
"type":"object", "type":"object",
"additionalProperties" : false,
"description" : "Town gates", "description" : "Town gates",
"properties":{ "properties":{
"arch": { "arch": {
@ -59,6 +63,7 @@
}, },
"moat": { "moat": {
"type":"object", "type":"object",
"additionalProperties" : false,
"description" : "Castle moat description", "description" : "Castle moat description",
"properties":{ "properties":{
"bank": { "bank": {
@ -81,6 +86,7 @@
}, },
"static": { "static": {
"type":"object", "type":"object",
"additionalProperties" : false,
"description" : "Static sections of walls", "description" : "Static sections of walls",
"properties":{ "properties":{
"background": { "background": {
@ -99,6 +105,7 @@
}, },
"towers": { "towers": {
"type":"object", "type":"object",
"additionalProperties" : false,
"description" : "Decription of towers", "description" : "Decription of towers",
"properties":{ "properties":{
"bottom": { "$ref" : "#/definitions/tower", "description" : "Bottom tower" }, "bottom": { "$ref" : "#/definitions/tower", "description" : "Bottom tower" },
@ -108,6 +115,7 @@
}, },
"walls": { "walls": {
"type":"object", "type":"object",
"additionalProperties" : false,
"description" : "Destructible sections of the walls", "description" : "Destructible sections of the walls",
"properties":{ "properties":{
"bottomMid": { "bottomMid": {

View File

@ -4,6 +4,7 @@
"title" : "VCMI town structures format", "title" : "VCMI town structures format",
"description" : "Format used to define structures visible on town screen in VCMI", "description" : "Format used to define structures visible on town screen in VCMI",
"required": [ "animation", "x", "y"], "required": [ "animation", "x", "y"],
"additionalProperties" : false,
"properties":{ "properties":{
"animation": { "animation": {
"type":"string", "type":"string",

View File

@ -205,6 +205,7 @@ void CArtHandler::load(bool onlyTxt)
JsonNode & artData = h3Data[numeric]; JsonNode & artData = h3Data[numeric];
JsonUtils::merge(artData, node.second); JsonUtils::merge(artData, node.second);
//JsonUtils::validate(artData, "vcmi:artifact", node.first);
artifacts[numeric] = loadArtifact(artData); artifacts[numeric] = loadArtifact(artData);
artifacts[numeric]->id = ArtifactID(numeric); artifacts[numeric]->id = ArtifactID(numeric);
@ -386,11 +387,11 @@ void CArtHandler::loadGrowingArt(CGrowingArtifact * art, const JsonNode & node)
{ {
BOOST_FOREACH (auto b, node["growing"]["bonusesPerLevel"].Vector()) BOOST_FOREACH (auto b, node["growing"]["bonusesPerLevel"].Vector())
{ {
art->bonusesPerLevel.push_back (std::pair <ui16, Bonus> (b["level"].Float(), *JsonUtils::parseBonus (b["bonus"].Vector()))); art->bonusesPerLevel.push_back (std::pair <ui16, Bonus> (b["level"].Float(), *JsonUtils::parseBonus (b["bonus"])));
} }
BOOST_FOREACH (auto b, node["growing"]["thresholdBonuses"].Vector()) BOOST_FOREACH (auto b, node["growing"]["thresholdBonuses"].Vector())
{ {
art->thresholdBonuses.push_back (std::pair <ui16, Bonus> (b["level"].Float(), *JsonUtils::parseBonus (b["bonus"].Vector()))); art->thresholdBonuses.push_back (std::pair <ui16, Bonus> (b["level"].Float(), *JsonUtils::parseBonus (b["bonus"])));
} }
} }

View File

@ -7,6 +7,7 @@
#include "CGameState.h" #include "CGameState.h"
#include "CTownHandler.h" #include "CTownHandler.h"
#include "CModHandler.h" #include "CModHandler.h"
#include "StringConstants.h"
using namespace boost::assign; using namespace boost::assign;
@ -20,24 +21,6 @@ using namespace boost::assign;
* *
*/ */
static inline void registerCreature(const std::string &name, const si32 id)
{
const std::string fullname = "creature." + name;
VLC->modh->identifiers.registerObject(fullname,id);
}
///CCreatureHandler
CCreatureHandler::CCreatureHandler()
{
VLC->creh = this;
allCreatures.setDescription("All creatures");
creaturesOfLevel[0].setDescription("Creatures of unnormalized tier");
for(int i = 1; i < ARRAY_COUNT(creaturesOfLevel); i++)
creaturesOfLevel[i].setDescription("Creatures of tier " + boost::lexical_cast<std::string>(i));
}
int CCreature::getQuantityID(const int & quantity) int CCreature::getQuantityID(const int & quantity)
{ {
if (quantity<5) if (quantity<5)
@ -182,78 +165,108 @@ static void AddAbility(CCreature *cre, const JsonVector &ability_vec)
cre->addNewBonus(nsf); cre->addNewBonus(nsf);
} }
static void RemoveAbility(CCreature *cre, const JsonNode &ability) CCreatureHandler::CCreatureHandler()
{ {
const std::string type = ability.String(); VLC->creh = this;
auto it = bonusNameMap.find(type); allCreatures.setDescription("All creatures");
creaturesOfLevel[0].setDescription("Creatures of unnormalized tier");
for(int i = 1; i < ARRAY_COUNT(creaturesOfLevel); i++)
creaturesOfLevel[i].setDescription("Creatures of tier " + boost::lexical_cast<std::string>(i));
if (it == bonusNameMap.end()) { loadCommanders();
if (type == "DOUBLE_WIDE")
cre->doubleWide = false;
else
logGlobal->errorStream() << "Error: invalid ability type " << type << " in creatures config";
return;
}
const int typeNo = it->second;
Bonus::BonusType ecf = static_cast<Bonus::BonusType>(typeNo);
Bonus *b = cre->getBonusLocalFirst(Selector::type(ecf));
cre->removeBonus(b);
} }
void CCreatureHandler::loadBonuses(CCreature & ncre, std::string bonuses) void CCreatureHandler::loadCommanders()
{ {
static const std::map<std::string,Bonus::BonusType> abilityMap = const JsonNode config(ResourceID("config/commanders.json"));
BOOST_FOREACH (auto bonus, config["bonusPerLevel"].Vector())
{
commanderLevelPremy.push_back(JsonUtils::parseBonus (bonus.Vector()));
}
int i = 0;
BOOST_FOREACH (auto skill, config["skillLevels"].Vector())
{
skillLevels.push_back (std::vector<ui8>());
BOOST_FOREACH (auto skillLevel, skill["levels"].Vector())
{
skillLevels[i].push_back (skillLevel.Float());
}
++i;
}
BOOST_FOREACH (auto ability, config["abilityRequirements"].Vector())
{
std::pair <Bonus, std::pair <ui8, ui8> > a;
a.first = *JsonUtils::parseBonus (ability["ability"].Vector());
a.second.first = ability["skills"].Vector()[0].Float();
a.second.second = ability["skills"].Vector()[1].Float();
skillRequirements.push_back (a);
}
}
void CCreatureHandler::loadBonuses(JsonNode & creature, std::string bonuses)
{
auto makeBonusNode = [&](std::string type) -> JsonNode
{
JsonNode ret;
ret["type"].String() = type;
return ret;
};
static const std::map<std::string, JsonNode> abilityMap =
boost::assign::map_list_of boost::assign::map_list_of
("FLYING_ARMY", Bonus::FLYING) ("FLYING_ARMY", makeBonusNode("FLYING"))
("SHOOTING_ARMY", Bonus::SHOOTER) ("SHOOTING_ARMY", makeBonusNode("SHOOTER"))
("SIEGE_WEAPON", Bonus::SIEGE_WEAPON) ("SIEGE_WEAPON", makeBonusNode("SIEGE_WEAPON"))
("const_free_attack", Bonus::BLOCKS_RETALIATION) ("const_free_attack", makeBonusNode("BLOCKS_RETALIATION"))
("IS_UNDEAD", Bonus::UNDEAD) ("IS_UNDEAD", makeBonusNode("UNDEAD"))
("const_no_melee_penalty",Bonus::NO_MELEE_PENALTY) ("const_no_melee_penalty", makeBonusNode("NO_MELEE_PENALTY"))
("const_jousting",Bonus::JOUSTING) ("const_jousting", makeBonusNode("JOUSTING"))
("KING_1",Bonus::KING1) ("KING_1", makeBonusNode("KING1"))
("KING_2",Bonus::KING2) ("KING_2", makeBonusNode("KING2"))
("KING_3",Bonus::KING3) ("KING_3", makeBonusNode("KING3"))
("const_no_wall_penalty",Bonus::NO_WALL_PENALTY) ("const_no_wall_penalty", makeBonusNode("NO_WALL_PENALTY"))
("CATAPULT",Bonus::CATAPULT) ("CATAPULT", makeBonusNode("CATAPULT"))
("MULTI_HEADED",Bonus::ATTACKS_ALL_ADJACENT) ("MULTI_HEADED", makeBonusNode("ATTACKS_ALL_ADJACENT"))
("IMMUNE_TO_MIND_SPELLS",Bonus::MIND_IMMUNITY) ("IMMUNE_TO_MIND_SPELLS", makeBonusNode("MIND_IMMUNITY"))
("HAS_EXTENDED_ATTACK",Bonus::TWO_HEX_ATTACK_BREATH); ("HAS_EXTENDED_ATTACK", makeBonusNode("TWO_HEX_ATTACK_BREATH"));
auto hasAbility = [&](const std::string name) -> bool auto hasAbility = [&](const std::string name) -> bool
{ {
return boost::algorithm::find_first(bonuses, name); return boost::algorithm::find_first(bonuses, name);
}; };
BOOST_FOREACH(auto a, abilityMap) BOOST_FOREACH(auto a, abilityMap)
{ {
if(hasAbility(a.first)) if(hasAbility(a.first))
ncre.addBonus(0, a.second); creature["abilities"][a.first] = a.second;
} }
if(hasAbility("DOUBLE_WIDE")) if(hasAbility("DOUBLE_WIDE"))
ncre.doubleWide = true; creature["doubleWide"].Bool() = true;
if(hasAbility("const_raises_morale")) if(hasAbility("const_raises_morale"))
{ {
ncre.addBonus(+1, Bonus::MORALE);; JsonNode node = makeBonusNode("MORALE");
ncre.getBonusList().back()->addPropagator(make_shared<CPropagatorNodeType>(CBonusSystemNode::HERO)); node["val"].Float() = 1;
node["propagator"].String() = "HERO";
creature["abilities"]["const_raises_morale"] = node;
} }
if(hasAbility("const_lowers_morale")) if(hasAbility("const_lowers_morale"))
{ {
ncre.addBonus(-1, Bonus::MORALE);; JsonNode node = makeBonusNode("MORALE");
ncre.getBonusList().back()->effectRange = Bonus::ONLY_ENEMY_ARMY; node["val"].Float() = 1;
node["effectRange"].String() = "ONLY_ENEMY_ARMY";
creature["abilities"]["const_lowers_morale"] = node;
} }
} }
void CCreatureHandler::load() void CCreatureHandler::load()
{ {
logGlobal->traceStream() << "\t\tReading ZCRTRAIT.TXT"; std::vector<JsonNode> h3Data;
////////////reading ZCRTRAIT.TXT ///////////////////
CLegacyConfigParser parser("DATA/ZCRTRAIT.TXT"); CLegacyConfigParser parser("DATA/ZCRTRAIT.TXT");
parser.endLine(); // header parser.endLine(); // header
@ -265,70 +278,80 @@ void CCreatureHandler::load()
while (parser.isNextEntryEmpty()) while (parser.isNextEntryEmpty())
parser.endLine(); parser.endLine();
CCreature &ncre = *new CCreature; JsonNode data;
ncre.idNumber = CreatureID(creatures.size());
ncre.cost.resize(GameConstants::RESOURCE_QUANTITY);
ncre.level=0;
ncre.iconIndex = ncre.idNumber + 2; // +2 for empty\selection images
ncre.nameSing = parser.readString(); data["graphics"]["iconIndex"].Float() = h3Data.size() + 2; // +2 for empty\selection images
ncre.namePl = parser.readString();
data["name"]["singular"].String() = parser.readString();
data["name"]["plural"].String() = parser.readString();
for(int v=0; v<7; ++v) for(int v=0; v<7; ++v)
{ data["cost"][GameConstants::RESOURCE_NAMES[v]].Float() = parser.readNumber();
ncre.cost[v] = parser.readNumber();
}
ncre.fightValue = parser.readNumber();
ncre.AIValue = parser.readNumber();
ncre.growth = parser.readNumber();
ncre.hordeGrowth = parser.readNumber();
ncre.addBonus(parser.readNumber(), Bonus::STACK_HEALTH); data["fightValue"].Float() = parser.readNumber();
ncre.addBonus(parser.readNumber(), Bonus::STACKS_SPEED); data["aiValue"].Float() = parser.readNumber();
ncre.addBonus(parser.readNumber(), Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK); data["growth"].Float() = parser.readNumber();
ncre.addBonus(parser.readNumber(), Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE); data["horde"].Float() = parser.readNumber();
ncre.addBonus(parser.readNumber(), Bonus::CREATURE_DAMAGE, 1);
ncre.addBonus(parser.readNumber(), Bonus::CREATURE_DAMAGE, 2);
ncre.addBonus(parser.readNumber(), Bonus::SHOTS);
//spells - not used? data["hitPoints"].Float() = parser.readNumber();
parser.readNumber(); data["speed"].Float() = parser.readNumber();
ncre.ammMin = parser.readNumber(); data["attack"].Float() = parser.readNumber();
ncre.ammMax = parser.readNumber(); data["defense"].Float() = parser.readNumber();
data["damage"]["min"].Float() = parser.readNumber();
data["damage"]["max"].Float() = parser.readNumber();
ncre.abilityText = parser.readString(); if (float shots = parser.readNumber())
loadBonuses(ncre, parser.readString()); //Attributes data["shots"].Float() = shots;
creatures.push_back(&ncre); if (float spells = parser.readNumber())
data["spellPoints"].Float() = spells;
data["advMapAmount"]["min"].Float() = parser.readNumber();
data["advMapAmount"]["max"].Float() = parser.readNumber();
data["abilityText"].String() = parser.readString();
loadBonuses(data, parser.readString()); //Attributes
h3Data.push_back(data);
} }
while (parser.endLine()); while (parser.endLine());
// loading creatures properties loadAnimationInfo(h3Data);
logGlobal->traceStream() << "\t\tReading creatures json configs";
const JsonNode gameConf(ResourceID("config/gameConfig.json")); const JsonNode gameConf(ResourceID("config/gameConfig.json"));
const JsonNode config(JsonUtils::assembleFromFiles(gameConf["creatures"].convertTo<std::vector<std::string> >())); JsonNode config(JsonUtils::assembleFromFiles(gameConf["creatures"].convertTo<std::vector<std::string> >()));
creatures.resize(GameConstants::CREATURES_COUNT);
BOOST_FOREACH(auto & node, config.Struct()) BOOST_FOREACH(auto & node, config.Struct())
{ {
int creatureID = node.second["id"].Float(); int numeric = node.second["id"].Float();
CCreature *c = creatures[creatureID];
loadCreatureJson(c, node.second); JsonUtils::merge(h3Data[numeric], node.second);
// Main reference name, e.g. royalGriffin //JsonUtils::validate(h3Data[numeric], "vcmi:creature", node.first);
c->nameRef = node.first;
registerCreature(node.first, c->idNumber); creatures[numeric] = loadCreature(h3Data[numeric]);
creatures[numeric]->idNumber = CreatureID(numeric);
VLC->modh->identifiers.registerObject ("creature." + node.first, numeric);
// Alternative names, if any // Alternative names, if any
BOOST_FOREACH(const JsonNode &name, node.second["extraNames"].Vector()) BOOST_FOREACH(const JsonNode &name, h3Data[numeric]["extraNames"].Vector())
VLC->modh->identifiers.registerObject ("creature." + name.String(), numeric);
}
for (size_t i=0; i < creatures.size(); i++)
{ {
registerCreature(name.String(), c->idNumber); if (creatures[i] == nullptr)
} logGlobal->warnStream() << "Warning: creature with id " << i << " is missing!";
} }
loadAnimationInfo(); loadCrExpBon();
}
void CCreatureHandler::loadCrExpBon()
{
if (VLC->modh->modules.STACK_EXP) //reading default stack experience bonuses if (VLC->modh->modules.STACK_EXP) //reading default stack experience bonuses
{ {
CLegacyConfigParser parser("DATA/CREXPBON.TXT"); CLegacyConfigParser parser("DATA/CREXPBON.TXT");
@ -429,76 +452,60 @@ void CCreatureHandler::load()
maxExpPerBattle[0] = maxExpPerBattle[7]; maxExpPerBattle[0] = maxExpPerBattle[7];
}//end of Stack Experience }//end of Stack Experience
logGlobal->traceStream() << "\t\tReading config/commanders.json";
const JsonNode config3(ResourceID("config/commanders.json"));
BOOST_FOREACH (auto bonus, config3["bonusPerLevel"].Vector())
{
commanderLevelPremy.push_back(JsonUtils::parseBonus (bonus.Vector()));
}
int i = 0;
BOOST_FOREACH (auto skill, config3["skillLevels"].Vector())
{
skillLevels.push_back (std::vector<ui8>());
BOOST_FOREACH (auto skillLevel, skill["levels"].Vector())
{
skillLevels[i].push_back (skillLevel.Float());
}
++i;
}
BOOST_FOREACH (auto ability, config3["abilityRequirements"].Vector())
{
std::pair <Bonus, std::pair <ui8, ui8> > a;
a.first = *JsonUtils::parseBonus (ability["ability"].Vector());
a.second.first = ability["skills"].Vector()[0].Float();
a.second.second = ability["skills"].Vector()[1].Float();
skillRequirements.push_back (a);
}
} }
void CCreatureHandler::loadAnimationInfo() void CCreatureHandler::loadAnimationInfo(std::vector<JsonNode> &h3Data)
{ {
CLegacyConfigParser parser("DATA/CRANIM.TXT"); CLegacyConfigParser parser("DATA/CRANIM.TXT");
parser.endLine(); // header parser.endLine(); // header
parser.endLine(); parser.endLine();
for(int dd=0; dd<creatures.size(); ++dd) for(int dd=0; dd<GameConstants::CREATURES_COUNT; ++dd)
{ {
while (parser.isNextEntryEmpty() && parser.endLine()) // skip empty lines while (parser.isNextEntryEmpty() && parser.endLine()) // skip empty lines
; ;
loadUnitAnimInfo(*creatures[dd], parser); loadUnitAnimInfo(h3Data[dd]["graphics"], parser);
parser.endLine();
} }
} }
void CCreatureHandler::loadUnitAnimInfo(CCreature & unit, CLegacyConfigParser & parser) void CCreatureHandler::loadUnitAnimInfo(JsonNode & graphics, CLegacyConfigParser & parser)
{ {
unit.animation.timeBetweenFidgets = parser.readNumber(); graphics["map"].String(); //create empty string. Real value will be loaded from H3 txt's
unit.animation.walkAnimationTime = parser.readNumber(); graphics["timeBetweenFidgets"].Float() = parser.readNumber();
unit.animation.attackAnimationTime = parser.readNumber();
unit.animation.flightAnimationDistance = parser.readNumber();
///////////////////////
unit.animation.upperRightMissleOffsetX = parser.readNumber(); JsonNode & animationTime = graphics["animationTime"];
unit.animation.upperRightMissleOffsetY = parser.readNumber(); animationTime["walk"].Float() = parser.readNumber();
unit.animation.rightMissleOffsetX = parser.readNumber(); animationTime["attack"].Float() = parser.readNumber();
unit.animation.rightMissleOffsetY = parser.readNumber(); animationTime["flight"].Float() = parser.readNumber();
unit.animation.lowerRightMissleOffsetX = parser.readNumber();
unit.animation.lowerRightMissleOffsetY = parser.readNumber();
/////////////////////// JsonNode & missile = graphics["missile"];
JsonNode & offsets = missile["offset"];
for(int jjj=0; jjj<12; ++jjj) offsets["upperX"].Float() = parser.readNumber();
unit.animation.missleFrameAngles.push_back(parser.readNumber()); offsets["upperY"].Float() = parser.readNumber();
offsets["middleX"].Float() = parser.readNumber();
offsets["middleY"].Float() = parser.readNumber();
offsets["lowerX"].Float() = parser.readNumber();
offsets["lowerY"].Float() = parser.readNumber();
unit.animation.troopCountLocationOffset= parser.readNumber(); for(int i=0; i<12; i++)
unit.animation.attackClimaxFrame = parser.readNumber(); {
JsonNode entry;
entry.Float() = parser.readNumber();
missile["frameAngles"].Vector().push_back(entry);
}
parser.endLine(); graphics["troopCountLocationOffset"].Float() = parser.readNumber();
missile["attackClimaxFrame"].Float() = parser.readNumber();
// assume that creature is not a shooter and should not have whole missile field
if (missile["frameAngles"].Vector()[0].Float() == 0 &&
missile["attackClimaxFrame"].Float() == 0)
graphics.Struct().erase("missile");
} }
void CCreatureHandler::load(std::string creatureID, const JsonNode & node) void CCreatureHandler::load(std::string creatureID, const JsonNode & node)
@ -509,7 +516,8 @@ void CCreatureHandler::load(std::string creatureID, const JsonNode & node)
creatures.push_back(creature); creatures.push_back(creature);
logGlobal->traceStream() << "Added creature: " << creatureID; logGlobal->traceStream() << "Added creature: " << creatureID;
registerCreature(creature->nameRef, creature->idNumber);
VLC->modh->identifiers.registerObject ("creature." + creature->nameRef, creature->idNumber);
} }
CCreature * CCreatureHandler::loadCreature(const JsonNode & node) CCreature * CCreatureHandler::loadCreature(const JsonNode & node)
@ -531,13 +539,12 @@ CCreature * CCreatureHandler::loadCreature(const JsonNode & node)
cre->addBonus(node["speed"].Float(), Bonus::STACKS_SPEED); cre->addBonus(node["speed"].Float(), Bonus::STACKS_SPEED);
cre->addBonus(node["attack"].Float(), Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK); cre->addBonus(node["attack"].Float(), Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK);
cre->addBonus(node["defense"].Float(), Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE); cre->addBonus(node["defense"].Float(), Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE);
const JsonNode & vec = node["damage"]; cre->addBonus(node["damage"]["min"].Float(), Bonus::CREATURE_DAMAGE, 1);
cre->addBonus(vec["min"].Float(), Bonus::CREATURE_DAMAGE, 1); cre->addBonus(node["damage"]["max"].Float(), Bonus::CREATURE_DAMAGE, 2);
cre->addBonus(vec["max"].Float(), Bonus::CREATURE_DAMAGE, 2);
auto & amounts = node ["advMapAmount"]; cre->ammMin = node["advMapAmount"]["min"].Float();
cre->ammMin = amounts["min"].Float(); cre->ammMax = node["advMapAmount"]["max"].Float();
cre->ammMax = amounts["max"].Float(); assert(cre->ammMin <= cre->ammMax);
if (!node["shots"].isNull()) if (!node["shots"].isNull())
cre->addBonus(node["shots"].Float(), Bonus::SHOTS); cre->addBonus(node["shots"].Float(), Bonus::SHOTS);
@ -547,13 +554,16 @@ CCreature * CCreatureHandler::loadCreature(const JsonNode & node)
cre->doubleWide = node["doubleWide"].Bool(); cre->doubleWide = node["doubleWide"].Bool();
//graphics
loadStackExperience(cre, node["stackExperience"]); loadStackExperience(cre, node["stackExperience"]);
loadJsonAnimation(cre, node["graphics"]);
loadCreatureJson(cre, node);
return cre;
}
const JsonNode & graphics = node["graphics"]; void CCreatureHandler::loadJsonAnimation(CCreature * cre, const JsonNode & graphics)
{
cre->animation.timeBetweenFidgets = graphics["timeBetweenFidgets"].Float(); cre->animation.timeBetweenFidgets = graphics["timeBetweenFidgets"].Float();
cre->animation.troopCountLocationOffset = graphics["troopCountLocationOffset"].Float(); cre->animation.troopCountLocationOffset = graphics["troopCountLocationOffset"].Float();
cre->animation.attackClimaxFrame = graphics["attackClimaxFrame"].Float();
const JsonNode & animationTime = graphics["animationTime"]; const JsonNode & animationTime = graphics["animationTime"];
cre->animation.walkAnimationTime = animationTime["walk"].Float(); cre->animation.walkAnimationTime = animationTime["walk"].Float();
@ -569,13 +579,11 @@ CCreature * CCreatureHandler::loadCreature(const JsonNode & node)
cre->animation.lowerRightMissleOffsetX = offsets["lowerX"].Float(); cre->animation.lowerRightMissleOffsetX = offsets["lowerX"].Float();
cre->animation.lowerRightMissleOffsetY = offsets["lowerY"].Float(); cre->animation.lowerRightMissleOffsetY = offsets["lowerY"].Float();
cre->animation.missleFrameAngles = missile["frameAngles"].convertTo<std::vector<double>>(); cre->animation.attackClimaxFrame = missile["attackClimaxFrame"].Float();
cre->animation.missleFrameAngles = missile["frameAngles"].convertTo<std::vector<double> >();
cre->advMapDef = graphics["map"].String(); cre->advMapDef = graphics["map"].String();
cre->iconIndex = graphics["iconIndex"].Float(); cre->iconIndex = graphics["iconIndex"].Float();
loadCreatureJson(cre, node);
return cre;
} }
void CCreatureHandler::loadCreatureJson(CCreature * creature, const JsonNode & config) void CCreatureHandler::loadCreatureJson(CCreature * creature, const JsonNode & config)
@ -583,11 +591,21 @@ void CCreatureHandler::loadCreatureJson(CCreature * creature, const JsonNode & c
creature->level = config["level"].Float(); creature->level = config["level"].Float();
creature->animDefName = config["graphics"]["animation"].String(); creature->animDefName = config["graphics"]["animation"].String();
BOOST_FOREACH(const JsonNode &ability, config["ability_remove"].Vector()) if (config["abilities"].getType() == JsonNode::DATA_STRUCT)
{ {
RemoveAbility(creature, ability); BOOST_FOREACH(auto &ability, config["abilities"].Struct())
{
if (!ability.second.isNull())
{
auto b = JsonUtils::parseBonus(ability.second);
b->source = Bonus::CREATURE_ABILITY;
b->duration = Bonus::PERMANENT;
creature->addNewBonus(b);
} }
}
}
else
{
BOOST_FOREACH(const JsonNode &ability, config["abilities"].Vector()) BOOST_FOREACH(const JsonNode &ability, config["abilities"].Vector())
{ {
if (ability.getType() == JsonNode::DATA_VECTOR) if (ability.getType() == JsonNode::DATA_VECTOR)
@ -600,6 +618,7 @@ void CCreatureHandler::loadCreatureJson(CCreature * creature, const JsonNode & c
creature->addNewBonus(b); creature->addNewBonus(b);
} }
} }
}
VLC->modh->identifiers.requestIdentifier(std::string("faction.") + config["faction"].String(), [=](si32 faction) VLC->modh->identifiers.requestIdentifier(std::string("faction.") + config["faction"].String(), [=](si32 faction)
{ {
@ -618,9 +637,8 @@ void CCreatureHandler::loadCreatureJson(CCreature * creature, const JsonNode & c
doubledCreatures.insert(creature->idNumber); doubledCreatures.insert(creature->idNumber);
creature->animation.projectileImageName = config["graphics"]["missile"]["projectile"].String(); creature->animation.projectileImageName = config["graphics"]["missile"]["projectile"].String();
//creature->animation.projectileSpin = config["graphics"]["missile"]["spinning"].Bool();
creature->special = config["special"].Bool(); creature->special = config["special"].Bool() || config["disabled"].Bool();
const JsonNode & sounds = config["sound"]; const JsonNode & sounds = config["sound"];
@ -631,8 +649,6 @@ void CCreatureHandler::loadCreatureJson(CCreature * creature, const JsonNode & c
GET_SOUND_VALUE(move); GET_SOUND_VALUE(move);
GET_SOUND_VALUE(shoot); GET_SOUND_VALUE(shoot);
GET_SOUND_VALUE(wince); GET_SOUND_VALUE(wince);
GET_SOUND_VALUE(ext1);
GET_SOUND_VALUE(ext2);
GET_SOUND_VALUE(startMoving); GET_SOUND_VALUE(startMoving);
GET_SOUND_VALUE(endMoving); GET_SOUND_VALUE(endMoving);
#undef GET_SOUND_VALUE #undef GET_SOUND_VALUE

View File

@ -79,14 +79,12 @@ public:
std::string move; std::string move;
std::string shoot; // range attack std::string shoot; // range attack
std::string wince; // attacked but did not die std::string wince; // attacked but did not die
std::string ext1; // creature specific extension std::string startMoving;
std::string ext2; // creature specific extension std::string endMoving;
std::string startMoving; // usually same as ext1
std::string endMoving; // usually same as ext2
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {
h & attack & defend & killed & move & shoot & wince & ext1 & ext2 & startMoving & endMoving; h & attack & defend & killed & move & shoot & wince & startMoving & endMoving;
} }
} sounds; } sounds;
@ -140,6 +138,7 @@ private:
CBonusSystemNode allCreatures; CBonusSystemNode allCreatures;
CBonusSystemNode creaturesOfLevel[GameConstants::CREATURES_PER_TOWN + 1];//index 0 is used for creatures of unknown tier or outside <1-7> range CBonusSystemNode creaturesOfLevel[GameConstants::CREATURES_PER_TOWN + 1];//index 0 is used for creatures of unknown tier or outside <1-7> range
void loadJsonAnimation(CCreature * creature, const JsonNode & graphics);
void loadStackExperience(CCreature * creature, const JsonNode &input); void loadStackExperience(CCreature * creature, const JsonNode &input);
void loadCreatureJson(CCreature * creature, const JsonNode & config); void loadCreatureJson(CCreature * creature, const JsonNode & config);
public: public:
@ -159,9 +158,10 @@ public:
/// loading functions /// loading functions
/// adding abilities from ZCRTRAIT.TXT /// adding abilities from ZCRTRAIT.TXT
void loadBonuses(CCreature & creature, std::string bonuses); void loadBonuses(JsonNode & creature, std::string bonuses);
/// load all creatures from H3 files /// load all creatures from H3 files
void load(); void load();
void loadCommanders();
/// load creature from json structure /// load creature from json structure
void load(std::string creatureID, const JsonNode & node); void load(std::string creatureID, const JsonNode & node);
/// load one creature from json config /// load one creature from json config
@ -169,9 +169,11 @@ public:
/// generates tier-specific bonus tree entries /// generates tier-specific bonus tree entries
void buildBonusTreeForTiers(); void buildBonusTreeForTiers();
/// read cranim.txt file from H3 /// read cranim.txt file from H3
void loadAnimationInfo(); void loadAnimationInfo(std::vector<JsonNode> & h3Data);
/// read one line from cranim.txt /// read one line from cranim.txt
void loadUnitAnimInfo(CCreature & unit, CLegacyConfigParser &parser); void loadUnitAnimInfo(JsonNode & unit, CLegacyConfigParser &parser);
/// load all creatures from H3 files
void loadCrExpBon();
/// parse crexpbon.txt file from H3 /// parse crexpbon.txt file from H3
void loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigParser &parser); void loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigParser &parser);
/// help function for parsing CREXPBON.txt /// help function for parsing CREXPBON.txt

View File

@ -123,6 +123,7 @@ void CHeroClassHandler::load()
JsonNode & classData = h3Data[numeric]; JsonNode & classData = h3Data[numeric];
JsonUtils::merge(classData, node.second); JsonUtils::merge(classData, node.second);
//JsonUtils::validate(classData, "vcmi:heroClass", node.first);
heroClasses[numeric] = loadClass(classData); heroClasses[numeric] = loadClass(classData);
heroClasses[numeric]->id = numeric; heroClasses[numeric]->id = numeric;
@ -457,6 +458,8 @@ void CHeroHandler::loadHeroes()
{ {
ui32 identifier = entry.second["id"].Float(); ui32 identifier = entry.second["id"].Float();
JsonUtils::merge(h3Data[identifier], entry.second); JsonUtils::merge(h3Data[identifier], entry.second);
//JsonUtils::validate(h3Data[identifier], "vcmi:hero", entry.first);
CHero * hero = loadHero(h3Data[identifier]); CHero * hero = loadHero(h3Data[identifier]);
hero->ID = identifier; hero->ID = identifier;
heroes[identifier] = hero; heroes[identifier] = hero;

View File

@ -70,6 +70,8 @@ JsonNode readBuilding(CLegacyConfigParser & parser)
BOOST_FOREACH(const std::string & resID, GameConstants::RESOURCE_NAMES) BOOST_FOREACH(const std::string & resID, GameConstants::RESOURCE_NAMES)
cost[resID].Float() = parser.readNumber(); cost[resID].Float() = parser.readNumber();
cost.Struct().erase("mithril"); // erase mithril to avoid confusing validator
parser.endLine(); parser.endLine();
return ret; return ret;
} }
@ -588,6 +590,7 @@ void CTownHandler::load()
} }
BOOST_FOREACH(auto & entry, buildingsConf.Struct()) BOOST_FOREACH(auto & entry, buildingsConf.Struct())
{ {
//JsonUtils::validate(entry.second, "vcmi:faction", entry.first);
load(entry.first, entry.second); load(entry.first, entry.second);
} }
} }

View File

@ -66,7 +66,8 @@ const bmap<std::string, TLimiterPtr> bonusLimiterMap = boost::assign::map_list_o
const bmap<std::string, TPropagatorPtr> bonusPropagatorMap = boost::assign::map_list_of const bmap<std::string, TPropagatorPtr> bonusPropagatorMap = boost::assign::map_list_of
("BATTLE_WIDE", make_shared<CPropagatorNodeType>(CBonusSystemNode::BATTLE)) ("BATTLE_WIDE", make_shared<CPropagatorNodeType>(CBonusSystemNode::BATTLE))
("VISITED_TOWN_AND_VISITOR", make_shared<CPropagatorNodeType>(CBonusSystemNode::TOWN_AND_VISITOR)) ("VISITED_TOWN_AND_VISITOR", make_shared<CPropagatorNodeType>(CBonusSystemNode::TOWN_AND_VISITOR))
("PLAYER_PROPAGATOR", make_shared<CPropagatorNodeType>(CBonusSystemNode::PLAYER)); ("PLAYER_PROPAGATOR", make_shared<CPropagatorNodeType>(CBonusSystemNode::PLAYER))
("HERO", make_shared<CPropagatorNodeType>(CBonusSystemNode::HERO));
#define BONUS_LOG_LINE(x) logBonus->traceStream() << x #define BONUS_LOG_LINE(x) logBonus->traceStream() << x

View File

@ -755,18 +755,23 @@ std::string JsonValidator::validateEnum(const JsonNode &node, const JsonVector &
std::string JsonValidator::validatesSchemaList(const JsonNode &node, const JsonNode &schemas, std::string errorMsg, std::function<bool(size_t)> isValid) std::string JsonValidator::validatesSchemaList(const JsonNode &node, const JsonNode &schemas, std::string errorMsg, std::function<bool(size_t)> isValid)
{ {
std::string errors;
if (!schemas.isNull()) if (!schemas.isNull())
{ {
std::string errors = "<tested schemas>\n";
size_t result = 0; size_t result = 0;
BOOST_FOREACH(auto & schema, schemas.Vector()) BOOST_FOREACH(auto & schema, schemas.Vector())
{ {
std::string error = validateNode(node, schema); std::string error = validateNode(node, schema);
if (error.empty()) if (error.empty())
{
result++; result++;
}
else else
errors += fail(error); {
errors += error;
errors += "<end of schema>\n";
}
} }
if (isValid(result)) if (isValid(result))
{ {
@ -794,7 +799,7 @@ std::string JsonValidator::validateNodeType(const JsonNode &node, const JsonNode
}); });
// data must be valid against one and only one schema // data must be valid against one and only one schema
errors += validatesSchemaList(node, schema["oneOf"], "Failed to pass only one and only one schema", [&](size_t count) errors += validatesSchemaList(node, schema["oneOf"], "Failed to pass one and only one schema", [&](size_t count)
{ {
return count == 1; return count == 1;
}); });
@ -805,13 +810,6 @@ std::string JsonValidator::validateNodeType(const JsonNode &node, const JsonNode
if (validateNode(node, schema["not"]).empty()) if (validateNode(node, schema["not"]).empty())
errors += fail("Successful validation against negative check"); errors += fail("Successful validation against negative check");
} }
// basic schema check
if (!schema["type"].isNull())
{
JsonNode::JsonType type = stringToType.find(schema["type"].String())->second;
if(type != node.getType())
errors += fail("Type mismatch!");
}
return errors; return errors;
} }
@ -822,6 +820,9 @@ std::string JsonValidator::validateNode(const JsonNode &node, const JsonNode &sc
assert(!schema.isNull()); // can this error be triggered? assert(!schema.isNull()); // can this error be triggered?
if (node.isNull())
return ""; // node not present. consider to be "valid"
if (!schema["$ref"].isNull()) if (!schema["$ref"].isNull())
{ {
std::string URI = schema["$ref"].String(); std::string URI = schema["$ref"].String();
@ -833,6 +834,14 @@ std::string JsonValidator::validateNode(const JsonNode &node, const JsonNode &sc
return validateRoot(node, URI); return validateRoot(node, URI);
} }
// basic schema check
if (!schema["type"].isNull())
{
JsonNode::JsonType type = stringToType.find(schema["type"].String())->second;
if(type != node.getType())
return errors + fail("Type mismatch!"); // different type. Any other checks are useless
}
errors += validateNodeType(node, schema); errors += validateNodeType(node, schema);
// enumeration - data must be equeal to one of items in list // enumeration - data must be equeal to one of items in list
@ -876,10 +885,10 @@ std::string JsonValidator::validateVectorItem(const JsonVector items, const Json
return validateNode(items[index], additional); return validateNode(items[index], additional);
// or, additionalItems field can be bool which indicates if such items are allowed // or, additionalItems field can be bool which indicates if such items are allowed
// default = false, so case if additionalItems is not present will be handled as well if (!additional.isNull() && additional.Bool() == false) // present and set to false - error
if (!additional.Bool())
return fail("Unknown entry found"); return fail("Unknown entry found");
// by default - additional items are allowed
return ""; return "";
} }
@ -930,9 +939,11 @@ std::string JsonValidator::validateStructItem(const JsonNode &node, const JsonNo
if (additional.getType() == JsonNode::DATA_STRUCT) if (additional.getType() == JsonNode::DATA_STRUCT)
return validateNode(node, additional); return validateNode(node, additional);
if (!additional.Bool()) // or, additionalItems field can be bool which indicates if such items are allowed
if (!additional.isNull() && additional.Bool() == false) // present and set to false - error
return fail("Unknown entry found: " + nodeName); return fail("Unknown entry found: " + nodeName);
// by default - additional items are allowed
return ""; return "";
} }
@ -947,7 +958,7 @@ std::string JsonValidator::validateStruct(const JsonNode &node, const JsonNode &
BOOST_FOREACH(auto & required, schema["required"].Vector()) BOOST_FOREACH(auto & required, schema["required"].Vector())
{ {
if (!vstd::contains(map, required.String())) if (node[required.String()].isNull())
errors += fail("Required entry " + required.String() + " is missing"); errors += fail("Required entry " + required.String() + " is missing");
} }

View File

@ -174,9 +174,6 @@ void CResourceLoader::addLoader(std::string mountPoint, shared_ptr<ISimpleResour
ResourceID ident(mountPoint, entry.first.getName(), entry.first.getType()); ResourceID ident(mountPoint, entry.first.getName(), entry.first.getType());
ResourceLocator locator(loader.get(), entry.second); ResourceLocator locator(loader.get(), entry.second);
if (ident.getType() == EResType::OTHER)
logGlobal->warnStream() << "Warning: unknown file type: " << entry.second;
resources[ident].push_back(locator); resources[ident].push_back(locator);
} }
} }

View File

@ -266,9 +266,9 @@ CLogFormatter::CLogFormatter() : pattern("%m")
} }
CLogFormatter::CLogFormatter(const std::string & pattern) : pattern(pattern) CLogFormatter::CLogFormatter(const std::string & pattern)
{ {
setPattern(pattern);
} }
std::string CLogFormatter::format(const LogRecord & record) const std::string CLogFormatter::format(const LogRecord & record) const
@ -370,7 +370,10 @@ EConsoleTextColor::EConsoleTextColor CColorMapping::getColorFor(const CLoggerDom
CLogConsoleTarget::CLogConsoleTarget(CConsoleHandler * console) : console(console), threshold(ELogLevel::INFO), coloredOutputEnabled(true) CLogConsoleTarget::CLogConsoleTarget(CConsoleHandler * console) : console(console), threshold(ELogLevel::INFO), coloredOutputEnabled(true)
{ {
formatter.setPattern("%l %n [%t] - %m"); // more verbose version:
//formatter.setPattern("%l %n [%t] - %m");
formatter.setPattern("%m");
} }
void CLogConsoleTarget::write(const LogRecord & record) void CLogConsoleTarget::write(const LogRecord & record)