mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Implemented object schema. Commiting current progress before sync with
upstream.
This commit is contained in:
parent
67f11b1a01
commit
dc7f820161
@ -8,7 +8,8 @@
|
||||
"creature" : 150,
|
||||
"faction" : 9,
|
||||
"hero" : 156,
|
||||
"spell" : 81,
|
||||
"spell" : 81,
|
||||
"object" : 256,
|
||||
"mapVersion" : 28 // max supported version, SoD
|
||||
},
|
||||
|
||||
|
@ -2,132 +2,132 @@
|
||||
/// These are objects that can not be configured, either due to
|
||||
/// their hardcoded status or because they don't have any configurable functionality
|
||||
|
||||
"altarOfSacrifice" : { "id" :2, "handler": "market" },
|
||||
"tradingPost" : { "id" :221, "handler": "market" },
|
||||
"tradingPost" : { "id" :99, "handler": "market" },
|
||||
"freelancer'SGuild" : { "id" :213, "handler": "market" },
|
||||
"altarOfSacrifice" : { "index" :2, "handler": "market" },
|
||||
"tradingPost" : { "index" :221, "handler": "market" },
|
||||
"tradingPostDUPLICATE" : { "index" :99, "handler": "market" },
|
||||
"freelancersGuild" : { "index" :213, "handler": "market" },
|
||||
|
||||
"blackMarket" : { "id" :7, "handler": "blackMarket" },
|
||||
"blackMarket" : { "index" :7, "handler": "blackMarket" },
|
||||
|
||||
"crypt" : { "id" :84, "handler": "bank" },
|
||||
"shipwreck" : { "id" :85, "handler": "bank" },
|
||||
"derelictShip" : { "id" :24, "handler": "bank" },
|
||||
"dragonUtopia" : { "id" :25, "handler": "bank" },
|
||||
"crypt" : { "index" :84, "handler": "bank" },
|
||||
"shipwreck" : { "index" :85, "handler": "bank" },
|
||||
"derelictShip" : { "index" :24, "handler": "bank" },
|
||||
"dragonUtopia" : { "index" :25, "handler": "bank" },
|
||||
|
||||
"pandoraBox" : { "id" :6, "handler": "pandora" },
|
||||
"event" : { "id" :26, "handler": "event" },
|
||||
"pandoraBox" : { "index" :6, "handler": "pandora" },
|
||||
"event" : { "index" :26, "handler": "event" },
|
||||
|
||||
"redwoodObservatory" : { "id" :58, "handler": "observatory" },
|
||||
"pillarOfFire" : { "id" :60, "handler": "observatory" },
|
||||
"coverOfDarkness" : { "id" :15, "handler": "observatory" },
|
||||
"redwoodObservatory" : { "index" :58, "handler": "observatory" },
|
||||
"pillarOfFire" : { "index" :60, "handler": "observatory" },
|
||||
"coverOfDarkness" : { "index" :15, "handler": "observatory" },
|
||||
|
||||
"subterraneanGate" : { "id" :103, "handler": "teleport" },
|
||||
"whirlpool" : { "id" :111, "handler": "teleport" },
|
||||
"subterraneanGate" : { "index" :103, "handler": "teleport" },
|
||||
"whirlpool" : { "index" :111, "handler": "teleport" },
|
||||
|
||||
"refugeeCamp" : { "id" :78, "handler": "dwelling" },
|
||||
"warMachineFactory" : { "id" :106, "handler": "dwelling" },
|
||||
"refugeeCamp" : { "index" :78, "handler": "dwelling" },
|
||||
"warMachineFactory" : { "index" :106, "handler": "dwelling" },
|
||||
|
||||
"shrineOfMagicLevel1" : { "id" :88, "handler": "shrine" },
|
||||
"shrineOfMagicLevel2" : { "id" :89, "handler": "shrine" },
|
||||
"shrineOfMagicLevel3" : { "id" :90, "handler": "shrine" },
|
||||
"shrineOfMagicLevel1" : { "index" :88, "handler": "shrine" },
|
||||
"shrineOfMagicLevel2" : { "index" :89, "handler": "shrine" },
|
||||
"shrineOfMagicLevel3" : { "index" :90, "handler": "shrine" },
|
||||
|
||||
"eyeOfTheMagi" : { "id" :27, "handler": "magi" },
|
||||
"hutOfTheMagi" : { "id" :37, "handler": "magi" },
|
||||
"eyeOfTheMagi" : { "index" :27, "handler": "magi" },
|
||||
"hutOfTheMagi" : { "index" :37, "handler": "magi" },
|
||||
|
||||
"lighthouse" : { "id" :42, "handler": "lighthouse" },
|
||||
"magicWell" : { "id" :49, "handler": "magicWell" },
|
||||
"obelisk" : { "id" :57, "handler": "obelisk" },
|
||||
"oceanBottle" : { "id" :59, "handler": "sign" },
|
||||
"prison" : { "id" :62, "handler": "hero" },
|
||||
"pyramid" : { "id" :63, "handler": "pyramid" },
|
||||
"scholar" : { "id" :81, "handler": "scholar" },
|
||||
"shipyard" : { "id" :87, "handler": "shipyard" },
|
||||
"sign" : { "id" :91, "handler": "sign" },
|
||||
"sirens" : { "id" :92, "handler": "siren" },
|
||||
"denOfThieves" : { "id" :97, "handler": "denOfThieves" },
|
||||
"university" : { "id" :104, "handler": "university" },
|
||||
"witchHut" : { "id" :113, "handler": "witch" },
|
||||
"questGuard" : { "id" :215, "handler": "questGuard" },
|
||||
"lighthouse" : { "index" :42, "handler": "lighthouse" },
|
||||
"magicWell" : { "index" :49, "handler": "magicWell" },
|
||||
"obelisk" : { "index" :57, "handler": "obelisk" },
|
||||
"oceanBottle" : { "index" :59, "handler": "sign" },
|
||||
"prison" : { "index" :62, "handler": "hero" },
|
||||
"pyramid" : { "index" :63, "handler": "pyramid" },
|
||||
"scholar" : { "index" :81, "handler": "scholar" },
|
||||
"shipyard" : { "index" :87, "handler": "shipyard" },
|
||||
"sign" : { "index" :91, "handler": "sign" },
|
||||
"sirens" : { "index" :92, "handler": "siren" },
|
||||
"denOfThieves" : { "index" :97, "handler": "denOfThieves" },
|
||||
"university" : { "index" :104, "handler": "university" },
|
||||
"witchHut" : { "index" :113, "handler": "witch" },
|
||||
"questGuard" : { "index" :215, "handler": "questGuard" },
|
||||
|
||||
/// Random objects
|
||||
"randomResource" : { "id" :76, "handler": "resource" },
|
||||
"randomTown" : { "id" :77, "handler": "town" },
|
||||
"randomHero" : { "id" :70, "handler": "hero" },
|
||||
"randomResource" : { "index" :76, "handler": "resource" },
|
||||
"randomTown" : { "index" :77, "handler": "town" },
|
||||
"randomHero" : { "index" :70, "handler": "hero" },
|
||||
|
||||
"randomDwelling" : { "id" :216, "handler": "dwelling" },
|
||||
"randomDwelling" : { "index" :216, "handler": "dwelling" },
|
||||
|
||||
"randomArtifact" : { "id" :65, "handler": "artifact" },
|
||||
"randomArtifactTreasure" : { "id" :66, "handler": "artifact" },
|
||||
"randomArtifactMinor" : { "id" :67, "handler": "artifact" },
|
||||
"randomArtifactMajor" : { "id" :68, "handler": "artifact" },
|
||||
"randomArtifactRelic" : { "id" :69, "handler": "artifact" },
|
||||
"randomArtifact" : { "index" :65, "handler": "artifact" },
|
||||
"randomArtifactTreasure" : { "index" :66, "handler": "artifact" },
|
||||
"randomArtifactMinor" : { "index" :67, "handler": "artifact" },
|
||||
"randomArtifactMajor" : { "index" :68, "handler": "artifact" },
|
||||
"randomArtifactRelic" : { "index" :69, "handler": "artifact" },
|
||||
|
||||
"randomMonster" : { "id" :71, "handler": "monster" },
|
||||
"randomMonsterLevel1" : { "id" :72, "handler": "monster" },
|
||||
"randomMonsterLevel2" : { "id" :73, "handler": "monster" },
|
||||
"randomMonsterLevel3" : { "id" :74, "handler": "monster" },
|
||||
"randomMonsterLevel4" : { "id" :75, "handler": "monster" },
|
||||
"randomMonsterLevel5" : { "id" :162, "handler": "monster" },
|
||||
"randomMonsterLevel6" : { "id" :163, "handler": "monster" },
|
||||
"randomMonsterLevel7" : { "id" :164, "handler": "monster" },
|
||||
"randomMonster" : { "index" :71, "handler": "monster" },
|
||||
"randomMonsterLevel1" : { "index" :72, "handler": "monster" },
|
||||
"randomMonsterLevel2" : { "index" :73, "handler": "monster" },
|
||||
"randomMonsterLevel3" : { "index" :74, "handler": "monster" },
|
||||
"randomMonsterLevel4" : { "index" :75, "handler": "monster" },
|
||||
"randomMonsterLevel5" : { "index" :162, "handler": "monster" },
|
||||
"randomMonsterLevel6" : { "index" :163, "handler": "monster" },
|
||||
"randomMonsterLevel7" : { "index" :164, "handler": "monster" },
|
||||
|
||||
/// Classes without dedicated object
|
||||
"hillFort" : { "id" :35, "handler": "generic" },
|
||||
"grail" : { "id" :36, "handler": "generic" },
|
||||
"tavern" : { "id" :95, "handler": "generic" },
|
||||
"sanctuary" : { "id" :80, "handler": "generic" },
|
||||
"hillFort" : { "index" :35, "handler": "generic" },
|
||||
"grail" : { "index" :36, "handler": "generic" },
|
||||
"tavern" : { "index" :95, "handler": "generic" },
|
||||
"sanctuary" : { "index" :80, "handler": "generic" },
|
||||
|
||||
/// Passive objects, terrain overlays
|
||||
"cursedGround" : { "id" :21, "handler": "generic" },
|
||||
"magicPlains" : { "id" :46, "handler": "generic" },
|
||||
"swampFoliage" : { "id" :211, "handler": "generic" },
|
||||
"cloverField" : { "id" :222, "handler": "generic" },
|
||||
"cursedGround" : { "id" :223, "handler": "generic" },
|
||||
"evilFog" : { "id" :224, "handler": "generic" },
|
||||
"favorableWinds" : { "id" :225, "handler": "generic" },
|
||||
"fieryFields" : { "id" :226, "handler": "generic" },
|
||||
"holyGround" : { "id" :227, "handler": "generic" },
|
||||
"lucidPools" : { "id" :228, "handler": "generic" },
|
||||
"magicClouds" : { "id" :229, "handler": "generic" },
|
||||
"magicPlains" : { "id" :230, "handler": "generic" },
|
||||
"rocklands" : { "id" :231, "handler": "generic" }
|
||||
"cursedGround" : { "index" :21, "handler": "generic" },
|
||||
"magicPlains" : { "index" :46, "handler": "generic" },
|
||||
"swampFoliage" : { "index" :211, "handler": "generic" },
|
||||
"cloverField" : { "index" :222, "handler": "generic" },
|
||||
"cursedGroundDUPLICATE" : { "index" :223, "handler": "generic" },
|
||||
"evilFog" : { "index" :224, "handler": "generic" },
|
||||
"favorableWinds" : { "index" :225, "handler": "generic" },
|
||||
"fieryFields" : { "index" :226, "handler": "generic" },
|
||||
"holyGround" : { "index" :227, "handler": "generic" },
|
||||
"lucidPools" : { "index" :228, "handler": "generic" },
|
||||
"magicClouds" : { "index" :229, "handler": "generic" },
|
||||
"magicPlainsDUPLICATE" : { "index" :230, "handler": "generic" },
|
||||
"rocklands" : { "index" :231, "handler": "generic" },
|
||||
|
||||
/// Decorations
|
||||
"cactus" : { "id" :116, "handler": "generic" },
|
||||
"canyon" : { "id" :117, "handler": "generic" },
|
||||
"crater" : { "id" :118, "handler": "generic" },
|
||||
"deadVegetation" : { "id" :119, "handler": "generic" },
|
||||
"flowers" : { "id" :120, "handler": "generic" },
|
||||
"frozenLake" : { "id" :121, "handler": "generic" },
|
||||
"hole" : { "id" :124, "handler": "generic" },
|
||||
"kelp" : { "id" :125, "handler": "generic" },
|
||||
"lake" : { "id" :126, "handler": "generic" },
|
||||
"lavaFlow" : { "id" :127, "handler": "generic" },
|
||||
"lavaLake" : { "id" :128, "handler": "generic" },
|
||||
"mushrooms" : { "id" :129, "handler": "generic" },
|
||||
"log" : { "id" :130, "handler": "generic" },
|
||||
"mandrake" : { "id" :131, "handler": "generic" },
|
||||
"moss" : { "id" :132, "handler": "generic" },
|
||||
"mound" : { "id" :133, "handler": "generic" },
|
||||
"mountain" : { "id" :134, "handler": "generic" },
|
||||
"oakTrees" : { "id" :135, "handler": "generic" },
|
||||
"outcropping" : { "id" :136, "handler": "generic" },
|
||||
"pineTrees" : { "id" :137, "handler": "generic" },
|
||||
"riverDelta" : { "id" :143, "handler": "generic" },
|
||||
"rock" : { "id" :147, "handler": "generic" },
|
||||
"sandDune" : { "id" :148, "handler": "generic" },
|
||||
"sandPit" : { "id" :149, "handler": "generic" },
|
||||
"shrub" : { "id" :150, "handler": "generic" },
|
||||
"skull" : { "id" :151, "handler": "generic" },
|
||||
"stump" : { "id" :153, "handler": "generic" },
|
||||
"trees" : { "id" :155, "handler": "generic" },
|
||||
"volcano" : { "id" :158, "handler": "generic" },
|
||||
"reef" : { "id" :161, "handler": "generic" },
|
||||
"lake" : { "id" :177, "handler": "generic" },
|
||||
"trees" : { "id" :199, "handler": "generic" },
|
||||
"desertHills" : { "id" :206, "handler": "generic" },
|
||||
"dirtHills" : { "id" :207, "handler": "generic" },
|
||||
"grassHills" : { "id" :208, "handler": "generic" },
|
||||
"roughHills" : { "id" :209, "handler": "generic" },
|
||||
"subterraneanRocks" : { "id" :210, "handler": "generic" },
|
||||
"cactus" : { "index" :116, "handler": "generic" },
|
||||
"canyon" : { "index" :117, "handler": "generic" },
|
||||
"crater" : { "index" :118, "handler": "generic" },
|
||||
"deadVegetation" : { "index" :119, "handler": "generic" },
|
||||
"flowers" : { "index" :120, "handler": "generic" },
|
||||
"frozenLake" : { "index" :121, "handler": "generic" },
|
||||
"hole" : { "index" :124, "handler": "generic" },
|
||||
"kelp" : { "index" :125, "handler": "generic" },
|
||||
"lake" : { "index" :126, "handler": "generic" },
|
||||
"lavaFlow" : { "index" :127, "handler": "generic" },
|
||||
"lavaLake" : { "index" :128, "handler": "generic" },
|
||||
"mushrooms" : { "index" :129, "handler": "generic" },
|
||||
"log" : { "index" :130, "handler": "generic" },
|
||||
"mandrake" : { "index" :131, "handler": "generic" },
|
||||
"moss" : { "index" :132, "handler": "generic" },
|
||||
"mound" : { "index" :133, "handler": "generic" },
|
||||
"mountain" : { "index" :134, "handler": "generic" },
|
||||
"oakTrees" : { "index" :135, "handler": "generic" },
|
||||
"outcropping" : { "index" :136, "handler": "generic" },
|
||||
"pineTrees" : { "index" :137, "handler": "generic" },
|
||||
"riverDelta" : { "index" :143, "handler": "generic" },
|
||||
"rock" : { "index" :147, "handler": "generic" },
|
||||
"sandDune" : { "index" :148, "handler": "generic" },
|
||||
"sandPit" : { "index" :149, "handler": "generic" },
|
||||
"shrub" : { "index" :150, "handler": "generic" },
|
||||
"skull" : { "index" :151, "handler": "generic" },
|
||||
"stump" : { "index" :153, "handler": "generic" },
|
||||
"trees" : { "index" :155, "handler": "generic" },
|
||||
"volcano" : { "index" :158, "handler": "generic" },
|
||||
"reef" : { "index" :161, "handler": "generic" },
|
||||
"lakeDUPLICATE" : { "index" :177, "handler": "generic" },
|
||||
"treesDUPLICATE" : { "index" :199, "handler": "generic" },
|
||||
"desertHills" : { "index" :206, "handler": "generic" },
|
||||
"dirtHills" : { "index" :207, "handler": "generic" },
|
||||
"grassHills" : { "index" :208, "handler": "generic" },
|
||||
"roughHills" : { "index" :209, "handler": "generic" },
|
||||
"subterraneanRocks" : { "index" :210, "handler": "generic" }
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
// subtype: artifact ID
|
||||
"artifact" : {
|
||||
"id" :5,
|
||||
"index" :5,
|
||||
"handler": "artifact",
|
||||
"base" : {
|
||||
"base" : {
|
||||
@ -17,7 +17,7 @@
|
||||
|
||||
// subtype: hero CLASS (not hero).
|
||||
"hero" : {
|
||||
"id" :34,
|
||||
"index" :34,
|
||||
"handler": "hero",
|
||||
"base" : {
|
||||
"base" : {
|
||||
@ -29,8 +29,8 @@
|
||||
|
||||
// subtype: creatures
|
||||
"monster" : {
|
||||
"id" :54,
|
||||
"handler": "monster"
|
||||
"index" :54,
|
||||
"handler": "monster",
|
||||
"base" : {
|
||||
"base" : {
|
||||
"visitableFrom" : [ "+++", "+-+", "+++" ],
|
||||
@ -41,7 +41,7 @@
|
||||
|
||||
// subtype: resource ID
|
||||
"resource" : {
|
||||
"id" :79,
|
||||
"index" :79,
|
||||
"handler": "resource",
|
||||
"base" : {
|
||||
"base" : {
|
||||
@ -53,7 +53,7 @@
|
||||
|
||||
// subtype: faction
|
||||
"town" : {
|
||||
"id" :98,
|
||||
"index" :98,
|
||||
"handler": "town",
|
||||
"base" : {
|
||||
"base" : {
|
||||
@ -72,7 +72,7 @@
|
||||
|
||||
// subtype: one of 3 possible boats
|
||||
"boat" : {
|
||||
"id" :8,
|
||||
"index" :8,
|
||||
"handler": "boat",
|
||||
"base" : {
|
||||
"base" : {
|
||||
@ -83,41 +83,41 @@
|
||||
},
|
||||
|
||||
// subtype: color of guard
|
||||
"borderGuard" : { "id" :9, "handler": "borderGuard" },
|
||||
"borderGate" : { "id" :212, "handler": "borderGate" },
|
||||
"keymasterTent" : { "id" :10, "handler": "keymaster" },
|
||||
"borderGuard" : { "index" :9, "handler": "borderGuard" },
|
||||
"borderGate" : { "index" :212, "handler": "borderGate" },
|
||||
"keymasterTent" : { "index" :10, "handler": "keymaster" },
|
||||
|
||||
// subtype: different content
|
||||
"creatureBank" : { "id" :16, "handler": "bank" },
|
||||
"creatureBank" : { "index" :16, "handler": "bank" },
|
||||
|
||||
// subtype: different revealed areas
|
||||
"cartographer" : { "id" :13, "handler": "cartographer" },
|
||||
"cartographer" : { "index" :13, "handler": "cartographer" },
|
||||
|
||||
// subtype: 0 = normal, 1 = anti-magic
|
||||
"garrisonHorizontal" : { "id" :33, "handler": "garrison" },
|
||||
"garrisonVertical" : { "id" :219, "handler": "garrison" },
|
||||
"garrisonHorizontal" : { "index" :33, "handler": "garrison" },
|
||||
"garrisonVertical" : { "index" :219, "handler": "garrison" },
|
||||
|
||||
// Subtype: paired monoliths
|
||||
"monolithOneWayEntrance" : { "id" :43, "handler": "teleport" },
|
||||
"monolithOneWayExit" : { "id" :44, "handler": "teleport" },
|
||||
"monolithTwoWay" : { "id" :45, "handler": "teleport" },
|
||||
"monolithOneWayEntrance" : { "index" :43, "handler": "teleport" },
|
||||
"monolithOneWayExit" : { "index" :44, "handler": "teleport" },
|
||||
"monolithTwoWay" : { "index" :45, "handler": "teleport" },
|
||||
|
||||
// subtype: resource ID
|
||||
"mine" : { "id" :53, "handler": "mine" },
|
||||
"abandonedMine" : { "id" :220, "handler": "mine" },
|
||||
"mine" : { "index" :53, "handler": "mine" },
|
||||
"abandonedMine" : { "index" :220, "handler": "mine" },
|
||||
|
||||
// subtype: different appearance. That's all?
|
||||
"seerHut" : { "id" :83, "handler": "seerHut" },
|
||||
"seerHut" : { "index" :83, "handler": "seerHut" },
|
||||
|
||||
// subtype: level
|
||||
"randomDwellingLvl" : { "id" :217, "handler": "dwelling" },
|
||||
"randomDwellingLvl" : { "index" :217, "handler": "dwelling" },
|
||||
|
||||
// subtype: faction ID
|
||||
"randomDwellingFaction" : { "id" :218, "handler": "dwelling" },
|
||||
"randomDwellingFaction" : { "index" :218, "handler": "dwelling" },
|
||||
|
||||
// subtype: not well defined, describes various dwellings that can be placed as random
|
||||
"creatureGeneratorCommon" : {
|
||||
"id" :17,
|
||||
"index" :17,
|
||||
"handler": "dwelling",
|
||||
"base" : {
|
||||
"base" : {
|
||||
@ -128,9 +128,9 @@
|
||||
},
|
||||
|
||||
// subtype: unique special dwellings - golem factory, elemental conflux
|
||||
"creatureGeneratorSpecial" : { "id" :20, "handler": "dwelling" },
|
||||
"creatureGeneratorSpecial" : { "index" :20, "handler": "dwelling" },
|
||||
|
||||
// don't have subtypes (at least now), but closely connected to this objects
|
||||
"spellScroll" : { "id" :93, "handler": "artifact" },
|
||||
"heroPlaceholder" : { "id" :214, "handler": "heroPlaceholder" }
|
||||
"spellScroll" : { "index" :93, "handler": "artifact" },
|
||||
"heroPlaceholder" : { "index" :214, "handler": "heroPlaceholder" }
|
||||
}
|
||||
|
@ -1,44 +1,44 @@
|
||||
{
|
||||
/// These are objects that covered by concept of "configurable object"
|
||||
/// Most or even all of their configuration located in this file
|
||||
"magicSpring" : { "id" :48, "handler": "magicSpring" },
|
||||
"magicSpring" : { "index" :48, "handler": "magicSpring" },
|
||||
|
||||
"mysticalGarden" : { "id" :55, "handler": "oncePerWeek" },
|
||||
"windmill" : { "id" :112, "handler": "oncePerWeek" },
|
||||
"waterWheel" : { "id" :109, "handler": "oncePerWeek" },
|
||||
"mysticalGarden" : { "index" :55, "handler": "oncePerWeek" },
|
||||
"windmill" : { "index" :112, "handler": "oncePerWeek" },
|
||||
"waterWheel" : { "index" :109, "handler": "oncePerWeek" },
|
||||
|
||||
"leanTo" : { "id" :39, "handler": "onceVisitable" },
|
||||
"corpse" : { "id" :22, "handler": "onceVisitable" },
|
||||
"wagon" : { "id" :105, "handler": "onceVisitable" },
|
||||
"warriorTomb" : { "id" :108, "handler": "onceVisitable" },
|
||||
"leanTo" : { "index" :39, "handler": "onceVisitable" },
|
||||
"corpse" : { "index" :22, "handler": "onceVisitable" },
|
||||
"wagon" : { "index" :105, "handler": "onceVisitable" },
|
||||
"warriorTomb" : { "index" :108, "handler": "onceVisitable" },
|
||||
|
||||
"campfire" : { "id" :12, "handler": "pickable" },
|
||||
"flotsam" : { "id" :29, "handler": "pickable" },
|
||||
"seaChest" : { "id" :82, "handler": "pickable" },
|
||||
"shipwreckSurvivor" : { "id" :86, "handler": "pickable" },
|
||||
"treasureChest" : { "id" :101, "handler": "pickable" },
|
||||
"campfire" : { "index" :12, "handler": "pickable" },
|
||||
"flotsam" : { "index" :29, "handler": "pickable" },
|
||||
"seaChest" : { "index" :82, "handler": "pickable" },
|
||||
"shipwreckSurvivor" : { "index" :86, "handler": "pickable" },
|
||||
"treasureChest" : { "index" :101, "handler": "pickable" },
|
||||
|
||||
"arena" : { "id" :4, "handler": "oncePerHero" },
|
||||
"marlettoTower" : { "id" :23, "handler": "oncePerHero" },
|
||||
"gardenOfRevelation" : { "id" :32, "handler": "oncePerHero" },
|
||||
"libraryOfEnlightenment" : { "id" :41, "handler": "oncePerHero" },
|
||||
"mercenaryCamp" : { "id" :51, "handler": "oncePerHero" },
|
||||
"starAxis" : { "id" :61, "handler": "oncePerHero" },
|
||||
"learningStone" : { "id" :100, "handler": "oncePerHero" },
|
||||
"treeOfKnowledge" : { "id" :102, "handler": "oncePerHero" },
|
||||
"schoolOfMagic" : { "id" :47, "handler": "oncePerHero" },
|
||||
"schoolOfWar" : { "id" :107, "handler": "oncePerHero" },
|
||||
"arena" : { "index" :4, "handler": "oncePerHero" },
|
||||
"marlettoTower" : { "index" :23, "handler": "oncePerHero" },
|
||||
"gardenOfRevelation" : { "index" :32, "handler": "oncePerHero" },
|
||||
"libraryOfEnlightenment" : { "index" :41, "handler": "oncePerHero" },
|
||||
"mercenaryCamp" : { "index" :51, "handler": "oncePerHero" },
|
||||
"starAxis" : { "index" :61, "handler": "oncePerHero" },
|
||||
"learningStone" : { "index" :100, "handler": "oncePerHero" },
|
||||
"treeOfKnowledge" : { "index" :102, "handler": "oncePerHero" },
|
||||
"schoolOfMagic" : { "index" :47, "handler": "oncePerHero" },
|
||||
"schoolOfWar" : { "index" :107, "handler": "oncePerHero" },
|
||||
|
||||
"buoy" : { "id" :11, "handler": "bonusingObject" },
|
||||
"swanPond" : { "id" :14, "handler": "bonusingObject" },
|
||||
"faerieRing" : { "id" :28, "handler": "bonusingObject" },
|
||||
"fountainOfFortune" : { "id" :30, "handler": "bonusingObject" },
|
||||
"fountainOfYouth" : { "id" :31, "handler": "bonusingObject" },
|
||||
"idolOfFortune" : { "id" :38, "handler": "bonusingObject" },
|
||||
"mermaids" : { "id" :52, "handler": "bonusingObject" },
|
||||
"oasis" : { "id" :56, "handler": "bonusingObject" },
|
||||
"stables" : { "id" :94, "handler": "bonusingObject" },
|
||||
"temple" : { "id" :96, "handler": "bonusingObject" },
|
||||
"rallyFlag" : { "id" :64, "handler": "bonusingObject" },
|
||||
"wateringHole" : { "id" :110, "handler": "bonusingObject" },
|
||||
"buoy" : { "index" :11, "handler": "bonusingObject" },
|
||||
"swanPond" : { "index" :14, "handler": "bonusingObject" },
|
||||
"faerieRing" : { "index" :28, "handler": "bonusingObject" },
|
||||
"fountainOfFortune" : { "index" :30, "handler": "bonusingObject" },
|
||||
"fountainOfYouth" : { "index" :31, "handler": "bonusingObject" },
|
||||
"idolOfFortune" : { "index" :38, "handler": "bonusingObject" },
|
||||
"mermaids" : { "index" :52, "handler": "bonusingObject" },
|
||||
"oasis" : { "index" :56, "handler": "bonusingObject" },
|
||||
"stables" : { "index" :94, "handler": "bonusingObject" },
|
||||
"temple" : { "index" :96, "handler": "bonusingObject" },
|
||||
"rallyFlag" : { "index" :64, "handler": "bonusingObject" },
|
||||
"wateringHole" : { "index" :110, "handler": "bonusingObject" },
|
||||
}
|
||||
|
@ -3,18 +3,10 @@
|
||||
"$schema": "http://json-schema.org/draft-04/schema",
|
||||
"title" : "VCMI map object template format",
|
||||
"description" : "Description of map object tempate that describes appearence of object instance",
|
||||
"required": ["basebase", "base", "animation", "mask" ],
|
||||
"required": [ "animation", "mask" ],
|
||||
|
||||
"additionalProperties" : false,
|
||||
"properties":{
|
||||
"basebase": {
|
||||
"type" : "number",
|
||||
"description": "Base object type, e.g. town or hero"
|
||||
},
|
||||
"base": {
|
||||
"type" : "number",
|
||||
"description": "Object subtype, e.g. Castle, Rampart, Cleric, Demon"
|
||||
},
|
||||
"animation": {
|
||||
"type" : "string",
|
||||
"description": "Path to def file with animation of this object",
|
||||
|
@ -658,6 +658,7 @@ void CArtHandler::afterLoadFinalization()
|
||||
|
||||
// add new template.
|
||||
// Necessary for objects added via mods that don't have any templates in H3
|
||||
VLC->objtypeh->createObject(art->Name(), JsonNode(), Obj::ARTIFACT, art->id.num);
|
||||
VLC->objtypeh->getHandlerFor(Obj::ARTIFACT, art->id)->addTemplate(base);
|
||||
}
|
||||
}
|
||||
|
@ -333,11 +333,12 @@ bool ObjectTemplate::canBePlacedAt(ETerrainType terrain) const
|
||||
|
||||
CObjectClassesHandler::CObjectClassesHandler()
|
||||
{
|
||||
// list of all known handlers, hardcoded for now since the only way to add new objects is via C++ code
|
||||
handlerConstructors["configurable"] = std::make_shared<CObjectWithRewardConstructor>;
|
||||
|
||||
#define SET_HANDLER_CLASS(STRING, CLASSNAME) handlerConstructors[STRING] = std::make_shared<CLASSNAME>;
|
||||
#define SET_HANDLER(STRING, TYPENAME) handlerConstructors[STRING] = std::make_shared<CDefaultObjectTypeHandler<TYPENAME> >
|
||||
|
||||
// list of all known handlers, hardcoded for now since the only way to add new objects is via C++ code
|
||||
SET_HANDLER_CLASS("configurable", CObjectWithRewardConstructor);
|
||||
|
||||
SET_HANDLER("", CGObjectInstance);
|
||||
SET_HANDLER("generic", CGObjectInstance);
|
||||
|
||||
@ -385,39 +386,34 @@ CObjectClassesHandler::CObjectClassesHandler()
|
||||
SET_HANDLER("oncePerWeek", CGVisitableOPW);
|
||||
SET_HANDLER("witch", CGWitchHut);
|
||||
|
||||
#undef SET_HANDLER_CLASS
|
||||
#undef SET_HANDLER
|
||||
}
|
||||
|
||||
static std::vector<JsonNode> readTextFile(std::string path)
|
||||
template<typename Container>
|
||||
void readTextFile(Container objects, std::string path)
|
||||
{
|
||||
//TODO
|
||||
CLegacyConfigParser parser(path);
|
||||
size_t totalNumber = parser.readNumber(); // first line contains number of objects to read and nothing else
|
||||
parser.endLine();
|
||||
|
||||
for (size_t i=0; i<totalNumber; i++)
|
||||
{
|
||||
ObjectTemplate templ;
|
||||
templ.readTxt(parser);
|
||||
parser.endLine();
|
||||
typename Container::key_type key(templ.id.num, templ.subid);
|
||||
objects.insert(std::make_pair(key, templ));
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<JsonNode> CObjectClassesHandler::loadLegacyData(size_t dataSize)
|
||||
{
|
||||
objects.resize(dataSize);
|
||||
readTextFile(legacyTemplates, "Data/Objects.txt");
|
||||
readTextFile(legacyTemplates, "Data/Heroes.txt");
|
||||
|
||||
std::vector<JsonNode> ret(dataSize);// create storage for 256 objects
|
||||
|
||||
auto parseFile = [&](std::string filename)
|
||||
{
|
||||
auto entries = readTextFile(filename);
|
||||
for (JsonNode & entry : entries)
|
||||
{
|
||||
si32 id = entry["basebase"].Float();
|
||||
si32 subid = entry["base"].Float();
|
||||
|
||||
entry.Struct().erase("basebase");
|
||||
entry.Struct().erase("base");
|
||||
|
||||
if (ret[id].Vector().size() <= subid)
|
||||
ret[id].Vector().resize(subid+1);
|
||||
ret[id]["legacyTypes"].Vector()[subid][entry["animation"].String()].swap(entry);
|
||||
}
|
||||
};
|
||||
|
||||
//parseFile("Data/Objects.txt");
|
||||
//parseFile("Data/Heroes.txt");
|
||||
assert(dataSize == 256);
|
||||
|
||||
CLegacyConfigParser parser("Data/ObjNames.txt");
|
||||
for (size_t i=0; i<256; i++)
|
||||
@ -428,16 +424,48 @@ std::vector<JsonNode> CObjectClassesHandler::loadLegacyData(size_t dataSize)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// selects preferred ID (or subID) for new object
|
||||
template<typename Map>
|
||||
si32 selectNextID(const JsonNode & fixedID, const Map & map, si32 defaultID)
|
||||
{
|
||||
if (!fixedID.isNull() && fixedID.Float() < defaultID)
|
||||
return fixedID.Float(); // H3M object with fixed ID
|
||||
|
||||
if (map.empty())
|
||||
return defaultID; // no objects loaded, keep gap for H3M objects
|
||||
if (map.rbegin()->first > defaultID)
|
||||
return map.rbegin()->first + 1; // some modded objects loaded, return next available
|
||||
|
||||
return defaultID; // some H3M objects loaded, first modded found
|
||||
}
|
||||
|
||||
void CObjectClassesHandler::loadObjectEntry(const JsonNode & entry, ObjectContainter * obj)
|
||||
{
|
||||
auto handler = handlerConstructors.at(obj->handlerName)();
|
||||
handler->init(entry);
|
||||
|
||||
si32 id = selectNextID(entry["index"], obj->objects, 256);
|
||||
handler->setType(obj->id, id);
|
||||
|
||||
if (handler->getTemplates().empty())
|
||||
{
|
||||
auto range = legacyTemplates.equal_range(std::make_pair(obj->id, si32(entry["index"].Float())));
|
||||
for (auto & templ : boost::make_iterator_range(range.first, range.second))
|
||||
handler->addTemplate(templ.second);
|
||||
}
|
||||
obj->objects[id] = handler;
|
||||
}
|
||||
|
||||
CObjectClassesHandler::ObjectContainter * CObjectClassesHandler::loadFromJson(const JsonNode & json)
|
||||
{
|
||||
auto obj = new ObjectContainter();
|
||||
obj->name = json["name"].String();
|
||||
obj->handlerName = json["handler"].String();
|
||||
obj->base = json["base"];
|
||||
obj->base = json["base"]; // FIXME: when this data will be actually merged?
|
||||
obj->id = selectNextID(json["index"], objects, 256);
|
||||
for (auto entry : json["types"].Struct())
|
||||
{
|
||||
auto handler = handlerConstructors.at(obj->handlerName)();
|
||||
handler->init(entry.second);
|
||||
loadObjectEntry(entry.second, obj);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
@ -445,8 +473,7 @@ CObjectClassesHandler::ObjectContainter * CObjectClassesHandler::loadFromJson(co
|
||||
void CObjectClassesHandler::loadObject(std::string scope, std::string name, const JsonNode & data)
|
||||
{
|
||||
auto object = loadFromJson(data);
|
||||
object->id = objects.size();
|
||||
objects.push_back(object);
|
||||
objects[object->id] = object;
|
||||
|
||||
VLC->modh->identifiers.registerObject(scope, "object", name, object->id);
|
||||
}
|
||||
@ -454,7 +481,6 @@ void CObjectClassesHandler::loadObject(std::string scope, std::string name, cons
|
||||
void CObjectClassesHandler::loadObject(std::string scope, std::string name, const JsonNode & data, size_t index)
|
||||
{
|
||||
auto object = loadFromJson(data);
|
||||
object->id = index;
|
||||
|
||||
assert(objects[index] == nullptr); // ensure that this id was not loaded before
|
||||
objects[index] = object;
|
||||
@ -462,6 +488,18 @@ void CObjectClassesHandler::loadObject(std::string scope, std::string name, cons
|
||||
VLC->modh->identifiers.registerObject(scope, "object", name, object->id);
|
||||
}
|
||||
|
||||
void CObjectClassesHandler::createObject(std::string name, JsonNode config, si32 ID, boost::optional<si32> subID)
|
||||
{
|
||||
assert(objects.count(ID));
|
||||
if (subID)
|
||||
{
|
||||
assert(objects.at(ID)->objects.count(subID.get()) == 0);
|
||||
assert(config["index"].isNull());
|
||||
config["index"].Float() = subID.get();
|
||||
}
|
||||
loadObjectEntry(config, objects[ID]);
|
||||
}
|
||||
|
||||
std::vector<bool> CObjectClassesHandler::getDefaultAllowed() const
|
||||
{
|
||||
return std::vector<bool>(); //TODO?
|
||||
@ -469,15 +507,21 @@ std::vector<bool> CObjectClassesHandler::getDefaultAllowed() const
|
||||
|
||||
TObjectTypeHandler CObjectClassesHandler::getHandlerFor(si32 type, si32 subtype) const
|
||||
{
|
||||
if (objects.size() > type)
|
||||
if (objects.count(type))
|
||||
{
|
||||
if (objects.at(type)->objects.count(subtype))
|
||||
return objects.at(type)->objects.at(subtype);
|
||||
}
|
||||
logGlobal->errorStream() << "Failed to find object of type " << type << ":" << subtype;
|
||||
assert(0); // FIXME: throw error?
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CObjectClassesHandler::afterLoadFinalization()
|
||||
{
|
||||
legacyTemplates.clear(); // whatever left there is no longer needed
|
||||
}
|
||||
|
||||
std::string CObjectClassesHandler::getObjectName(si32 type) const
|
||||
{
|
||||
assert(objects.count(type));
|
||||
|
@ -110,12 +110,10 @@ class AObjectTypeHandler
|
||||
|
||||
std::vector<ObjectTemplate> templates;
|
||||
protected:
|
||||
void setType(si32 type, si32 subtype);
|
||||
|
||||
virtual bool objectFilter(const CGObjectInstance *, const ObjectTemplate &) const;
|
||||
public:
|
||||
/// returns true if type is not configurable and new objects can be created without valid config
|
||||
virtual bool confFree();
|
||||
void setType(si32 type, si32 subtype);
|
||||
|
||||
/// loads templates from Json structure using fields "base" and "templates"
|
||||
virtual void init(const JsonNode & input);
|
||||
@ -193,12 +191,18 @@ class DLL_LINKAGE CObjectClassesHandler : public IHandlerBase
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::multimap<std::pair<si32, si32>, ObjectTemplate> TTemplatesContainer;
|
||||
|
||||
/// list of object handlers, each of them handles only one type
|
||||
std::vector<ObjectContainter * > objects;
|
||||
std::map<si32, ObjectContainter * > objects;
|
||||
|
||||
/// map that is filled during contruction with all known handlers. Not serializeable
|
||||
std::map<std::string, std::function<TObjectTypeHandler()> > handlerConstructors;
|
||||
|
||||
/// container with H3 templates, used only during loading
|
||||
TTemplatesContainer legacyTemplates;
|
||||
|
||||
void loadObjectEntry(const JsonNode & entry, ObjectContainter * obj);
|
||||
ObjectContainter * loadFromJson(const JsonNode & json);
|
||||
public:
|
||||
CObjectClassesHandler();
|
||||
@ -208,7 +212,9 @@ public:
|
||||
virtual void loadObject(std::string scope, std::string name, const JsonNode & data);
|
||||
virtual void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index);
|
||||
|
||||
virtual void afterLoadFinalization(){};
|
||||
void createObject(std::string name, JsonNode config, si32 ID, boost::optional<si32> subID = boost::optional<si32>());
|
||||
|
||||
virtual void afterLoadFinalization();
|
||||
|
||||
virtual std::vector<bool> getDefaultAllowed() const;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user