瀏覽代碼

[refactor]
* creature config use string ids now
+ support string subtype id in short bonus format
* crexp parser: less magic nombers

alexvins 12 年之前
父節點
當前提交
856c7feeba

+ 2 - 4
config/artifacts.json

@@ -1706,7 +1706,7 @@
 		{
 			"id" : 122,
 			"type" : ["HERO"],
-		"bonuses" : [
+			"bonuses" : [
 				{
 					"type" : "CREATURE_GROWTH",
 					"subtype" : 6,
@@ -2058,9 +2058,7 @@
 		{
 			"bonuses" : [
 				{
-					"limiters" : [
-							"SHOOTER_ONLY",
-							],
+					"limiters" : ["SHOOTER_ONLY"],
 					"subtype" : 0,
 					"type" : "NO_DISTANCE_PENALTY",
 					"val" : 0,

+ 14 - 8
config/creatures/castle.json

@@ -132,7 +132,7 @@
 			"defend": "RGRFDFND.wav",
 			"killed": "RGRFKILL.wav",
 			"move": "RGRFMOVE.wav",
-						"wince": "RGRFWNCE.wav"
+			"wince": "RGRFWNCE.wav"
 		}
 	},
 	"swordsman" :
@@ -264,8 +264,11 @@
 		"id": 12,
 		"level": 7,
 		"faction": "castle",
-		"abilities": [ [ "HATE", 50, 55, 0 ],					//angels hate archdevils
-						 [			 "HATE", 50, 54, 0 ] ],			   	 	//angels hate devils
+		"abilities": 
+		[ 
+			["HATE", 50, "creature.archDevil", 0],	//angels hate archdevils
+			["HATE", 50, "creature.devil", 0]		//angels hate devil
+		],			   	 	
 		"upgrades": ["archangel"],
 		"graphics" :
 		{
@@ -285,11 +288,14 @@
 		"id": 13,
 		"level": 7,
 		"faction": "castle",
-		"abilities": [ [ "SPECIFIC_SPELL_POWER", 100, 38, 0 ],			// 100 hp per Archangel
-						 [ "SPELLCASTER", 0, 38, 0 ],			//archangels cast resurrection
-						 [ "HATE", 50, 55, 0 ],					//archangels hate arch
-						 [ "HATE", 50, 54, 0 ] ,					//archangels hate devils
-						 [ "CASTS", 1, 0, 0]],
+		"abilities": 
+		[ 
+			["SPECIFIC_SPELL_POWER", 100, "spell.resurrection", 0],	// 100 hp per Archangel
+			["SPELLCASTER", 0, "spell.resurrection", 0 ],			//archangels cast resurrection
+			["HATE", 50, "creature.archDevil", 0],	//archangels hate archdevils
+			["HATE", 50, "creature.devil", 0] ,		//archangels hate devils
+			["CASTS", 1, 0, 0]
+		],
 		"graphics" :
 		{
 			"animation": "CRANGL.DEF"

+ 38 - 40
config/creatures/conflux.json

@@ -5,14 +5,14 @@
 		"level": 2,
 		"extraNames": [ "airElementals" ],
 		"faction": "conflux",
-		"abilities": [ [ "SPELL_IMMUNITY", 0, 61, 0 ],			//air elementals are immune to mind spells (forgetfulness)	//earth elementals are non-living
-					   [ "SPELL_IMMUNITY", 0, 60, 0 ],			//air elementals are immune to mind spells (hypnotize)
-					   [ "SPELL_IMMUNITY", 0, 59, 0 ],			//air elementals are immune to mind spells (berserk)
-					   [ "SPELL_IMMUNITY", 0, 50, 0 ],			//air elementals are immune to mind spells (sorrow)
-					   [ "SPELL_IMMUNITY", 0, 23, 0 ],			//air elementals are immune to meteor shower
-					   [ "NON_LIVING", 0, 0, 0 ],
-					   [ "MORE_DAMAGE_FROM_SPELL", 100, 19, 0 ],		//air elementals are vulnerable to chain lightning
-					   [ "MORE_DAMAGE_FROM_SPELL", 100, 17, 0 ] ],	  	//air elementals are vulnerable to lightning bolt		//air elementals are non-living
+		"abilities": 
+		[ 
+			["MIND_IMMUNITY", 0, 0, 0],                       //air elementals are immune to mind spells 
+			["SPELL_IMMUNITY", 0, "spell.meteorShower", 0], //air elementals are immune to meteor shower
+			["NON_LIVING", 0, 0, 0 ],                        //air elementals are 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
+		],	  			
 		"upgrades": ["stormElemental"],
 		"graphics" :
 		{
@@ -32,14 +32,14 @@
 		"id": 113,
 		"level": 5,
 		"faction": "conflux",
-		"abilities": [ [ "SPELL_IMMUNITY", 0, 61, 0 ],			//earth elementals are immune to mind spells (forgetfulness)
-						 [ "SPELL_IMMUNITY", 0, 60, 0 ],			//earth elementals are immune to mind spells (hypnotize)
-						 [ "SPELL_IMMUNITY", 0, 59, 0 ],			//earth elementals are immune to mind spells (berserk)
-						 [ "SPELL_IMMUNITY", 0, 50, 0 ],			//earth elementals are immune to mind spells (sorrow)
-						 [ "SPELL_IMMUNITY", 0, 19, 0 ],			//earth elementals are immune to chain lightning
-						 [ "SPELL_IMMUNITY", 0, 17, 0 ],			//earth elementals are immune to lightning bolt
-						 [ "NON_LIVING", 0, 0, 0 ],
-						 [ "MORE_DAMAGE_FROM_SPELL", 100, 23, 0 ] ],		//earth elementals are vulnerable to meteor shower
+		"abilities": 
+		[ 
+			["MIND_IMMUNITY", 0, 0, 0], //earth elementals are immune to mind spells 
+			["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
+			["NON_LIVING", 0, 0, 0],
+			[ "MORE_DAMAGE_FROM_SPELL", 100, "spell.meteorShower", 0 ]   //earth elementals are vulnerable to meteor shower
+		],		
 		"upgrades": ["magmaElemental"],
 		"graphics" :
 		{
@@ -59,14 +59,13 @@
 		"id": 114,
 		"level": 4,
 		"faction": "conflux",
-		"abilities": [ [ "SPELL_IMMUNITY", 0, 61, 0 ],			//fire elementals are immune to mind spells (forgetfulness)
-					   [ "SPELL_IMMUNITY", 0, 60, 0 ],			//fire elementals are immune to mind spells (hypnotize)	//water elemental should be treated as double-wide
-					   [ "SPELL_IMMUNITY", 0, 59, 0 ],			//fire elementals are immune to mind spells (berserk)
-					   [ "SPELL_IMMUNITY", 0, 50, 0 ],			//fire elementals are immune to mind spells (sorrow)
-					   [ "NON_LIVING", 0, 0, 0 ],				//fire elementals are non-living
-					   [ "MORE_DAMAGE_FROM_SPELL", 100, 20, 0 ],		//fire elementals are vulnerable to frost ring
-					   [ "MORE_DAMAGE_FROM_SPELL", 100, 16, 0 ],		//fire elementals are vulnerable to ice bolt
-					   [ "FIRE_IMMUNITY", 0, 0, 0 ] ],			//fire elementals are immune to fire spells
+		"abilities": 
+		[ 
+			["MIND_IMMUNITY", 0, 0, 0],//fire elementals are immune to mind spells 
+			["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
+			[ "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
 		"upgrades": ["energyElemental"],
 		"graphics" :
 		{
@@ -87,18 +86,17 @@
 		"level": 3,
 		"extraNames": [ "waterElementals" ],
 		"faction": "conflux",
-		"abilities": [ [ "SPELL_IMMUNITY", 0, 61, 0 ],			//water elementals are immune to mind spells (forgetfulness)
-						 [ "SPELL_IMMUNITY", 0, 60, 0 ],			//water elementals are immune to mind spells (hypnotize)
-						 [ "SPELL_IMMUNITY", 0, 59, 0 ],			//water elementals are immune to mind spells (berserk)
-						 [ "SPELL_IMMUNITY", 0, 50, 0 ],			//water elementals are immune to mind spells (sorrow)
-						 [ "SPELL_IMMUNITY", 0, 20, 0 ],			//water elementals are immune to frost ring
-						 [ "SPELL_IMMUNITY", 0, 16, 0 ],			//water elementals are immune to ice bolt
-						 [ "NON_LIVING", 0, 0, 0 ],				//water elementals are non-living
-						 [ "MORE_DAMAGE_FROM_SPELL", 100, 29, 0 ],		//water elementals are vulnerable to fire shield
-						 [ "MORE_DAMAGE_FROM_SPELL", 100, 22, 0 ],		//water elementals are vulnerable to inferno
-						 [ "MORE_DAMAGE_FROM_SPELL", 100, 21, 0 ],		//water elementals are vulnerable to fireball
-						 [ "MORE_DAMAGE_FROM_SPELL", 100, 13, 0 ],		//water elementals are vulnerable to fire wall
-						 [ "DOUBLE_WIDE", 0, 0, 0 ] ],
+		"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
+			["SPELL_IMMUNITY", 0, "spell.iceBolt", 0 ],//water elementals are immune to ice bolt
+			["NON_LIVING", 0, 0, 0 ],				//water elementals are 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
+			["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
+			["DOUBLE_WIDE", 0, 0, 0 ] 
+		],
 		"upgrades": ["iceElemental"],
 		"graphics" :
 		{
@@ -202,7 +200,7 @@
 						 [ "DOUBLE_WIDE", 0, 0, 0 ],					//ice elemental should be treated as double-wide
 						 [ "CREATURE_ENCHANT_POWER", 6, 0, 0 ],
 						 [ "CASTS", 3, 0, 0 ],
-						 [ "SPELLCASTER", 2, 32, 0 ]],
+						 [ "SPELLCASTER", 2, "spell.protectWater", 0 ]],
 		"graphics" :
 		{
 			"animation": "CICEE.DEF",
@@ -230,7 +228,7 @@
 		"abilities": [ [ "NON_LIVING", 0, 0, 0 ],						//magma elementals shouldn't get morale
 						[ "CREATURE_ENCHANT_POWER", 6, 0, 0 ],
 						[ "CASTS", 3, 0, 0 ],
-						[ "SPELLCASTER", 2, 33, 0 ]],
+						[ "SPELLCASTER", 2, "spell.protectEarth", 0 ]],
 		"graphics" :
 		{
 			"animation": "CSTONE.DEF"
@@ -252,7 +250,7 @@
 		"abilities": [ [ "NON_LIVING", 0, 0, 0 ],						//storm elementals shouldn't get morale
 						[ "CREATURE_ENCHANT_POWER", 6, 0, 0 ],
 						[ "CASTS", 3, 0, 0 ],
-						[ "SPELLCASTER", 2, 30, 0 ]],
+						[ "SPELLCASTER", 2, "spell.protectAir", 0 ]],
 		"graphics" :
 		{
 			"animation": "CSTORM.DEF",
@@ -280,7 +278,7 @@
 		"abilities": [ [ "NON_LIVING", 0, 0, 0 ] ,					//energy elementals shouldn't get morale
 						[ "CREATURE_ENCHANT_POWER", 6, 0, 0 ],
 						[ "CASTS", 3, 0, 0 ],
-						[ "SPELLCASTER", 2, 31, 0 ]],
+						[ "SPELLCASTER", 2, "spell.protectFire", 0 ]],
 		"graphics" :
 		{
 			"animation": "CNRG.DEF"

+ 7 - 7
config/creatures/dungeon.json

@@ -4,7 +4,7 @@
 		"id": 70,
 		"level": 1,
 		"faction": "dungeon",
-		"abilities": [ [ "SPELL_IMMUNITY", 0, 62, 0 ] ],	  	   	//troglodytes are immune to blind
+		"abilities": [ [ "SPELL_IMMUNITY", 0, "spell.blind", 0 ] ],	  	   	//troglodytes are immune to blind
 		"upgrades": ["infernalTroglodyte"],
 		"hasDoubleWeek": true,
 		"graphics" :
@@ -25,7 +25,7 @@
 		"id": 71,
 		"level": 1,
 		"faction": "dungeon",
-		"abilities": [ [ "SPELL_IMMUNITY", 0, 62, 0 ] ],		   	//infernal troglodytes are immune to blind
+		"abilities": [ [ "SPELL_IMMUNITY", 0, "spell.blind", 0 ] ],		   	//infernal troglodytes are immune to blind
 		"graphics" :
 		{
 			"animation": "CITROG.DEF"
@@ -138,7 +138,7 @@
 		"id": 76,
 		"level": 4,
 		"faction": "dungeon",
-		"abilities": [ [ "SPELL_AFTER_ATTACK", 20, 70, 2000 ] ],  	//medusas			//minotaurs
+		"abilities": [ [ "SPELL_AFTER_ATTACK", 20, "spell.stoneGaze", 2000 ] ],
 		"upgrades": ["medusaQueen"],
 		"graphics" :
 		{
@@ -164,7 +164,7 @@
 		"id": 77,
 		"level": 4,
 		"faction": "dungeon",
-		"abilities": [ [ "SPELL_AFTER_ATTACK", 20, 70, 2000 ] ],  	//medusa queens			//minotaur kings
+		"abilities": [ [ "SPELL_AFTER_ATTACK", 20, "spell.stoneGaze", 2000 ] ],
 		"graphics" :
 		{
 			"animation": "CMEDUQ.DEF",
@@ -249,7 +249,7 @@
 		"id": 81,
 		"level": 6,
 		"faction": "dungeon",
-		"abilities": [ [ "SPELL_AFTER_ATTACK", 20, 74, 0 ] ],   	//scorpicore
+		"abilities": [ [ "SPELL_AFTER_ATTACK", 20, "spell.paralyze", 0 ] ],
 		"graphics" :
 		{
 			"animation": "CCMCOR.DEF"
@@ -293,8 +293,8 @@
 		"faction": "dungeon",
 		"abilities": [ [ "DRAGON_NATURE", 0, 0, 0 ],			//black dragon is a dragon
 						 [ "TWO_HEX_ATTACK_BREATH", 0, 0, 0 ],  	//Black Dragon has breath attack
-						 [ "HATE", 50, 41, 0 ],	//Hate Titans
-						 [ "HATE", 50, 40, 0 ],	//Hate Giants
+						 [ "HATE", 50, "creature.titan", 0 ],	//Hate Titans
+						 [ "HATE", 50, "creature.giant", 0 ],	//Hate Giants
 						 [ "LEVEL_SPELL_IMMUNITY", 5, 0, 0 ] ],   	//black dragon's spell immunity
 		"graphics" :
 		{

+ 10 - 10
config/creatures/fortress.json

@@ -131,7 +131,7 @@
 		"level": 3,
 		"extraNames": [ "dragonFly" ],
 		"faction": "fortress",
-		"abilities": [ [ "SPELL_AFTER_ATTACK", 100, 78, 0 ] ],  	//serpent fly
+		"abilities": [ [ "SPELL_AFTER_ATTACK", 100, "spell.dispelHelpful", 0 ] ], 
 		"upgrades": ["fireDragonFly"],
 		"hasDoubleWeek": true,
 		"graphics" :
@@ -152,8 +152,8 @@
 		"id": 105,
 		"level": 3,
 		"faction": "fortress",
-		"abilities": [ [ "SPELL_AFTER_ATTACK", 100, 78, 0 ],	//dragon fly
-					   [ "SPELL_AFTER_ATTACK", 100, 45, 0 ] ],  	//mighty gorgons
+		"abilities": [ [ "SPELL_AFTER_ATTACK", 100, "spell.dispelHelpful", 0 ],	
+					   [ "SPELL_AFTER_ATTACK", 100, "spell.weakness", 0 ] ],  
 		"graphics" :
 		{
 			"animation": "CDRFIR.DEF"
@@ -173,7 +173,7 @@
 		"id": 106,
 		"level": 4,
 		"faction": "fortress",
-		"abilities": [ [ "SPELL_AFTER_ATTACK", 20, 70, 0 ] ],   	//basilisks
+		"abilities": [ [ "SPELL_AFTER_ATTACK", 20, "spell.stoneGaze", 0 ] ],
 		"upgrades": ["greaterBasilisk"],
 		"graphics" :
 		{
@@ -193,7 +193,7 @@
 		"id": 107,
 		"level": 4,
 		"faction": "fortress",
-		"abilities": [ [ "SPELL_AFTER_ATTACK", 20, 70, 0 ] ],   	//greater basilisks
+		"abilities": [ [ "SPELL_AFTER_ATTACK", 20, "spell.stoneGaze", 0 ] ],
 		"graphics" :
 		{
 			"animation": "CGBASI.DEF"
@@ -231,7 +231,7 @@
 		"id": 109,
 		"level": 6,
 		"faction": "fortress",
-		"abilities": [ [ "SPELL_AFTER_ATTACK", 20, 71, 0 ] ],   	//Wyvern Monarch
+		"abilities": [ [ "SPELL_AFTER_ATTACK", 50, "spell.poison", 0 ] ],   	//50% probability (from FizMiG)
 		"graphics" :
 		{
 			"animation": "CWYVMN.DEF"
@@ -250,8 +250,8 @@
 		"id": 110,
 		"level": 7,
 		"faction": "fortress",
-		"abilities": [ [ "BLOCKS_RETALIATION", 0, 0, 0 ], 	   	//hydras
-					   [ "ATTACKS_ALL_ADJACENT", 0, 0, 0 ] ],   	//hydras
+		"abilities": [ [ "BLOCKS_RETALIATION", 0, 0, 0 ], 	   	
+					   [ "ATTACKS_ALL_ADJACENT", 0, 0, 0 ] ], 
 		"upgrades": ["chaosHydra"],
 		"graphics" :
 		{
@@ -271,8 +271,8 @@
 		"id": 111,
 		"level": 7,
 		"faction": "fortress",
-		"abilities": [ [ "BLOCKS_RETALIATION", 0, 0, 0 ], 	   	//chaos hydras
-					   [ "ATTACKS_ALL_ADJACENT", 0, 0, 0 ] ],   	//chaos hydras
+		"abilities": [ [ "BLOCKS_RETALIATION", 0, 0, 0 ], 	   	
+					   [ "ATTACKS_ALL_ADJACENT", 0, 0, 0 ] ],   
 		"graphics" :
 		{
 			"animation": "CCHYDR.DEF"

+ 10 - 10
config/creatures/necropolis.json

@@ -79,7 +79,7 @@
 		"id": 60,
 		"level": 3,
 		"faction": "necropolis",
-		"abilities": [ [ "FULL_HP_REGENERATION", 0, 1, 0 ] ],			//wight
+		"abilities": [ [ "FULL_HP_REGENERATION", 0, 1, 0 ] ],
 		"upgrades": ["wraith"],
 		"hasDoubleWeek": true,
 		"graphics" :
@@ -100,7 +100,7 @@
 		"id": 61,
 		"level": 3,
 		"faction": "necropolis",
-		"abilities": [ [ "FULL_HP_REGENERATION", 0, 1, 0 ], 			//wraith
+		"abilities": [ [ "FULL_HP_REGENERATION", 0, 1, 0 ],
 						 [ "MANA_DRAIN", 2, 0, 0 ] ],
 		"graphics" :
 		{
@@ -120,7 +120,7 @@
 		"id": 62,
 		"level": 4,
 		"faction": "necropolis",
-		"abilities": [ [ "BLOCKS_RETALIATION", 0, 0, 0 ] ],		//vampires		//vampire lords
+		"abilities": [ [ "BLOCKS_RETALIATION", 0, 0, 0 ] ],
 		"upgrades": ["vampireLord"],
 		"graphics" :
 		{
@@ -143,7 +143,7 @@
 		"level": 4,
 		"faction": "necropolis",
 		"abilities": [ [ "LIFE_DRAIN", 100, 0, 0 ], //drain 100% of damage dealt
-						 [ "BLOCKS_RETALIATION", 0, 0, 0 ] ],		//vampire lords
+						 [ "BLOCKS_RETALIATION", 0, 0, 0 ] ],
 		"graphics" :
 		{
 			"animation": "CNOSFE.DEF"
@@ -165,7 +165,7 @@
 		"id": 64,
 		"level": 5,
 		"faction": "necropolis",
-		"abilities": [ [ "SPELL_LIKE_ATTACK", 0, 76, 0 ] ],		//liches
+		"abilities": [ [ "SPELL_LIKE_ATTACK", 0, "spell.deathCloud", 0 ] ],
 		"upgrades": ["powerLich"],
 		"graphics" :
 		{
@@ -192,7 +192,7 @@
 		"id": 65,
 		"level": 5,
 		"faction": "necropolis",
-		"abilities": [ [ "SPELL_LIKE_ATTACK", 0, 76, 0 ] ], 		//power liches
+		"abilities": [ [ "SPELL_LIKE_ATTACK", 0, "spell.deathCloud", 0 ] ], 		//power liches
 		"graphics" :
 		{
 			"animation": "CPLICH.DEF",
@@ -217,7 +217,7 @@
 		"id": 66,
 		"level": 6,
 		"faction": "necropolis",
-		"abilities": [ [ "SPELL_AFTER_ATTACK", 20, 42, 0 ] ], 	//black knights
+		"abilities": [ [ "SPELL_AFTER_ATTACK", 20, "spell.curse", 0 ] ], 	
 		"upgrades": ["dreadKnight"],
 		"graphics" :
 		{
@@ -237,8 +237,8 @@
 		"id": 67,
 		"level": 6,
 		"faction": "necropolis",
-		"abilities": [ [ "SPELL_AFTER_ATTACK", 20, 42, 0 ], 	//dread knights
-						 [ "DOUBLE_DAMAGE_CHANCE", 20, 0, 0 ] ],	//vampire lords
+		"abilities": [ [ "SPELL_AFTER_ATTACK", 20, "spell.curse", 0 ], 	
+						 [ "DOUBLE_DAMAGE_CHANCE", 20, 0, 0 ] ],
 		"graphics" :
 		{
 			"animation": "CBLORD.DEF"
@@ -278,7 +278,7 @@
 		"level": 7,
 		"faction": "necropolis",
 		"abilities": [ [ "DRAGON_NATURE", 0, 0, 0 ],			//ghost dragon is a dragon
-						 [ "SPELL_AFTER_ATTACK", 20, 75, 0 ] ],  	//ghost dragon
+						 [ "SPELL_AFTER_ATTACK", 20, "spell.age", 0 ] ],  	
 		"graphics" :
 		{
 			"animation": "CHDRGN.DEF"

+ 17 - 17
config/creatures/neutral.json

@@ -91,14 +91,14 @@
 		"abilities": [ [ "DRAGON_NATURE", 0, 0, 0 ],			//faerie dragon is a dragon
 						[ "CASTS", 5, 0, 0 ],
 						[ "CREATURE_SPELL_POWER", 500, 0, 0], 	//5 spell power per dragon
-						[ "SPELLCASTER", 2, 15, 10 ],			//magic arrow
-						[ "SPELLCASTER", 2, 16, 22 ],			//ice bolt
-						[ "SPELLCASTER", 2, 17, 22 ],			//thunderbolt
-						[ "SPELLCASTER", 2, 19, 5 ],			//chain lightning
-						[ "SPELLCASTER", 2, 20, 10 ],			//frost ring
-						[ "SPELLCASTER", 2, 21, 21 ],			//fireball
-						[ "SPELLCASTER", 2, 22, 5 ],			//inferno
-						[ "SPELLCASTER", 2, 23, 5 ]],			//meteor shower
+						[ "SPELLCASTER", 2, "spell.magicArrow", 10 ],			
+						[ "SPELLCASTER", 2, "spell.iceBolt", 22 ],			
+						[ "SPELLCASTER", 2, "spell.lightningBolt", 22 ],			
+						[ "SPELLCASTER", 2, "spell.chainLightning", 5 ],			
+						[ "SPELLCASTER", 2, "spell.frostRing", 10 ],			
+						[ "SPELLCASTER", 2, "spell.fireball", 21 ],			
+						[ "SPELLCASTER", 2, "spell.inferno", 5 ],			
+						[ "SPELLCASTER", 2, "spell.meteorShower", 5 ]],			
 		"graphics" :
 		{
 			"animation": "CFDRGN.DEF"
@@ -141,13 +141,13 @@
 		"extraNames": [ "enchanters" ],
 		"faction": "neutral",
 		"abilities": [ [ "NO_WALL_PENALTY", 0, 0, 0 ],
-						 [ "ENCHANTER", 3, 28, 3],		//air shield
-						 [ "ENCHANTER", 3, 41, 3],		//bless
-						 [ "ENCHANTER", 3, 45, 3],		//wealness
-						 [ "ENCHANTER", 3, 46, 3],		//stone skin
-						 [ "ENCHANTER", 3, 53, 3],		//slow
-						 [ "ENCHANTER", 3, 54, 3],		//haster
-						 [ "CASTS", 5, 0, 0]],			//Enchanter
+						 [ "ENCHANTER", 3, "spell.airShield", 3],		
+						 [ "ENCHANTER", 3, "spell.bless", 3],		
+						 [ "ENCHANTER", 3, "spell.weakness", 3],		
+						 [ "ENCHANTER", 3, "spell.stoneSkin", 3],		
+						 [ "ENCHANTER", 3, "spell.slow", 3],		
+						 [ "ENCHANTER", 3, "spell.haste", 3],		
+						 [ "CASTS", 5, 0, 0]],			
 		"graphics" :
 		{
 			"animation": "CENCH.DEF",
@@ -174,7 +174,7 @@
 		"extraNames": [ "sharpshooters" ],
 		"faction": "neutral",
 		"abilities": [ [ "NO_WALL_PENALTY", 0, 0, 0 ],
-						 [ "NO_DISTANCE_PENALTY", 0, 0, 0 ] ],			//Sharpshooter
+						 [ "NO_DISTANCE_PENALTY", 0, 0, 0 ] ],
 		"graphics" :
 		{
 			"animation": "CSHARP.DEF",
@@ -316,7 +316,7 @@
 		"id": 144,
 		"level": 5,
 		"faction": "neutral",
-		"abilities": [ [ "FULL_HP_REGENERATION", 0, 0, 0 ] ], 			//troll
+		"abilities": [ [ "FULL_HP_REGENERATION", 0, 0, 0 ] ],
 		"graphics" :
 		{
 			"animation": "CTROLL.DEF"

+ 4 - 4
config/creatures/rampart.json

@@ -178,7 +178,7 @@
 		"id": 22,
 		"level": 5,
 		"faction": "rampart",
-		"abilities": [ [ "SPELL_AFTER_ATTACK", 100, 72, 0 ] ],   //dendroids cast bind
+		"abilities": [ [ "SPELL_AFTER_ATTACK", 100, "spell.bind", 0 ] ],   //dendroids cast bind
 		"upgrades": ["dendroidSoldier"],
 		"graphics" :
 		{
@@ -198,7 +198,7 @@
 		"id": 23,
 		"level": 5,
 		"faction": "rampart",
-		"abilities": [ [ "SPELL_AFTER_ATTACK", 100, 72, 0 ] ],	//dendroid guards cast bind
+		"abilities": [ [ "SPELL_AFTER_ATTACK", 100, "spell.bind", 0 ] ],	//dendroid guards cast bind
 		"graphics" :
 		{
 			"animation": "CBTREE.DEF"
@@ -218,7 +218,7 @@
 		"level": 6,
 		"faction": "rampart",
 		"abilities": [ [ "SPELL_RESISTANCE_AURA", 0, 55, 0 ],	//unicorn
-						 [ "SPELL_AFTER_ATTACK", 20, 62, 0 ] ],	//unicorns cast blind with 20% probability
+						 [ "SPELL_AFTER_ATTACK", 20, "spell.blind", 0 ] ],	//unicorns cast blind with 20% probability
 		"upgrades": ["warUnicorn"],
 		"graphics" :
 		{
@@ -239,7 +239,7 @@
 		"level": 6,
 		"faction": "rampart",
 		"abilities": [ [ "SPELL_RESISTANCE_AURA", 20, 55, 0 ], 	//war unicorn
-						 [ "SPELL_AFTER_ATTACK", 20, 62, 0 ] ],	//war unicorns cast blind with 20% probability
+						 [ "SPELL_AFTER_ATTACK", 20, "spell.blind", 0 ] ],	//war unicorns cast blind with 20% probability
 		"graphics" :
 		{
 			"animation": "CWUNIC.DEF"

+ 7 - 7
config/creatures/stronghold.json

@@ -63,7 +63,7 @@
 		"id": 87,
 		"level": 2,
 		"faction": "stronghold",
-		"abilities": [ [ "ADDITIONAL_ATTACK", 1, 0, 0 ] ],		//wolf raider
+		"abilities": [ [ "ADDITIONAL_ATTACK", 1, 0, 0 ] ],
 		"graphics" :
 		{
 			"animation": "CUWLFR.DEF"
@@ -150,9 +150,9 @@
 		"id": 91,
 		"level": 4,
 		"faction": "stronghold",
-		"abilities": [ [ "SPELLCASTER", 2, 43, 0 ],
+		"abilities": [ [ "SPELLCASTER", 2, "spell.bloodlust", 0 ],
 						 [ "CASTS", 3, 0, 0],
-						 [ "CREATURE_ENCHANT_POWER", 3, 0, 0]],   	   	   	//ogre magi cast bloodlust
+						 [ "CREATURE_ENCHANT_POWER", 3, 0, 0]],   	   	   	
 		"graphics" :
 		{
 			"animation": "COGMAG.DEF"
@@ -191,8 +191,8 @@
 		"id": 93,
 		"level": 5,
 		"faction": "stronghold",
-		"abilities": [ [ "SPECIFIC_SPELL_POWER", 10, 77, 0 ],	//10 damage per unit
-						 [ "SPELL_AFTER_ATTACK", 20, 77, 0 ] ],   	//thunderbirds
+		"abilities": [ [ "SPECIFIC_SPELL_POWER", 10, "spell.thunderbolt", 0 ],	//10 damage per unit
+						 [ "SPELL_AFTER_ATTACK", 20, "spell.thunderbolt", 0 ] ],   	
 		"graphics" :
 		{
 			"animation": "CTBIRD.DEF"
@@ -260,7 +260,7 @@
 		"id": 96,
 		"level": 7,
 		"faction": "stronghold",
-		"abilities": [ [ "ENEMY_DEFENCE_REDUCTION", 40, 0, 0 ] ],		//behemots
+		"abilities": [ [ "ENEMY_DEFENCE_REDUCTION", 40, 0, 0 ] ],		
 		"upgrades": ["ancientBehemoth"],
 		"graphics" :
 		{
@@ -280,7 +280,7 @@
 		"id": 97,
 		"level": 7,
 		"faction": "stronghold",
-		"abilities": [ [ "ENEMY_DEFENCE_REDUCTION", 80, 0, 0 ] ],		//ancient behemots
+		"abilities": [ [ "ENEMY_DEFENCE_REDUCTION", 80, 0, 0 ] ],
 		"graphics" :
 		{
 			"animation": "CABEHE.DEF"

+ 1 - 1
config/creatures/tower.json

@@ -286,7 +286,7 @@
 		"level": 7,
 		"faction": "tower",
 		"abilities": [ ["MIND_IMMUNITY", 0, 0, 0],			//Titans are immune to mind spells
-						 [ "HATE", 50, 83, 0 ] ],					//titans hate black dragons
+						 [ "HATE", 50, "creature.blackDragon", 0 ] ],					//titans hate black dragons
 		"graphics" :
 		{
 			"animation": "CGTITA.DEF",

+ 9 - 9
config/creatures/wog.json

@@ -284,7 +284,7 @@
 						[ "CASTS", 1, 0, 0 ] ,
 						[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
 						[ "CREATURE_SPELL_POWER", 100, 0, 0 ] ,
-						[ "SPELLCASTER", 3, 37, 0 ] ], //expert cure
+						[ "SPELLCASTER", 3, "spell.cure", 0 ] ], //expert cure
 		"graphics" :
 		{
 			"animation": "ZM174NPC.DEF",
@@ -312,7 +312,7 @@
 						[ "CASTS", 1, 0, 0 ] ,
 						[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
 						[ "CREATURE_SPELL_POWER", 100, 0, 0 ] ,
-						[ "SPELLCASTER", 3, 27, 0 ] ], //expert shield
+						[ "SPELLCASTER", 3, "spell.shield", 0 ] ], //expert shield
 		"graphics" :
 		{
 			"animation": "ZM175NPC.DEF",
@@ -341,7 +341,7 @@
 						[ "CASTS", 1, 0, 0 ] ,
 						[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
 						[ "CREATURE_SPELL_POWER", 100, 0, 0 ] ,
-						[ "SPELLCASTER", 3, 44, 0 ] ], //expert precision
+						[ "SPELLCASTER", 3, "spell.precision", 0 ] ], //expert precision
 		"graphics" :
 		{
 			"animation": "ZM176NPC.DEF",
@@ -371,7 +371,7 @@
 						[ "CASTS", 1, 0, 0 ] ,
 						[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
 						[ "CREATURE_SPELL_POWER", 100, 0, 0 ] ,
-						[ "SPELLCASTER", 3, 29, 0 ] ], //expert fire shield
+						[ "SPELLCASTER", 3, "spell.fireShield", 0 ] ], //expert fire shield
 		"graphics" :
 		{
 			"animation": "ZM177NPC.DEF",
@@ -399,7 +399,7 @@
 						[ "CASTS", 1, 0, 0 ] ,
 						[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
 						[ "CREATURE_SPELL_POWER", 100, 0, 0 ] ,
-						[ "SPELLCASTER", 3, 39, 0 ] ], //expert animate dead
+						[ "SPELLCASTER", 3, "spell.animateDead", 0 ] ], //expert animate dead
 		"graphics" :
 		{
 			"animation": "ZM178NPC.DEF",
@@ -427,7 +427,7 @@
 						[ "CASTS", 1, 0, 0 ] ,
 						[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
 						[ "CREATURE_SPELL_POWER", 100, 0, 0 ] ,
-						[ "SPELLCASTER", 3, 46, 0 ] ], //expert stone skin
+						[ "SPELLCASTER", 3, "spell.stoneSkin", 0 ] ], //expert stone skin
 		"graphics" :
 		{
 			"animation": "ZM179NPC.DEF",
@@ -455,7 +455,7 @@
 						[ "CASTS", 1, 0, 0 ] ,
 						[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
 						[ "CREATURE_SPELL_POWER", 100, 0, 0 ] ,
-						[ "SPELLCASTER", 3, 37, 0 ] ], //expert cure
+						[ "SPELLCASTER", 3, "spell.cure", 0 ] ], //expert cure
 		"graphics" :
 		{
 			"animation": "ZM180NPC.DEF",
@@ -483,7 +483,7 @@
 						[ "CASTS", 1, 0, 0 ] ,
 						[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
 						[ "CREATURE_SPELL_POWER", 100, 0, 0 ] ,
-						[ "SPELLCASTER", 3, 53, 0 ] ], //expert haste
+						[ "SPELLCASTER", 3, "spell.haste", 0 ] ], //expert haste
 		"graphics" :
 		{
 			"animation": "ZM181NPC.DEF",
@@ -512,7 +512,7 @@
 						[ "CASTS", 1, 0, 0 ] ,
 						[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
 						[ "CREATURE_SPELL_POWER", 100, 0, 0 ] ,
-						[ "SPELLCASTER", 3, 58, 0 ] ], //expert counterstrike
+						[ "SPELLCASTER", 3, "spell.counterstrike", 0 ] ], //expert counterstrike
 		"graphics" :
 		{
 			"animation": "ZM182NPC.DEF",

+ 53 - 50
lib/CCreatureHandler.cpp

@@ -19,6 +19,14 @@ using namespace boost::assign;
  * Full text of license available in license.txt file, in main folder
  *
  */
+ 
+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()
 {
@@ -162,7 +170,7 @@ static void AddAbility(CCreature *cre, const JsonVector &ability_vec)
 			cre->addBonus(-1, Bonus::LUCK);
 			cre->getBonusList().back()->effectRange = Bonus::ONLY_ENEMY_ARMY;
 		} else
-			tlog1 << "Error: invalid ability type " << type << " in creatures.txt" << std::endl;
+			tlog1 << "Error: invalid ability type " << type << " in creatures config" << std::endl;
 
 		return;
 	}
@@ -170,7 +178,7 @@ static void AddAbility(CCreature *cre, const JsonVector &ability_vec)
 	nsf->type = it->second;
 
 	nsf->val = ability_vec[1].Float();
-	nsf->subtype = ability_vec[2].Float();
+	JsonUtils::resolveIdentifier(ability_vec[2],nsf->subtype);
 	nsf->additionalInfo = ability_vec[3].Float();
 	nsf->source = Bonus::CREATURE_ABILITY;
 	nsf->sid = cre->idNumber;
@@ -191,7 +199,7 @@ static void RemoveAbility(CCreature *cre, const JsonNode &ability)
 		if (type == "DOUBLE_WIDE")
 			cre->doubleWide = false;
 		else
-			tlog1 << "Error: invalid ability type " << type << " in creatures.json" << std::endl;
+			tlog1 << "Error: invalid ability type " << type << " in creatures config" << std::endl;
 
 		return;
 	}
@@ -255,51 +263,46 @@ void CCreatureHandler::loadCreatures()
 		ncre.abilityRefs = parser.readString();
 
 		{ //adding abilities from ZCRTRAIT.TXT
-			if(boost::algorithm::find_first(ncre.abilityRefs, "DOUBLE_WIDE"))
+			static const std::map<std::string,Bonus::BonusType> abilityMap = 
+			  boost::assign::map_list_of
+			    ("FLYING_ARMY", Bonus::FLYING)
+			    ("SHOOTING_ARMY", Bonus::SHOOTER)
+			    ("SIEGE_WEAPON", Bonus::SIEGE_WEAPON)
+			    ("const_free_attack", Bonus::BLOCKS_RETALIATION)
+			    ("IS_UNDEAD", Bonus::UNDEAD)
+			    ("const_no_melee_penalty",Bonus::NO_MELEE_PENALTY)
+			    ("const_jousting",Bonus::JOUSTING)
+			    ("KING_1",Bonus::KING1)
+			    ("KING_2",Bonus::KING2)
+				("KING_3",Bonus::KING3)
+				("const_no_wall_penalty",Bonus::NO_WALL_PENALTY)
+				("CATAPULT",Bonus::CATAPULT)
+				("MULTI_HEADED",Bonus::ATTACKS_ALL_ADJACENT)
+				("IMMUNE_TO_MIND_SPELLS",Bonus::MIND_IMMUNITY)
+				("IMMUNE_TO_FIRE_SPELLS",Bonus::FIRE_IMMUNITY)
+				("HAS_EXTENDED_ATTACK",Bonus::TWO_HEX_ATTACK_BREATH);
+				
+			auto hasAbility = [&ncre](const std::string name) -> bool
+			{
+				return boost::algorithm::find_first(ncre.abilityRefs,name);
+			};			
+			BOOST_FOREACH(auto a, abilityMap)
+			{
+				if(hasAbility(a.first))
+					ncre.addBonus(0, a.second);
+			}			
+			if(hasAbility("DOUBLE_WIDE"))
 				ncre.doubleWide = true;
-			if(boost::algorithm::find_first(ncre.abilityRefs, "FLYING_ARMY"))
-				ncre.addBonus(0, Bonus::FLYING);
-			if(boost::algorithm::find_first(ncre.abilityRefs, "SHOOTING_ARMY"))
-				ncre.addBonus(0, Bonus::SHOOTER);
-			if(boost::algorithm::find_first(ncre.abilityRefs, "SIEGE_WEAPON"))
-				ncre.addBonus(0, Bonus::SIEGE_WEAPON);
-			if(boost::algorithm::find_first(ncre.abilityRefs, "const_free_attack"))
-				ncre.addBonus(0, Bonus::BLOCKS_RETALIATION);
-			if(boost::algorithm::find_first(ncre.abilityRefs, "IS_UNDEAD"))
-				ncre.addBonus(0, Bonus::UNDEAD);
-			if(boost::algorithm::find_first(ncre.abilityRefs, "const_no_melee_penalty"))
-				ncre.addBonus(0, Bonus::NO_MELEE_PENALTY);
-			if(boost::algorithm::find_first(ncre.abilityRefs, "const_jousting"))
-				ncre.addBonus(0, Bonus::JOUSTING);
-			if(boost::algorithm::find_first(ncre.abilityRefs, "const_raises_morale"))
+			if(hasAbility("const_raises_morale"))
 			{
 				ncre.addBonus(+1, Bonus::MORALE);;
 				ncre.getBonusList().back()->addPropagator(make_shared<CPropagatorNodeType>(CBonusSystemNode::HERO));
 			}
-			if(boost::algorithm::find_first(ncre.abilityRefs, "const_lowers_morale"))
+			if(hasAbility("const_lowers_morale"))
 			{
 				ncre.addBonus(-1, Bonus::MORALE);;
 				ncre.getBonusList().back()->effectRange = Bonus::ONLY_ENEMY_ARMY;
 			}
-			if(boost::algorithm::find_first(ncre.abilityRefs, "KING_1"))
-				ncre.addBonus(0, Bonus::KING1);
-			if(boost::algorithm::find_first(ncre.abilityRefs, "KING_2"))
-				ncre.addBonus(0, Bonus::KING2);
-			if(boost::algorithm::find_first(ncre.abilityRefs, "KING_3"))
-				ncre.addBonus(0, Bonus::KING3);
-			if(boost::algorithm::find_first(ncre.abilityRefs, "const_no_wall_penalty"))
-				ncre.addBonus(0, Bonus::NO_WALL_PENALTY);
-			if(boost::algorithm::find_first(ncre.abilityRefs, "CATAPULT"))
-				ncre.addBonus(0, Bonus::CATAPULT);
-			if(boost::algorithm::find_first(ncre.abilityRefs, "MULTI_HEADED"))
-				ncre.addBonus(0, Bonus::ATTACKS_ALL_ADJACENT);
-
-			if(boost::algorithm::find_first(ncre.abilityRefs, "IMMUNE_TO_MIND_SPELLS"))
-				ncre.addBonus(0, Bonus::MIND_IMMUNITY);
-			if(boost::algorithm::find_first(ncre.abilityRefs, "IMMUNE_TO_FIRE_SPELLS"))
-				ncre.addBonus(0, Bonus::FIRE_IMMUNITY);
-			if(boost::algorithm::find_first(ncre.abilityRefs, "HAS_EXTENDED_ATTACK"))
-				ncre.addBonus(0, Bonus::TWO_HEX_ATTACK_BREATH);;
 		}
 		creatures.push_back(&ncre);
 	}
@@ -332,12 +335,12 @@ void CCreatureHandler::loadCreatures()
 
 		// Main reference name, e.g. royalGriffin
 		c->nameRef = node.first;
-		VLC->modh->identifiers.registerObject("creature." + node.first, c->idNumber);
+		registerCreature(node.first, c->idNumber);
 
 		// Alternative names, if any
 		BOOST_FOREACH(const JsonNode &name, node.second["extraNames"].Vector())
 		{
-			VLC->modh->identifiers.registerObject("creature." + name.String(), c->idNumber);
+			registerCreature(name.String(), c->idNumber);
 		}
 	}
 
@@ -548,7 +551,7 @@ void CCreatureHandler::load(const JsonNode & node)
 
 			creatures.push_back(creature);
 			tlog5 << "Added creature: " << entry.first << "\n";
-			VLC->modh->identifiers.registerObject(std::string("creature.") + creature->nameRef, creature->idNumber);
+			registerCreature(creature->nameRef,creature->idNumber);
 		}
 	}
 }
@@ -818,35 +821,35 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigPars
 		{
 			case 'B': //Blind
 				b.type = Bonus::SPELL_IMMUNITY;
-				b.subtype = 74;
+				b.subtype = SpellID::BLIND;
 				break;
 			case 'H': //Hypnotize
 				b.type = Bonus::SPELL_IMMUNITY;
-				b.subtype = 60;
+				b.subtype = SpellID::HYPNOTIZE;
 				break;
 			case 'I': //Implosion
 				b.type = Bonus::SPELL_IMMUNITY;
-				b.subtype = 18;
+				b.subtype = SpellID::IMPLOSION;
 				break;
 			case 'K': //Berserk
 				b.type = Bonus::SPELL_IMMUNITY;
-				b.subtype = 59;
+				b.subtype = SpellID::BERSERK;
 				break;
 			case 'M': //Meteor Shower
 				b.type = Bonus::SPELL_IMMUNITY;
-				b.subtype = 23;
+				b.subtype = SpellID::METEOR_SHOWER;
 				break;
 			case 'N': //dispell beneficial spells
 				b.type = Bonus::SPELL_IMMUNITY;
-				b.subtype = 78;
+				b.subtype = SpellID::DISPEL_HELPFUL_SPELLS;
 				break;
 			case 'R': //Armageddon
 				b.type = Bonus::SPELL_IMMUNITY;
-				b.subtype = 26;
+				b.subtype = SpellID::ARMAGEDDON;
 				break;
 			case 'S': //Slow
 				b.type = Bonus::SPELL_IMMUNITY;
-				b.subtype = 54;
+				b.subtype = SpellID::SLOW;
 				break;
 			case '6':
 			case '7':

+ 1 - 1
lib/JsonNode.cpp

@@ -897,7 +897,7 @@ Bonus * JsonUtils::parseBonus (const JsonVector &ability_vec) //TODO: merge with
 	}
 	b->type = it->second;
 	b->val = ability_vec[1].Float();
-	b->subtype = ability_vec[2].Float();
+	resolveIdentifier(ability_vec[2],b->subtype);
 	b->additionalInfo = ability_vec[3].Float();
 	b->duration = Bonus::PERMANENT; //TODO: handle flags (as integer)
 	b->turnsRemain = 0;