mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-13 19:54:17 +02:00
Merge pull request #1466 from IvanSavenko/translate_adventure_map
Translate adventure map objects
This commit is contained in:
@@ -32,10 +32,6 @@ MapObjectsEvaluator::MapObjectsEvaluator()
|
|||||||
{
|
{
|
||||||
objectDatabase[CompoundMapObjectID(primaryID, secondaryID)] = handler->getAiValue().get();
|
objectDatabase[CompoundMapObjectID(primaryID, secondaryID)] = handler->getAiValue().get();
|
||||||
}
|
}
|
||||||
else if(VLC->objtypeh->getObjGroupAiValue(primaryID) != boost::none) //if value is not initialized - fallback to default value for this object family if it exists
|
|
||||||
{
|
|
||||||
objectDatabase[CompoundMapObjectID(primaryID, secondaryID)] = VLC->objtypeh->getObjGroupAiValue(primaryID).get();
|
|
||||||
}
|
|
||||||
else //some default handling when aiValue not found, objects that require advanced properties (unavailable from handler) get their value calculated in getObjectValue
|
else //some default handling when aiValue not found, objects that require advanced properties (unavailable from handler) get their value calculated in getObjectValue
|
||||||
{
|
{
|
||||||
objectDatabase[CompoundMapObjectID(primaryID, secondaryID)] = 0;
|
objectDatabase[CompoundMapObjectID(primaryID, secondaryID)] = 0;
|
||||||
|
@@ -1371,7 +1371,7 @@ void CMapHandler::getTerrainDescr(const int3 & pos, std::string & out, bool isRM
|
|||||||
|
|
||||||
if(t.hasFavorableWinds())
|
if(t.hasFavorableWinds())
|
||||||
{
|
{
|
||||||
out = CGI->objtypeh->getObjectName(Obj::FAVORABLE_WINDS);
|
out = CGI->objtypeh->getObjectName(Obj::FAVORABLE_WINDS, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const TerrainTile2 & tt = ttiles[pos.z][pos.x][pos.y];
|
const TerrainTile2 & tt = ttiles[pos.z][pos.x][pos.y];
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
"creatureBank" : {
|
"creatureBank" : {
|
||||||
"index" :16,
|
"index" :16,
|
||||||
"handler": "bank",
|
"handler": "bank",
|
||||||
|
"lastReservedIndex" : 6,
|
||||||
"base" : {
|
"base" : {
|
||||||
"sounds" : {
|
"sounds" : {
|
||||||
"visit" : ["ROGUE"]
|
"visit" : ["ROGUE"]
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
"creatureGeneratorCommon" : {
|
"creatureGeneratorCommon" : {
|
||||||
"index" :17,
|
"index" :17,
|
||||||
"handler": "dwelling",
|
"handler": "dwelling",
|
||||||
|
"lastReservedIndex" : 79,
|
||||||
"base" : {
|
"base" : {
|
||||||
"base" : {
|
"base" : {
|
||||||
"visitableFrom" : [ "---", "+++", "+++" ],
|
"visitableFrom" : [ "---", "+++", "+++" ],
|
||||||
@@ -528,6 +529,12 @@
|
|||||||
"creatureGeneratorSpecial" : {
|
"creatureGeneratorSpecial" : {
|
||||||
"index" :20,
|
"index" :20,
|
||||||
"handler": "dwelling",
|
"handler": "dwelling",
|
||||||
|
"lastReservedIndex" : 1,
|
||||||
|
"base" : {
|
||||||
|
"base" : {
|
||||||
|
"visitableFrom" : [ "---", "+++", "+++" ]
|
||||||
|
}
|
||||||
|
},
|
||||||
"types" : {
|
"types" : {
|
||||||
"elementalConflux" : {
|
"elementalConflux" : {
|
||||||
"index" : 0,
|
"index" : 0,
|
||||||
|
@@ -238,8 +238,8 @@
|
|||||||
},
|
},
|
||||||
"types" : {
|
"types" : {
|
||||||
"object" : {
|
"object" : {
|
||||||
"index" : 0 },
|
"index" : 0
|
||||||
"objectWoG" : { "index" : 1 } // WoG object? Present on VCMI Test 2011b
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -341,9 +341,6 @@
|
|||||||
"value" : 3000,
|
"value" : 3000,
|
||||||
"rarity" : 100
|
"rarity" : 100
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"object1":{ //WoG?
|
|
||||||
"index" :1
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -573,9 +570,6 @@
|
|||||||
"value" : 1500,
|
"value" : 1500,
|
||||||
"rarity" : 80
|
"rarity" : 80
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"object1" : { //WoG?
|
|
||||||
"index" : 1
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -1042,10 +1036,5 @@
|
|||||||
"grassHills" : { "index" :208, "handler": "static", "types" : { "object" : { "index" : 0} } },
|
"grassHills" : { "index" :208, "handler": "static", "types" : { "object" : { "index" : 0} } },
|
||||||
"roughHills" : { "index" :209, "handler": "static", "types" : { "object" : { "index" : 0} } },
|
"roughHills" : { "index" :209, "handler": "static", "types" : { "object" : { "index" : 0} } },
|
||||||
"subterraneanRocks" : { "index" :210, "handler": "static", "types" : { "object" : { "index" : 0} } },
|
"subterraneanRocks" : { "index" :210, "handler": "static", "types" : { "object" : { "index" : 0} } },
|
||||||
"swampFoliage" : { "index" :211, "handler": "static", "types" : { "object" : { "index" : 0} } },
|
"swampFoliage" : { "index" :211, "handler": "static", "types" : { "object" : { "index" : 0} } }
|
||||||
|
|
||||||
//These are WoG objects? They are not available in H3
|
|
||||||
"frozenLakeDUPLICATE" : { "index" :172, "handler": "static", "types" : { "object" : { "index" : 0} } },
|
|
||||||
"oakTreesDUPLICATE" : { "index" :186, "handler": "static", "types" : { "object" : { "index" : 0} } },
|
|
||||||
"plant" : { "index" :189, "handler": "static", "types" : { "object" : { "index" : 0} } }
|
|
||||||
}
|
}
|
||||||
|
@@ -23,8 +23,8 @@
|
|||||||
"hero" : {
|
"hero" : {
|
||||||
"index" :34,
|
"index" :34,
|
||||||
"handler": "hero",
|
"handler": "hero",
|
||||||
"defaultAiValue" : 7500,
|
|
||||||
"base" : {
|
"base" : {
|
||||||
|
"aiValue" : 7500,
|
||||||
"base" : {
|
"base" : {
|
||||||
"visitableFrom" : [ "+++", "+-+", "+++" ],
|
"visitableFrom" : [ "+++", "+-+", "+++" ],
|
||||||
"mask" : [ "VVV", "VAV"]
|
"mask" : [ "VVV", "VAV"]
|
||||||
@@ -54,6 +54,7 @@
|
|||||||
"resource" : {
|
"resource" : {
|
||||||
"index" :79,
|
"index" :79,
|
||||||
"handler": "resource",
|
"handler": "resource",
|
||||||
|
"lastReservedIndex" : 6,
|
||||||
"base" : {
|
"base" : {
|
||||||
"base" : {
|
"base" : {
|
||||||
"visitableFrom" : [ "+++", "+-+", "+++" ],
|
"visitableFrom" : [ "+++", "+-+", "+++" ],
|
||||||
@@ -67,8 +68,7 @@
|
|||||||
"sulfur" : { "index" : 3, "aiValue" : 2000, "rmg" : { "value" : 2000, "rarity" : 300 }, "templates" : { "res" : { "animation" : "AVTsulf0.def" } } },
|
"sulfur" : { "index" : 3, "aiValue" : 2000, "rmg" : { "value" : 2000, "rarity" : 300 }, "templates" : { "res" : { "animation" : "AVTsulf0.def" } } },
|
||||||
"crystal" : { "index" : 4, "aiValue" : 2000, "rmg" : { "value" : 2000, "rarity" : 300 }, "templates" : { "res" : { "animation" : "AVTcrys0.def" } } },
|
"crystal" : { "index" : 4, "aiValue" : 2000, "rmg" : { "value" : 2000, "rarity" : 300 }, "templates" : { "res" : { "animation" : "AVTcrys0.def" } } },
|
||||||
"gems" : { "index" : 5, "aiValue" : 2000, "rmg" : { "value" : 2000, "rarity" : 300 }, "templates" : { "res" : { "animation" : "AVTgems0.def" } } },
|
"gems" : { "index" : 5, "aiValue" : 2000, "rmg" : { "value" : 2000, "rarity" : 300 }, "templates" : { "res" : { "animation" : "AVTgems0.def" } } },
|
||||||
"gold" : { "index" : 6, "aiValue" : 750, "rmg" : { "value" : 750, "rarity" : 300 }, "templates" : { "res" : { "animation" : "AVTgold0.def" } } },
|
"gold" : { "index" : 6, "aiValue" : 750, "rmg" : { "value" : 750, "rarity" : 300 }, "templates" : { "res" : { "animation" : "AVTgold0.def" } } }
|
||||||
"mithril" : { "index" : 7, "aiValue" : 3500 } // TODO: move to WoG?
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -76,8 +76,8 @@
|
|||||||
"town" : {
|
"town" : {
|
||||||
"index" :98,
|
"index" :98,
|
||||||
"handler": "town",
|
"handler": "town",
|
||||||
"defaultAiValue" : 20000,
|
|
||||||
"base" : {
|
"base" : {
|
||||||
|
"aiValue" : 20000,
|
||||||
"filters" : {
|
"filters" : {
|
||||||
// village image - fort not present
|
// village image - fort not present
|
||||||
"village" : [ "noneOf", [ "fort" ] ],
|
"village" : [ "noneOf", [ "fort" ] ],
|
||||||
@@ -106,8 +106,9 @@
|
|||||||
"boat" : {
|
"boat" : {
|
||||||
"index" :8,
|
"index" :8,
|
||||||
"handler": "boat",
|
"handler": "boat",
|
||||||
"defaultAiValue" : 0,
|
"lastReservedIndex" : 2,
|
||||||
"base" : {
|
"base" : {
|
||||||
|
"aiValue" : 0,
|
||||||
"base" : {
|
"base" : {
|
||||||
"visitableFrom" : [ "+++", "+-+", "+++" ],
|
"visitableFrom" : [ "+++", "+-+", "+++" ],
|
||||||
"mask" : [ "VVV", "VAV" ]
|
"mask" : [ "VVV", "VAV" ]
|
||||||
@@ -124,8 +125,9 @@
|
|||||||
"borderGuard" : {
|
"borderGuard" : {
|
||||||
"index" :9,
|
"index" :9,
|
||||||
"handler": "borderGuard",
|
"handler": "borderGuard",
|
||||||
"defaultAiValue" : 0,
|
"lastReservedIndex" : 7,
|
||||||
"base" : {
|
"base" : {
|
||||||
|
"aiValue" : 0,
|
||||||
"sounds" : {
|
"sounds" : {
|
||||||
"visit" : ["CAVEHEAD"],
|
"visit" : ["CAVEHEAD"],
|
||||||
"removal" : [ "PICKUP01", "PICKUP02", "PICKUP03", "PICKUP04", "PICKUP05", "PICKUP06", "PICKUP07" ]
|
"removal" : [ "PICKUP01", "PICKUP02", "PICKUP03", "PICKUP04", "PICKUP05", "PICKUP06", "PICKUP07" ]
|
||||||
@@ -145,8 +147,9 @@
|
|||||||
"borderGate" : {
|
"borderGate" : {
|
||||||
"index" :212,
|
"index" :212,
|
||||||
"handler": "borderGate",
|
"handler": "borderGate",
|
||||||
"defaultAiValue" : 0,
|
"lastReservedIndex" : 7,
|
||||||
"base" : {
|
"base" : {
|
||||||
|
"aiValue" : 0,
|
||||||
"sounds" : {
|
"sounds" : {
|
||||||
"visit" : ["CAVEHEAD"]
|
"visit" : ["CAVEHEAD"]
|
||||||
}
|
}
|
||||||
@@ -165,8 +168,9 @@
|
|||||||
"keymasterTent" : {
|
"keymasterTent" : {
|
||||||
"index" :10,
|
"index" :10,
|
||||||
"handler": "keymaster",
|
"handler": "keymaster",
|
||||||
"defaultAiValue" : 10000,
|
"lastReservedIndex" : 7,
|
||||||
"base" : {
|
"base" : {
|
||||||
|
"aiValue" : 10000,
|
||||||
"sounds" : {
|
"sounds" : {
|
||||||
"visit" : ["CAVEHEAD"]
|
"visit" : ["CAVEHEAD"]
|
||||||
}
|
}
|
||||||
@@ -186,8 +190,9 @@
|
|||||||
"seerHut" : {
|
"seerHut" : {
|
||||||
"index" :83,
|
"index" :83,
|
||||||
"handler": "seerHut",
|
"handler": "seerHut",
|
||||||
"defaultAiValue" : 10000,
|
"lastReservedIndex" : 2,
|
||||||
"base" : {
|
"base" : {
|
||||||
|
"aiValue" : 10000,
|
||||||
"base" : {
|
"base" : {
|
||||||
"visitableFrom" : [ "---", "+++", "+++" ],
|
"visitableFrom" : [ "---", "+++", "+++" ],
|
||||||
"mask" : [ "VVV", "VVV", "VAV" ]
|
"mask" : [ "VVV", "VVV", "VAV" ]
|
||||||
@@ -207,6 +212,7 @@
|
|||||||
"cartographer" : {
|
"cartographer" : {
|
||||||
"index" :13,
|
"index" :13,
|
||||||
"handler": "cartographer",
|
"handler": "cartographer",
|
||||||
|
"lastReservedIndex" : 2,
|
||||||
"base" : {
|
"base" : {
|
||||||
"sounds" : {
|
"sounds" : {
|
||||||
"visit" : ["LIGHTHOUSE"]
|
"visit" : ["LIGHTHOUSE"]
|
||||||
@@ -223,6 +229,7 @@
|
|||||||
"mine" : {
|
"mine" : {
|
||||||
"index" :53,
|
"index" :53,
|
||||||
"handler": "mine",
|
"handler": "mine",
|
||||||
|
"lastReservedIndex" : 7,
|
||||||
"base" : {
|
"base" : {
|
||||||
"sounds" : {
|
"sounds" : {
|
||||||
"visit" : ["FLAGMINE"]
|
"visit" : ["FLAGMINE"]
|
||||||
@@ -237,8 +244,7 @@
|
|||||||
},
|
},
|
||||||
"sounds" : {
|
"sounds" : {
|
||||||
"ambient" : ["LOOPLUMB"]
|
"ambient" : ["LOOPLUMB"]
|
||||||
},
|
}
|
||||||
"battleground": "subterranean"
|
|
||||||
},
|
},
|
||||||
"alchemistLab" : {
|
"alchemistLab" : {
|
||||||
"index" : 1,
|
"index" : 1,
|
||||||
@@ -248,8 +254,7 @@
|
|||||||
},
|
},
|
||||||
"sounds" : {
|
"sounds" : {
|
||||||
"ambient" : ["LOOPSTAR"]
|
"ambient" : ["LOOPSTAR"]
|
||||||
},
|
}
|
||||||
"battleground": "subterranean"
|
|
||||||
},
|
},
|
||||||
"orePit" : {
|
"orePit" : {
|
||||||
"index" : 2,
|
"index" : 2,
|
||||||
@@ -259,8 +264,7 @@
|
|||||||
},
|
},
|
||||||
"sounds" : {
|
"sounds" : {
|
||||||
"ambient" : ["LOOPSULF"]
|
"ambient" : ["LOOPSULF"]
|
||||||
},
|
}
|
||||||
"battleground": "subterranean"
|
|
||||||
},
|
},
|
||||||
"sulfurDune" : {
|
"sulfurDune" : {
|
||||||
"index" : 3,
|
"index" : 3,
|
||||||
@@ -270,8 +274,7 @@
|
|||||||
},
|
},
|
||||||
"sounds" : {
|
"sounds" : {
|
||||||
"ambient" : ["LOOPSULF"]
|
"ambient" : ["LOOPSULF"]
|
||||||
},
|
}
|
||||||
"battleground": "subterranean"
|
|
||||||
},
|
},
|
||||||
"crystalCavern" : {
|
"crystalCavern" : {
|
||||||
"index" : 4,
|
"index" : 4,
|
||||||
@@ -292,8 +295,7 @@
|
|||||||
},
|
},
|
||||||
"sounds" : {
|
"sounds" : {
|
||||||
"ambient" : ["LOOPGEMP"]
|
"ambient" : ["LOOPGEMP"]
|
||||||
},
|
}
|
||||||
"battleground": "subterranean"
|
|
||||||
},
|
},
|
||||||
"goldMine" : {
|
"goldMine" : {
|
||||||
"index" : 6,
|
"index" : 6,
|
||||||
@@ -320,8 +322,9 @@
|
|||||||
"abandonedMine" : {
|
"abandonedMine" : {
|
||||||
"index" :220,
|
"index" :220,
|
||||||
"handler": "mine",
|
"handler": "mine",
|
||||||
"defaultAiValue" : 3500,
|
"lastReservedIndex" : 7,
|
||||||
"base" : {
|
"base" : {
|
||||||
|
"aiValue" : 3500,
|
||||||
"sounds" : {
|
"sounds" : {
|
||||||
"ambient" : ["LOOPCAVE"]
|
"ambient" : ["LOOPCAVE"]
|
||||||
}
|
}
|
||||||
@@ -334,8 +337,9 @@
|
|||||||
"garrisonHorizontal": {
|
"garrisonHorizontal": {
|
||||||
"index" :33,
|
"index" :33,
|
||||||
"handler": "garrison",
|
"handler": "garrison",
|
||||||
"defaultAiValue" : 0,
|
"lastReservedIndex" : 1,
|
||||||
"base" : {
|
"base" : {
|
||||||
|
"aiValue" : 0,
|
||||||
"sounds" : {
|
"sounds" : {
|
||||||
"visit" : ["MILITARY"]
|
"visit" : ["MILITARY"]
|
||||||
}
|
}
|
||||||
@@ -358,8 +362,9 @@
|
|||||||
"garrisonVertical" : {
|
"garrisonVertical" : {
|
||||||
"index" :219,
|
"index" :219,
|
||||||
"handler": "garrison",
|
"handler": "garrison",
|
||||||
"defaultAiValue" : 0,
|
"lastReservedIndex" : 1,
|
||||||
"base" : {
|
"base" : {
|
||||||
|
"aiValue" : 0,
|
||||||
"sounds" : {
|
"sounds" : {
|
||||||
"visit" : ["MILITARY"]
|
"visit" : ["MILITARY"]
|
||||||
}
|
}
|
||||||
@@ -384,6 +389,7 @@
|
|||||||
"monolithOneWayEntrance" : {
|
"monolithOneWayEntrance" : {
|
||||||
"index" :43,
|
"index" :43,
|
||||||
"handler": "monolith",
|
"handler": "monolith",
|
||||||
|
"lastReservedIndex" : 7,
|
||||||
"base" : {
|
"base" : {
|
||||||
"sounds" : {
|
"sounds" : {
|
||||||
"ambient" : ["LOOPMON1"],
|
"ambient" : ["LOOPMON1"],
|
||||||
@@ -404,6 +410,7 @@
|
|||||||
"monolithOneWayExit" : {
|
"monolithOneWayExit" : {
|
||||||
"index" :44,
|
"index" :44,
|
||||||
"handler": "monolith",
|
"handler": "monolith",
|
||||||
|
"lastReservedIndex" : 7,
|
||||||
"base" : {
|
"base" : {
|
||||||
"sounds" : { "ambient" : ["LOOPMON1"] }
|
"sounds" : { "ambient" : ["LOOPMON1"] }
|
||||||
},
|
},
|
||||||
@@ -421,6 +428,7 @@
|
|||||||
"monolithTwoWay" : {
|
"monolithTwoWay" : {
|
||||||
"index" :45,
|
"index" :45,
|
||||||
"handler": "monolith",
|
"handler": "monolith",
|
||||||
|
"lastReservedIndex" : 7,
|
||||||
"base" : {
|
"base" : {
|
||||||
"sounds" : {
|
"sounds" : {
|
||||||
"ambient" : ["LOOPMON2"],
|
"ambient" : ["LOOPMON2"],
|
||||||
@@ -441,7 +449,9 @@
|
|||||||
|
|
||||||
// subtype: level
|
// subtype: level
|
||||||
"randomDwellingLvl" : {
|
"randomDwellingLvl" : {
|
||||||
"index" :217, "handler": "randomDwelling",
|
"index" :217,
|
||||||
|
"handler": "randomDwelling",
|
||||||
|
"lastReservedIndex" : 6,
|
||||||
"types" : {
|
"types" : {
|
||||||
"objectLvl1" : { "index" : 0},
|
"objectLvl1" : { "index" : 0},
|
||||||
"objectLvl2" : { "index" : 1},
|
"objectLvl2" : { "index" : 1},
|
||||||
@@ -457,6 +467,7 @@
|
|||||||
"randomDwellingFaction" : {
|
"randomDwellingFaction" : {
|
||||||
"index" :218,
|
"index" :218,
|
||||||
"handler": "randomDwelling",
|
"handler": "randomDwelling",
|
||||||
|
"lastReservedIndex" : 8,
|
||||||
"types" : {
|
"types" : {
|
||||||
"objectCastle" : { "index" : 0},
|
"objectCastle" : { "index" : 0},
|
||||||
"objectRampart" : { "index" : 1},
|
"objectRampart" : { "index" : 1},
|
||||||
|
@@ -10,49 +10,18 @@
|
|||||||
"index": {
|
"index": {
|
||||||
"type":"number"
|
"type":"number"
|
||||||
},
|
},
|
||||||
"name": {
|
"lastReservedIndex" : {
|
||||||
"type":"string"
|
|
||||||
},
|
|
||||||
"defaultAiValue": {
|
|
||||||
"type":"number"
|
"type":"number"
|
||||||
},
|
},
|
||||||
|
|
||||||
"handler": {
|
"handler": {
|
||||||
"type":"string"
|
"type":"string"
|
||||||
},
|
},
|
||||||
|
|
||||||
"sounds": {
|
|
||||||
"type":"object",
|
|
||||||
"additionalProperties" : false,
|
|
||||||
"description": "Sounds used by this object",
|
|
||||||
"properties" : {
|
|
||||||
"ambient": {
|
|
||||||
"type":"array",
|
|
||||||
"description": "Background sound of an object",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"visit": {
|
|
||||||
"type":"array",
|
|
||||||
"description": "Sound that played on object visit",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"removal": {
|
|
||||||
"type":"array",
|
|
||||||
"description": "Sound that played on object removal",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
"base": {
|
"base": {
|
||||||
"type" : "object"
|
"type" : "object"
|
||||||
},
|
},
|
||||||
|
"name": {
|
||||||
|
"type":"string"
|
||||||
|
},
|
||||||
"types": {
|
"types": {
|
||||||
"type":"object",
|
"type":"object",
|
||||||
"additionalProperties": {
|
"additionalProperties": {
|
||||||
|
@@ -10,13 +10,9 @@
|
|||||||
"index": {
|
"index": {
|
||||||
"type":"number"
|
"type":"number"
|
||||||
},
|
},
|
||||||
"name": {
|
|
||||||
"type":"string"
|
|
||||||
},
|
|
||||||
"aiValue": {
|
"aiValue": {
|
||||||
"type":"number"
|
"type":"number"
|
||||||
},
|
},
|
||||||
|
|
||||||
"sounds": {
|
"sounds": {
|
||||||
"type":"object",
|
"type":"object",
|
||||||
"additionalProperties" : false,
|
"additionalProperties" : false,
|
||||||
|
@@ -390,7 +390,7 @@ CArtifact * CArtHandler::loadFromJson(const std::string & scope, const JsonNode
|
|||||||
JsonNode conf;
|
JsonNode conf;
|
||||||
conf.setMeta(scope);
|
conf.setMeta(scope);
|
||||||
|
|
||||||
VLC->objtypeh->loadSubObject(art->getJsonKey(), conf, Obj::ARTIFACT, art->getIndex());
|
VLC->objtypeh->loadSubObject(art->identifier, conf, Obj::ARTIFACT, art->getIndex());
|
||||||
|
|
||||||
if(!art->advMapDef.empty())
|
if(!art->advMapDef.empty())
|
||||||
{
|
{
|
||||||
|
@@ -129,7 +129,7 @@ void MetaString::getLocalString(const std::pair<ui8,ui32> &txt, std::string &dst
|
|||||||
}
|
}
|
||||||
else if(type == OBJ_NAMES)
|
else if(type == OBJ_NAMES)
|
||||||
{
|
{
|
||||||
dst = VLC->objtypeh->getObjectName(ser);
|
dst = VLC->objtypeh->getObjectName(ser, 0);
|
||||||
}
|
}
|
||||||
else if(type == SEC_SKILL_NAME)
|
else if(type == SEC_SKILL_NAME)
|
||||||
{
|
{
|
||||||
@@ -149,10 +149,10 @@ void MetaString::getLocalString(const std::pair<ui8,ui32> &txt, std::string &dst
|
|||||||
dst = VLC->generaltexth->translate("core.arraytxt", ser);
|
dst = VLC->generaltexth->translate("core.arraytxt", ser);
|
||||||
break;
|
break;
|
||||||
case CREGENS:
|
case CREGENS:
|
||||||
dst = VLC->generaltexth->translate("core.crgen1", ser);
|
dst = VLC->objtypeh->getObjectName(Obj::CREATURE_GENERATOR1, ser);
|
||||||
break;
|
break;
|
||||||
case CREGENS4:
|
case CREGENS4:
|
||||||
dst = VLC->generaltexth->translate("core.crgen4", ser);
|
dst = VLC->objtypeh->getObjectName(Obj::CREATURE_GENERATOR4, ser);
|
||||||
break;
|
break;
|
||||||
case ADVOB_TXT:
|
case ADVOB_TXT:
|
||||||
dst = VLC->generaltexth->translate("core.advevent", ser);
|
dst = VLC->generaltexth->translate("core.advevent", ser);
|
||||||
|
@@ -440,8 +440,6 @@ CGeneralTextHandler::CGeneralTextHandler():
|
|||||||
readToVector("core.advevent", "DATA/ADVEVENT.TXT" );
|
readToVector("core.advevent", "DATA/ADVEVENT.TXT" );
|
||||||
readToVector("core.restypes", "DATA/RESTYPES.TXT" );
|
readToVector("core.restypes", "DATA/RESTYPES.TXT" );
|
||||||
readToVector("core.randsign", "DATA/RANDSIGN.TXT" );
|
readToVector("core.randsign", "DATA/RANDSIGN.TXT" );
|
||||||
readToVector("core.crgen1", "DATA/CRGEN1.TXT" );
|
|
||||||
readToVector("core.crgen4", "DATA/CRGEN4.TXT" );
|
|
||||||
readToVector("core.overview", "DATA/OVERVIEW.TXT" );
|
readToVector("core.overview", "DATA/OVERVIEW.TXT" );
|
||||||
readToVector("core.arraytxt", "DATA/ARRAYTXT.TXT" );
|
readToVector("core.arraytxt", "DATA/ARRAYTXT.TXT" );
|
||||||
readToVector("core.priskill", "DATA/PRISKILL.TXT" );
|
readToVector("core.priskill", "DATA/PRISKILL.TXT" );
|
||||||
|
@@ -160,6 +160,7 @@ class DLL_LINKAGE CGeneralTextHandler
|
|||||||
/// Attempts to detect encoding & language of H3 files
|
/// Attempts to detect encoding & language of H3 files
|
||||||
void detectInstallParameters() const;
|
void detectInstallParameters() const;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// Loads translation from provided json
|
/// Loads translation from provided json
|
||||||
/// Any entries loaded by this will have priority over texts registered normally
|
/// Any entries loaded by this will have priority over texts registered normally
|
||||||
void loadTranslationOverrides(JsonNode const & file);
|
void loadTranslationOverrides(JsonNode const & file);
|
||||||
|
@@ -92,7 +92,7 @@ CObjectClassesHandler::CObjectClassesHandler()
|
|||||||
CObjectClassesHandler::~CObjectClassesHandler()
|
CObjectClassesHandler::~CObjectClassesHandler()
|
||||||
{
|
{
|
||||||
for(auto p : objects)
|
for(auto p : objects)
|
||||||
delete p.second;
|
delete p;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<JsonNode> CObjectClassesHandler::loadLegacyData(size_t dataSize)
|
std::vector<JsonNode> CObjectClassesHandler::loadLegacyData(size_t dataSize)
|
||||||
@@ -112,6 +112,8 @@ std::vector<JsonNode> CObjectClassesHandler::loadLegacyData(size_t dataSize)
|
|||||||
legacyTemplates.insert(std::make_pair(key, std::shared_ptr<const ObjectTemplate>(tmpl)));
|
legacyTemplates.insert(std::make_pair(key, std::shared_ptr<const ObjectTemplate>(tmpl)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
objects.resize(256);
|
||||||
|
|
||||||
std::vector<JsonNode> ret(dataSize);// create storage for 256 objects
|
std::vector<JsonNode> ret(dataSize);// create storage for 256 objects
|
||||||
assert(dataSize == 256);
|
assert(dataSize == 256);
|
||||||
|
|
||||||
@@ -122,171 +124,170 @@ std::vector<JsonNode> CObjectClassesHandler::loadLegacyData(size_t dataSize)
|
|||||||
namesParser.endLine();
|
namesParser.endLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JsonNode cregen1;
|
||||||
|
JsonNode cregen4;
|
||||||
|
|
||||||
CLegacyConfigParser cregen1Parser("data/crgen1");
|
CLegacyConfigParser cregen1Parser("data/crgen1");
|
||||||
do
|
do
|
||||||
customNames[Obj::CREATURE_GENERATOR1].push_back(cregen1Parser.readString());
|
{
|
||||||
|
JsonNode subObject;
|
||||||
|
subObject["name"].String() = cregen1Parser.readString();
|
||||||
|
cregen1.Vector().push_back(subObject);
|
||||||
|
}
|
||||||
while(cregen1Parser.endLine());
|
while(cregen1Parser.endLine());
|
||||||
|
|
||||||
CLegacyConfigParser cregen4Parser("data/crgen4");
|
CLegacyConfigParser cregen4Parser("data/crgen4");
|
||||||
do
|
do
|
||||||
customNames[Obj::CREATURE_GENERATOR4].push_back(cregen4Parser.readString());
|
{
|
||||||
|
JsonNode subObject;
|
||||||
|
subObject["name"].String() = cregen4Parser.readString();
|
||||||
|
cregen4.Vector().push_back(subObject);
|
||||||
|
}
|
||||||
while(cregen4Parser.endLine());
|
while(cregen4Parser.endLine());
|
||||||
|
|
||||||
|
ret[Obj::CREATURE_GENERATOR1]["subObjects"] = cregen1;
|
||||||
|
ret[Obj::CREATURE_GENERATOR4]["subObjects"] = cregen4;
|
||||||
|
|
||||||
|
ret[Obj::REFUGEE_CAMP]["subObjects"].Vector().push_back(ret[Obj::REFUGEE_CAMP]);
|
||||||
|
ret[Obj::WAR_MACHINE_FACTORY]["subObjects"].Vector().push_back(ret[Obj::WAR_MACHINE_FACTORY]);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// selects preferred ID (or subID) for new object
|
void CObjectClassesHandler::loadSubObject(const std::string & scope, const std::string & identifier, const JsonNode & entry, ObjectClass * obj)
|
||||||
template<typename Map>
|
|
||||||
si32 selectNextID(const JsonNode & fixedID, const Map & map, si32 fixedObjectsBound)
|
|
||||||
{
|
{
|
||||||
assert(fixedObjectsBound > 0);
|
auto object = loadSubObjectFromJson(scope, identifier, entry, obj, obj->objects.size());
|
||||||
if(fixedID.isNull())
|
|
||||||
{
|
|
||||||
auto lastID = map.empty() ? 0 : map.rbegin()->first;
|
|
||||||
return lastID < fixedObjectsBound ? fixedObjectsBound : lastID + 1;
|
|
||||||
}
|
|
||||||
auto id = static_cast<si32>(fixedID.Float());
|
|
||||||
if(id >= fixedObjectsBound)
|
|
||||||
logGlobal->error("Getting next ID overflowed: %d >= %d", id, fixedObjectsBound);
|
|
||||||
|
|
||||||
return id;
|
assert(object);
|
||||||
|
obj->objects.push_back(object);
|
||||||
|
|
||||||
|
registerObject(scope, obj->getJsonKey(), object->getSubTypeName(), object->subtype);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CObjectClassesHandler::loadObjectEntry(const std::string & identifier, const JsonNode & entry, ObjectContainter * obj, bool isSubobject)
|
void CObjectClassesHandler::loadSubObject(const std::string & scope, const std::string & identifier, const JsonNode & entry, ObjectClass * obj, size_t index)
|
||||||
{
|
{
|
||||||
static const si32 fixedObjectsBound = 1000; // legacy value for backward compatibilitty
|
auto object = loadSubObjectFromJson(scope, identifier, entry, obj, index);
|
||||||
static const si32 fixedSubobjectsBound = 10000000; // large enough arbitrary value to avoid ID-collisions
|
|
||||||
si32 usedBound = fixedObjectsBound;
|
assert(object);
|
||||||
|
assert(obj->objects[index] == nullptr); // ensure that this id was not loaded before
|
||||||
|
obj->objects[index] = object;
|
||||||
|
|
||||||
|
registerObject(scope, obj->getJsonKey(), object->getSubTypeName(), object->subtype);
|
||||||
|
}
|
||||||
|
|
||||||
|
TObjectTypeHandler CObjectClassesHandler::loadSubObjectFromJson(const std::string & scope, const std::string & identifier, const JsonNode & entry, ObjectClass * obj, size_t index)
|
||||||
|
{
|
||||||
|
assert(identifier.find(':') == std::string::npos);
|
||||||
|
assert(!scope.empty());
|
||||||
|
|
||||||
if(!handlerConstructors.count(obj->handlerName))
|
if(!handlerConstructors.count(obj->handlerName))
|
||||||
{
|
{
|
||||||
logGlobal->error("Handler with name %s was not found!", obj->handlerName);
|
logGlobal->error("Handler with name %s was not found!", obj->handlerName);
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
const auto convertedId = VLC->modh->normalizeIdentifier(entry.meta, CModHandler::scopeBuiltin(), identifier);
|
|
||||||
const auto & entryIndex = entry["index"];
|
|
||||||
bool useSelectNextID = !isSubobject || entryIndex.isNull();
|
|
||||||
|
|
||||||
if(useSelectNextID && isSubobject)
|
auto createdObject = handlerConstructors.at(obj->handlerName)();
|
||||||
{
|
|
||||||
usedBound = fixedSubobjectsBound;
|
|
||||||
logGlobal->error("Subobject index is Null. convertedId = '%s' obj->id = %d", convertedId, obj->id);
|
|
||||||
}
|
|
||||||
si32 id = useSelectNextID ? selectNextID(entryIndex, obj->subObjects, usedBound)
|
|
||||||
: (si32)entryIndex.Float();
|
|
||||||
|
|
||||||
auto handler = handlerConstructors.at(obj->handlerName)();
|
createdObject->modScope = scope;
|
||||||
handler->setType(obj->id, id);
|
createdObject->typeName = obj->identifier;;
|
||||||
handler->setTypeName(obj->identifier, convertedId);
|
createdObject->subTypeName = identifier;
|
||||||
|
|
||||||
if (customNames.count(obj->id) && customNames.at(obj->id).size() > id)
|
createdObject->type = obj->id;
|
||||||
handler->init(entry, customNames.at(obj->id).at(id));
|
createdObject->subtype = index;
|
||||||
else
|
createdObject->init(entry);
|
||||||
handler->init(entry);
|
|
||||||
|
|
||||||
//if (handler->getTemplates().empty())
|
auto range = legacyTemplates.equal_range(std::make_pair(obj->id, index));
|
||||||
{
|
|
||||||
auto range = legacyTemplates.equal_range(std::make_pair(obj->id, id));
|
|
||||||
for (auto & templ : boost::make_iterator_range(range.first, range.second))
|
for (auto & templ : boost::make_iterator_range(range.first, range.second))
|
||||||
{
|
{
|
||||||
handler->addTemplate(templ.second);
|
createdObject->addTemplate(templ.second);
|
||||||
}
|
}
|
||||||
legacyTemplates.erase(range.first, range.second);
|
legacyTemplates.erase(range.first, range.second);
|
||||||
|
|
||||||
|
logGlobal->debug("Loaded object %s(%d)::%s(%d)", obj->getJsonKey(), obj->id, identifier, index);
|
||||||
|
|
||||||
|
return createdObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
logGlobal->debug("Loaded object %s(%d)::%s(%d)", obj->identifier, obj->id, convertedId, id);
|
std::string ObjectClass::getJsonKey() const
|
||||||
|
|
||||||
//some mods redefine content handlers in the decoration.json in such way:
|
|
||||||
//"core:sign" : { "types" : { "forgeSign" : { ...
|
|
||||||
static const std::vector<std::string> breakersRMG
|
|
||||||
{
|
{
|
||||||
"hota.hota decorations:hotaPandoraBox"
|
return modScope + ':' + identifier;
|
||||||
, "hota.hota decorations:hotaSubterreanGate"
|
|
||||||
};
|
|
||||||
const bool isExistingKey = obj->subObjects.count(id) > 0;
|
|
||||||
const bool isBreaker = std::any_of(breakersRMG.begin(), breakersRMG.end(),
|
|
||||||
[&handler](const std::string & str)
|
|
||||||
{
|
|
||||||
return str.compare(handler->subTypeName) == 0;
|
|
||||||
});
|
|
||||||
const bool passedHandler = !isExistingKey && !isBreaker;
|
|
||||||
|
|
||||||
if(passedHandler)
|
|
||||||
{
|
|
||||||
obj->subObjects[id] = handler;
|
|
||||||
obj->subIds[convertedId] = id;
|
|
||||||
}
|
|
||||||
else if(isExistingKey) //It's supposed that fan mods handlers are not overridden by default handlers
|
|
||||||
{
|
|
||||||
logGlobal->trace("Handler '%s' has not been overridden with handler '%s' in object %s(%d)::%s(%d)",
|
|
||||||
obj->subObjects[id]->subTypeName, obj->handlerName, obj->identifier, obj->id, convertedId, id);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
logGlobal->warn("Handler '%s' for object %s(%d)::%s(%d) has not been activated as RMG breaker",
|
|
||||||
obj->handlerName, obj->identifier, obj->id, convertedId, id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CObjectClassesHandler::ObjectContainter * CObjectClassesHandler::loadFromJson(const std::string & scope, const JsonNode & json, const std::string & name)
|
std::string ObjectClass::getNameTextID() const
|
||||||
{
|
{
|
||||||
auto obj = new ObjectContainter();
|
return TextIdentifier("object", modScope, identifier, "name").get();
|
||||||
static const si32 fixedObjectsBound = 256; //Legacy value for backward compatibility
|
}
|
||||||
|
|
||||||
|
std::string ObjectClass::getNameTranslated() const
|
||||||
|
{
|
||||||
|
return VLC->generaltexth->translate(getNameTextID());
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectClass * CObjectClassesHandler::loadFromJson(const std::string & scope, const JsonNode & json, const std::string & name, size_t index)
|
||||||
|
{
|
||||||
|
auto obj = new ObjectClass();
|
||||||
|
|
||||||
|
obj->modScope = scope;
|
||||||
obj->identifier = name;
|
obj->identifier = name;
|
||||||
obj->name = json["name"].String();
|
|
||||||
obj->handlerName = json["handler"].String();
|
obj->handlerName = json["handler"].String();
|
||||||
obj->base = json["base"];
|
obj->base = json["base"];
|
||||||
obj->id = selectNextID(json["index"], objects, fixedObjectsBound);
|
obj->id = index;
|
||||||
|
|
||||||
if(json["defaultAiValue"].isNull())
|
VLC->generaltexth->registerString(obj->getNameTextID(), json["name"].String());
|
||||||
obj->groupDefaultAiValue = boost::none;
|
|
||||||
|
obj->objects.resize(json["lastReservedIndex"].Float() + 1);
|
||||||
|
|
||||||
|
for (auto subData : json["types"].Struct())
|
||||||
|
{
|
||||||
|
if (!subData.second["index"].isNull())
|
||||||
|
{
|
||||||
|
std::string const & subMeta = subData.second["index"].meta;
|
||||||
|
|
||||||
|
if ( subMeta != "core")
|
||||||
|
logMod->warn("Object %s:%s.%s - attempt to load object with preset index! This option is reserved for built-in mod", subMeta, name, subData.first );
|
||||||
|
size_t subIndex = subData.second["index"].Integer();
|
||||||
|
loadSubObject(subData.second.meta, subData.first, subData.second, obj, subIndex);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
obj->groupDefaultAiValue = static_cast<boost::optional<si32>>(json["defaultAiValue"].Integer());
|
loadSubObject(subData.second.meta, subData.first, subData.second, obj);
|
||||||
|
}
|
||||||
for (auto entry : json["types"].Struct())
|
|
||||||
loadObjectEntry(entry.first, entry.second, obj);
|
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CObjectClassesHandler::loadObject(std::string scope, std::string name, const JsonNode & data)
|
void CObjectClassesHandler::loadObject(std::string scope, std::string name, const JsonNode & data)
|
||||||
{
|
{
|
||||||
auto object = loadFromJson(scope, data, VLC->modh->normalizeIdentifier(scope, CModHandler::scopeBuiltin(), name));
|
auto object = loadFromJson(scope, data, name, objects.size());
|
||||||
objects[object->id] = object;
|
objects.push_back(object);
|
||||||
VLC->modh->identifiers.registerObject(scope, "object", name, object->id);
|
VLC->modh->identifiers.registerObject(scope, "object", name, object->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CObjectClassesHandler::loadObject(std::string scope, std::string name, const JsonNode & data, size_t index)
|
void CObjectClassesHandler::loadObject(std::string scope, std::string name, const JsonNode & data, size_t index)
|
||||||
{
|
{
|
||||||
auto object = loadFromJson(scope, data, VLC->modh->normalizeIdentifier(scope, CModHandler::scopeBuiltin(), name));
|
auto object = loadFromJson(scope, data, name, index);
|
||||||
assert(objects[(si32)index] == nullptr); // ensure that this id was not loaded before
|
assert(objects[(si32)index] == nullptr); // ensure that this id was not loaded before
|
||||||
objects[(si32)index] = object;
|
objects[(si32)index] = object;
|
||||||
VLC->modh->identifiers.registerObject(scope, "object", name, object->id);
|
VLC->modh->identifiers.registerObject(scope, "object", name, object->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CObjectClassesHandler::loadSubObject(const std::string & identifier, JsonNode config, si32 ID, boost::optional<si32> subID)
|
void CObjectClassesHandler::loadSubObject(const std::string & identifier, JsonNode config, si32 ID, si32 subID)
|
||||||
{
|
{
|
||||||
static const bool isSubObject = true;
|
|
||||||
|
|
||||||
config.setType(JsonNode::JsonType::DATA_STRUCT); // ensure that input is not NULL
|
config.setType(JsonNode::JsonType::DATA_STRUCT); // ensure that input is not NULL
|
||||||
assert(objects.count(ID));
|
assert(ID < objects.size());
|
||||||
if (subID)
|
assert(objects[ID]);
|
||||||
{
|
|
||||||
assert(objects.at(ID)->subObjects.count(subID.get()) == 0);
|
if ( subID >= objects[ID]->objects.size())
|
||||||
assert(config["index"].isNull());
|
objects[ID]->objects.resize(subID+1);
|
||||||
config["index"].Float() = subID.get();
|
|
||||||
config["index"].setMeta(config.meta);
|
|
||||||
}
|
|
||||||
JsonUtils::inherit(config, objects.at(ID)->base);
|
JsonUtils::inherit(config, objects.at(ID)->base);
|
||||||
loadObjectEntry(identifier, config, objects[ID], isSubObject);
|
loadSubObject(config.meta, identifier, config, objects[ID], subID);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CObjectClassesHandler::removeSubObject(si32 ID, si32 subID)
|
void CObjectClassesHandler::removeSubObject(si32 ID, si32 subID)
|
||||||
{
|
{
|
||||||
assert(objects.count(ID));
|
assert(ID < objects.size());
|
||||||
assert(objects.at(ID)->subObjects.count(subID));
|
assert(objects[ID]);
|
||||||
objects.at(ID)->subObjects.erase(subID); //TODO: cleanup string id map
|
assert(subID < objects[ID]->objects.size());
|
||||||
|
objects[ID]->objects[subID] = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<bool> CObjectClassesHandler::getDefaultAllowed() const
|
std::vector<bool> CObjectClassesHandler::getDefaultAllowed() const
|
||||||
@@ -296,29 +297,25 @@ std::vector<bool> CObjectClassesHandler::getDefaultAllowed() const
|
|||||||
|
|
||||||
TObjectTypeHandler CObjectClassesHandler::getHandlerFor(si32 type, si32 subtype) const
|
TObjectTypeHandler CObjectClassesHandler::getHandlerFor(si32 type, si32 subtype) const
|
||||||
{
|
{
|
||||||
if (objects.count(type))
|
assert(type < objects.size());
|
||||||
{
|
assert(objects[type]);
|
||||||
if (objects.at(type)->subObjects.count(subtype))
|
assert(subtype < objects[type]->objects.size());
|
||||||
return objects.at(type)->subObjects.at(subtype);
|
|
||||||
}
|
return objects.at(type)->objects.at(subtype);
|
||||||
std::string errorString = "Failed to find object of type " + std::to_string(type) + "::" + std::to_string(subtype);
|
|
||||||
logGlobal->error(errorString);
|
|
||||||
throw std::runtime_error(errorString);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TObjectTypeHandler CObjectClassesHandler::getHandlerFor(std::string scope, std::string type, std::string subtype) const
|
TObjectTypeHandler CObjectClassesHandler::getHandlerFor(std::string scope, std::string type, std::string subtype) const
|
||||||
{
|
{
|
||||||
boost::optional<si32> id = VLC->modh->identifiers.getIdentifier(scope, "object", type, false);
|
boost::optional<si32> id = VLC->modh->identifiers.getIdentifier(scope, "object", type);
|
||||||
if(id)
|
if(id)
|
||||||
{
|
{
|
||||||
auto object = objects.at(id.get());
|
auto object = objects[id.get()];
|
||||||
if(object->subIds.count(subtype))
|
boost::optional<si32> subID = VLC->modh->identifiers.getIdentifier(scope, object->getJsonKey(), subtype);
|
||||||
{
|
|
||||||
si32 subId = object->subIds.at(subtype);
|
|
||||||
|
|
||||||
return object->subObjects.at(subId);
|
if (subID)
|
||||||
}
|
return object->objects[subID.get()];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string errorString = "Failed to find object of type " + type + "::" + subtype;
|
std::string errorString = "Failed to find object of type " + type + "::" + subtype;
|
||||||
logGlobal->error(errorString);
|
logGlobal->error(errorString);
|
||||||
throw std::runtime_error(errorString);
|
throw std::runtime_error(errorString);
|
||||||
@@ -334,20 +331,23 @@ std::set<si32> CObjectClassesHandler::knownObjects() const
|
|||||||
std::set<si32> ret;
|
std::set<si32> ret;
|
||||||
|
|
||||||
for (auto entry : objects)
|
for (auto entry : objects)
|
||||||
ret.insert(entry.first);
|
if (entry)
|
||||||
|
ret.insert(entry->id);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<si32> CObjectClassesHandler::knownSubObjects(si32 primaryID) const
|
std::set<si32> CObjectClassesHandler::knownSubObjects(si32 primaryID) const
|
||||||
{
|
{
|
||||||
|
assert(primaryID < objects.size());
|
||||||
|
assert(objects[primaryID]);
|
||||||
|
|
||||||
std::set<si32> ret;
|
std::set<si32> ret;
|
||||||
|
|
||||||
if (objects.count(primaryID))
|
for (auto entry : objects.at(primaryID)->objects)
|
||||||
{
|
if (entry)
|
||||||
for (auto entry : objects.at(primaryID)->subObjects)
|
ret.insert(entry->subtype);
|
||||||
ret.insert(entry.first);
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,68 +355,75 @@ void CObjectClassesHandler::beforeValidate(JsonNode & object)
|
|||||||
{
|
{
|
||||||
for (auto & entry : object["types"].Struct())
|
for (auto & entry : object["types"].Struct())
|
||||||
{
|
{
|
||||||
|
if (object.Struct().count("subObjects"))
|
||||||
|
{
|
||||||
|
auto const & vector = object["subObjects"].Vector();
|
||||||
|
|
||||||
|
if (entry.second.Struct().count("index"))
|
||||||
|
{
|
||||||
|
size_t index = entry.second["index"].Integer();
|
||||||
|
|
||||||
|
if (index < vector.size())
|
||||||
|
JsonUtils::inherit(entry.second, vector[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
JsonUtils::inherit(entry.second, object["base"]);
|
JsonUtils::inherit(entry.second, object["base"]);
|
||||||
for (auto & templ : entry.second["templates"].Struct())
|
for (auto & templ : entry.second["templates"].Struct())
|
||||||
JsonUtils::inherit(templ.second, entry.second["base"]);
|
JsonUtils::inherit(templ.second, entry.second["base"]);
|
||||||
}
|
}
|
||||||
|
object.Struct().erase("subObjects");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CObjectClassesHandler::afterLoadFinalization()
|
void CObjectClassesHandler::afterLoadFinalization()
|
||||||
{
|
{
|
||||||
for(auto entry : objects)
|
for(auto entry : objects)
|
||||||
{
|
{
|
||||||
for(auto obj : entry.second->subObjects)
|
if (!entry)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for(auto obj : entry->objects)
|
||||||
{
|
{
|
||||||
obj.second->afterLoadFinalization();
|
if (!obj)
|
||||||
if(obj.second->getTemplates().empty())
|
continue;
|
||||||
logGlobal->warn("No templates found for %d:%d", entry.first, obj.first);
|
|
||||||
|
obj->afterLoadFinalization();
|
||||||
|
if(obj->getTemplates().empty())
|
||||||
|
logGlobal->warn("No templates found for %s:%s", entry->getJsonKey(), obj->getJsonKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//duplicate existing two-way portals to make reserve for RMG
|
//duplicate existing two-way portals to make reserve for RMG
|
||||||
auto& portalVec = objects[Obj::MONOLITH_TWO_WAY]->subObjects;
|
auto& portalVec = objects[Obj::MONOLITH_TWO_WAY]->objects;
|
||||||
size_t portalCount = portalVec.size();
|
size_t portalCount = portalVec.size();
|
||||||
size_t currentIndex = portalCount;
|
|
||||||
while(portalVec.size() < 100)
|
|
||||||
{
|
|
||||||
portalVec[(si32)currentIndex] = portalVec[static_cast<si32>(currentIndex % portalCount)];
|
|
||||||
currentIndex++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CObjectClassesHandler::getObjectName(si32 type) const
|
for (size_t i = portalCount; i < 100; ++i)
|
||||||
{
|
portalVec.push_back(portalVec[static_cast<si32>(i % portalCount)]);
|
||||||
if (objects.count(type))
|
|
||||||
return objects.at(type)->name;
|
|
||||||
logGlobal->error("Access to non existing object of type %d", type);
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CObjectClassesHandler::getObjectName(si32 type, si32 subtype) const
|
std::string CObjectClassesHandler::getObjectName(si32 type, si32 subtype) const
|
||||||
{
|
{
|
||||||
if (knownSubObjects(type).count(subtype))
|
auto const handler = getHandlerFor(type, subtype);
|
||||||
{
|
if (handler->hasNameTextID())
|
||||||
auto name = getHandlerFor(type, subtype)->getCustomName();
|
return handler->getNameTranslated();
|
||||||
if (name)
|
else
|
||||||
return name.get();
|
return objects[type]->getNameTranslated();
|
||||||
}
|
|
||||||
return getObjectName(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
SObjectSounds CObjectClassesHandler::getObjectSounds(si32 type) const
|
|
||||||
{
|
|
||||||
if(objects.count(type))
|
|
||||||
return objects.at(type)->sounds;
|
|
||||||
logGlobal->error("Access to non existing object of type %d", type);
|
|
||||||
return SObjectSounds();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SObjectSounds CObjectClassesHandler::getObjectSounds(si32 type, si32 subtype) const
|
SObjectSounds CObjectClassesHandler::getObjectSounds(si32 type, si32 subtype) const
|
||||||
{
|
{
|
||||||
if(knownSubObjects(type).count(subtype))
|
// TODO: these objects may have subID's that does not have associated handler:
|
||||||
|
// Prison: uses hero type as subID
|
||||||
|
// Hero: uses hero type as subID, but registers hero classes as subtypes
|
||||||
|
// Spell scroll: uses spell ID as subID
|
||||||
|
if(type == Obj::PRISON || type == Obj::HERO || type == Obj::SPELL_SCROLL)
|
||||||
|
subtype = 0;
|
||||||
|
|
||||||
|
assert(type < objects.size());
|
||||||
|
assert(objects[type]);
|
||||||
|
assert(subtype < objects[type]->objects.size());
|
||||||
|
|
||||||
return getHandlerFor(type, subtype)->getSounds();
|
return getHandlerFor(type, subtype)->getSounds();
|
||||||
else
|
|
||||||
return getObjectSounds(type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CObjectClassesHandler::getObjectHandlerName(si32 type) const
|
std::string CObjectClassesHandler::getObjectHandlerName(si32 type) const
|
||||||
@@ -424,11 +431,6 @@ std::string CObjectClassesHandler::getObjectHandlerName(si32 type) const
|
|||||||
return objects.at(type)->handlerName;
|
return objects.at(type)->handlerName;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<si32> CObjectClassesHandler::getObjGroupAiValue(si32 primaryID) const
|
|
||||||
{
|
|
||||||
return objects.at(primaryID)->groupDefaultAiValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
AObjectTypeHandler::AObjectTypeHandler():
|
AObjectTypeHandler::AObjectTypeHandler():
|
||||||
type(-1), subtype(-1)
|
type(-1), subtype(-1)
|
||||||
{
|
{
|
||||||
@@ -439,16 +441,29 @@ AObjectTypeHandler::~AObjectTypeHandler()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void AObjectTypeHandler::setType(si32 type, si32 subtype)
|
std::string AObjectTypeHandler::getJsonKey() const
|
||||||
{
|
{
|
||||||
this->type = type;
|
return modScope + ':' + subTypeName;
|
||||||
this->subtype = subtype;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AObjectTypeHandler::setTypeName(std::string type, std::string subtype)
|
si32 AObjectTypeHandler::getIndex() const
|
||||||
{
|
{
|
||||||
this->typeName = type;
|
return type;
|
||||||
this->subTypeName = subtype;
|
}
|
||||||
|
|
||||||
|
si32 AObjectTypeHandler::getSubIndex() const
|
||||||
|
{
|
||||||
|
return subtype;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string AObjectTypeHandler::getTypeName() const
|
||||||
|
{
|
||||||
|
return typeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string AObjectTypeHandler::getSubTypeName() const
|
||||||
|
{
|
||||||
|
return subTypeName;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ui32 loadJsonOrMax(const JsonNode & input)
|
static ui32 loadJsonOrMax(const JsonNode & input)
|
||||||
@@ -459,7 +474,7 @@ static ui32 loadJsonOrMax(const JsonNode & input)
|
|||||||
return static_cast<ui32>(input.Float());
|
return static_cast<ui32>(input.Float());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AObjectTypeHandler::init(const JsonNode & input, boost::optional<std::string> name)
|
void AObjectTypeHandler::init(const JsonNode & input)
|
||||||
{
|
{
|
||||||
base = input["base"];
|
base = input["base"];
|
||||||
|
|
||||||
@@ -491,11 +506,6 @@ void AObjectTypeHandler::init(const JsonNode & input, boost::optional<std::strin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input["name"].isNull())
|
|
||||||
objectName = name;
|
|
||||||
else
|
|
||||||
objectName.reset(input["name"].String());
|
|
||||||
|
|
||||||
for(const JsonNode & node : input["sounds"]["ambient"].Vector())
|
for(const JsonNode & node : input["sounds"]["ambient"].Vector())
|
||||||
sounds.ambient.push_back(node.String());
|
sounds.ambient.push_back(node.String());
|
||||||
|
|
||||||
@@ -536,9 +546,19 @@ void AObjectTypeHandler::initTypeData(const JsonNode & input)
|
|||||||
// empty implementation for overrides
|
// empty implementation for overrides
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<std::string> AObjectTypeHandler::getCustomName() const
|
bool AObjectTypeHandler::hasNameTextID() const
|
||||||
{
|
{
|
||||||
return objectName;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string AObjectTypeHandler::getNameTextID() const
|
||||||
|
{
|
||||||
|
return TextIdentifier("mapObject", modScope, typeName, subTypeName, "name").get();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string AObjectTypeHandler::getNameTranslated() const
|
||||||
|
{
|
||||||
|
return VLC->generaltexth->translate(getNameTextID());
|
||||||
}
|
}
|
||||||
|
|
||||||
SObjectSounds AObjectTypeHandler::getSounds() const
|
SObjectSounds AObjectTypeHandler::getSounds() const
|
||||||
|
@@ -136,12 +136,12 @@ public:
|
|||||||
|
|
||||||
class CGObjectInstance;
|
class CGObjectInstance;
|
||||||
|
|
||||||
|
/// Class responsible for creation of objects of specific type & subtype
|
||||||
class DLL_LINKAGE AObjectTypeHandler : public boost::noncopyable
|
class DLL_LINKAGE AObjectTypeHandler : public boost::noncopyable
|
||||||
{
|
{
|
||||||
RandomMapInfo rmgInfo;
|
friend class CObjectClassesHandler;
|
||||||
|
|
||||||
/// Human-readable name of this object, used for objects like banks and dwellings, if set
|
RandomMapInfo rmgInfo;
|
||||||
boost::optional<std::string> objectName;
|
|
||||||
|
|
||||||
JsonNode base; /// describes base template
|
JsonNode base; /// describes base template
|
||||||
|
|
||||||
@@ -150,9 +150,15 @@ class DLL_LINKAGE AObjectTypeHandler : public boost::noncopyable
|
|||||||
SObjectSounds sounds;
|
SObjectSounds sounds;
|
||||||
|
|
||||||
boost::optional<si32> aiValue;
|
boost::optional<si32> aiValue;
|
||||||
|
|
||||||
boost::optional<std::string> battlefield;
|
boost::optional<std::string> battlefield;
|
||||||
|
|
||||||
|
std::string modScope;
|
||||||
|
std::string typeName;
|
||||||
|
std::string subTypeName;
|
||||||
|
|
||||||
|
si32 type;
|
||||||
|
si32 subtype;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void preInitObject(CGObjectInstance * obj) const;
|
void preInitObject(CGObjectInstance * obj) const;
|
||||||
virtual bool objectFilter(const CGObjectInstance *, std::shared_ptr<const ObjectTemplate>) const;
|
virtual bool objectFilter(const CGObjectInstance *, std::shared_ptr<const ObjectTemplate>) const;
|
||||||
@@ -160,22 +166,23 @@ protected:
|
|||||||
/// initialization for classes that inherit this one
|
/// initialization for classes that inherit this one
|
||||||
virtual void initTypeData(const JsonNode & input);
|
virtual void initTypeData(const JsonNode & input);
|
||||||
public:
|
public:
|
||||||
std::string typeName;
|
|
||||||
std::string subTypeName;
|
|
||||||
|
|
||||||
si32 type;
|
|
||||||
si32 subtype;
|
|
||||||
AObjectTypeHandler();
|
AObjectTypeHandler();
|
||||||
virtual ~AObjectTypeHandler();
|
virtual ~AObjectTypeHandler();
|
||||||
|
|
||||||
void setType(si32 type, si32 subtype);
|
si32 getIndex() const;
|
||||||
void setTypeName(std::string type, std::string subtype);
|
si32 getSubIndex() const;
|
||||||
|
|
||||||
|
std::string getTypeName() const;
|
||||||
|
std::string getSubTypeName() const;
|
||||||
|
|
||||||
/// loads generic data from Json structure and passes it towards type-specific constructors
|
/// loads generic data from Json structure and passes it towards type-specific constructors
|
||||||
void init(const JsonNode & input, boost::optional<std::string> name = boost::optional<std::string>());
|
void init(const JsonNode & input);
|
||||||
|
|
||||||
|
/// returns full form of identifier of this object in form of modName:objectName
|
||||||
|
std::string getJsonKey() const;
|
||||||
|
|
||||||
/// Returns object-specific name, if set
|
/// Returns object-specific name, if set
|
||||||
boost::optional<std::string> getCustomName() const;
|
|
||||||
SObjectSounds getSounds() const;
|
SObjectSounds getSounds() const;
|
||||||
|
|
||||||
void addTemplate(std::shared_ptr<const ObjectTemplate> templ);
|
void addTemplate(std::shared_ptr<const ObjectTemplate> templ);
|
||||||
@@ -191,13 +198,19 @@ public:
|
|||||||
|
|
||||||
BattleField getBattlefield() const;
|
BattleField getBattlefield() const;
|
||||||
|
|
||||||
/// returns preferred template for this object, if present (e.g. one of 3 possible templates for town - village, fort and castle)
|
|
||||||
/// note that appearance will not be changed - this must be done separately (either by assignment or via pack from server)
|
|
||||||
|
|
||||||
const RandomMapInfo & getRMGInfo();
|
const RandomMapInfo & getRMGInfo();
|
||||||
|
|
||||||
boost::optional<si32> getAiValue() const;
|
boost::optional<si32> getAiValue() const;
|
||||||
|
|
||||||
|
/// returns true if this class provides custom text ID's instead of generic per-object name
|
||||||
|
virtual bool hasNameTextID() const;
|
||||||
|
|
||||||
|
/// returns object's name in form of translatable text ID
|
||||||
|
virtual std::string getNameTextID() const;
|
||||||
|
|
||||||
|
/// returns object's name in form of human-readable text
|
||||||
|
std::string getNameTranslated() const;
|
||||||
|
|
||||||
virtual bool isStaticObject();
|
virtual bool isStaticObject();
|
||||||
|
|
||||||
virtual void afterLoadFinalization();
|
virtual void afterLoadFinalization();
|
||||||
@@ -219,7 +232,7 @@ public:
|
|||||||
h & subtype;
|
h & subtype;
|
||||||
h & templates;
|
h & templates;
|
||||||
h & rmgInfo;
|
h & rmgInfo;
|
||||||
h & objectName;
|
h & modScope;
|
||||||
h & typeName;
|
h & typeName;
|
||||||
h & subTypeName;
|
h & subTypeName;
|
||||||
h & sounds;
|
h & sounds;
|
||||||
@@ -230,40 +243,40 @@ public:
|
|||||||
|
|
||||||
typedef std::shared_ptr<AObjectTypeHandler> TObjectTypeHandler;
|
typedef std::shared_ptr<AObjectTypeHandler> TObjectTypeHandler;
|
||||||
|
|
||||||
class DLL_LINKAGE CObjectClassesHandler : public IHandlerBase
|
/// Class responsible for creation of adventure map objects of specific type
|
||||||
|
class DLL_LINKAGE ObjectClass
|
||||||
{
|
{
|
||||||
/// Small internal structure that contains information on specific group of objects
|
public:
|
||||||
/// (creating separate entity is overcomplicating at least at this point)
|
std::string modScope;
|
||||||
struct ObjectContainter
|
|
||||||
{
|
|
||||||
si32 id;
|
|
||||||
std::string identifier;
|
std::string identifier;
|
||||||
std::string name; // human-readable name
|
|
||||||
|
si32 id;
|
||||||
std::string handlerName; // ID of handler that controls this object, should be determined using handlerConstructor map
|
std::string handlerName; // ID of handler that controls this object, should be determined using handlerConstructor map
|
||||||
|
|
||||||
JsonNode base;
|
JsonNode base;
|
||||||
std::map<si32, TObjectTypeHandler> subObjects;
|
std::vector<TObjectTypeHandler> objects;
|
||||||
std::map<std::string, si32> subIds;//full id from core scope -> subtype
|
|
||||||
|
|
||||||
SObjectSounds sounds;
|
ObjectClass() = default;
|
||||||
|
|
||||||
boost::optional<si32> groupDefaultAiValue;
|
std::string getJsonKey() const;
|
||||||
|
std::string getNameTextID() const;
|
||||||
|
std::string getNameTranslated() const;
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & name;
|
|
||||||
h & handlerName;
|
h & handlerName;
|
||||||
h & base;
|
h & base;
|
||||||
h & subObjects;
|
h & objects;
|
||||||
h & identifier;
|
h & identifier;
|
||||||
h & subIds;
|
h & modScope;
|
||||||
h & sounds;
|
|
||||||
h & groupDefaultAiValue;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Main class responsible for creation of all adventure map objects
|
||||||
|
class DLL_LINKAGE CObjectClassesHandler : public IHandlerBase
|
||||||
|
{
|
||||||
/// list of object handlers, each of them handles only one type
|
/// list of object handlers, each of them handles only one type
|
||||||
std::map<si32, ObjectContainter * > objects;
|
std::vector<ObjectClass * > objects;
|
||||||
|
|
||||||
/// map that is filled during contruction with all known handlers. Not serializeable due to usage of std::function
|
/// map that is filled during contruction with all known handlers. Not serializeable due to usage of std::function
|
||||||
std::map<std::string, std::function<TObjectTypeHandler()> > handlerConstructors;
|
std::map<std::string, std::function<TObjectTypeHandler()> > handlerConstructors;
|
||||||
@@ -272,12 +285,12 @@ class DLL_LINKAGE CObjectClassesHandler : public IHandlerBase
|
|||||||
typedef std::multimap<std::pair<si32, si32>, std::shared_ptr<const ObjectTemplate>> TTemplatesContainer;
|
typedef std::multimap<std::pair<si32, si32>, std::shared_ptr<const ObjectTemplate>> TTemplatesContainer;
|
||||||
TTemplatesContainer legacyTemplates;
|
TTemplatesContainer legacyTemplates;
|
||||||
|
|
||||||
/// contains list of custom names for H3 objects (e.g. Dwellings), used to load H3 data
|
TObjectTypeHandler loadSubObjectFromJson(const std::string & scope, const std::string & identifier, const JsonNode & entry, ObjectClass * obj, size_t index);
|
||||||
/// format: customNames[primaryID][secondaryID] -> name
|
|
||||||
std::map<si32, std::vector<std::string>> customNames;
|
|
||||||
|
|
||||||
void loadObjectEntry(const std::string & identifier, const JsonNode & entry, ObjectContainter * obj, bool isSubobject = false);
|
void loadSubObject(const std::string & scope, const std::string & identifier, const JsonNode & entry, ObjectClass * obj);
|
||||||
ObjectContainter * loadFromJson(const std::string & scope, const JsonNode & json, const std::string & name);
|
void loadSubObject(const std::string & scope, const std::string & identifier, const JsonNode & entry, ObjectClass * obj, size_t index);
|
||||||
|
|
||||||
|
ObjectClass * loadFromJson(const std::string & scope, const JsonNode & json, const std::string & name, size_t index);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CObjectClassesHandler();
|
CObjectClassesHandler();
|
||||||
@@ -288,7 +301,7 @@ public:
|
|||||||
void loadObject(std::string scope, std::string name, const JsonNode & data) override;
|
void loadObject(std::string scope, std::string name, const JsonNode & data) override;
|
||||||
void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) override;
|
void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) override;
|
||||||
|
|
||||||
void loadSubObject(const std::string & identifier, JsonNode config, si32 ID, boost::optional<si32> subID = boost::optional<si32>());
|
void loadSubObject(const std::string & identifier, JsonNode config, si32 ID, si32 subID);
|
||||||
void removeSubObject(si32 ID, si32 subID);
|
void removeSubObject(si32 ID, si32 subID);
|
||||||
|
|
||||||
void beforeValidate(JsonNode & object) override;
|
void beforeValidate(JsonNode & object) override;
|
||||||
@@ -305,17 +318,13 @@ public:
|
|||||||
TObjectTypeHandler getHandlerFor(std::string scope, std::string type, std::string subtype) const;
|
TObjectTypeHandler getHandlerFor(std::string scope, std::string type, std::string subtype) const;
|
||||||
TObjectTypeHandler getHandlerFor(CompoundMapObjectID compoundIdentifier) const;
|
TObjectTypeHandler getHandlerFor(CompoundMapObjectID compoundIdentifier) const;
|
||||||
|
|
||||||
std::string getObjectName(si32 type) const;
|
|
||||||
std::string getObjectName(si32 type, si32 subtype) const;
|
std::string getObjectName(si32 type, si32 subtype) const;
|
||||||
|
|
||||||
SObjectSounds getObjectSounds(si32 type) const;
|
|
||||||
SObjectSounds getObjectSounds(si32 type, si32 subtype) const;
|
SObjectSounds getObjectSounds(si32 type, si32 subtype) const;
|
||||||
|
|
||||||
/// Returns handler string describing the handler (for use in client)
|
/// Returns handler string describing the handler (for use in client)
|
||||||
std::string getObjectHandlerName(si32 type) const;
|
std::string getObjectHandlerName(si32 type) const;
|
||||||
|
|
||||||
boost::optional<si32> getObjGroupAiValue(si32 primaryID) const; //default AI value of objects belonging to particular primaryID
|
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & objects;
|
h & objects;
|
||||||
|
@@ -1171,7 +1171,7 @@ void CGBorderGuard::getVisitText (MetaString &text, std::vector<Component> &comp
|
|||||||
void CGBorderGuard::getRolloverText (MetaString &text, bool onHover) const
|
void CGBorderGuard::getRolloverText (MetaString &text, bool onHover) const
|
||||||
{
|
{
|
||||||
if (!onHover)
|
if (!onHover)
|
||||||
text << VLC->generaltexth->tentColors[subID] << " " << VLC->objtypeh->getObjectName(Obj::KEYMASTER);
|
text << VLC->generaltexth->tentColors[subID] << " " << VLC->objtypeh->getObjectName(Obj::KEYMASTER, subID);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CGBorderGuard::checkQuest(const CGHeroInstance * h) const
|
bool CGBorderGuard::checkQuest(const CGHeroInstance * h) const
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
#include "../TerrainHandler.h"
|
#include "../TerrainHandler.h"
|
||||||
#include "../mapping/CMap.h"
|
#include "../mapping/CMap.h"
|
||||||
#include "../CHeroHandler.h"
|
#include "../CHeroHandler.h"
|
||||||
|
#include "../CGeneralTextHandler.h"
|
||||||
#include "../CCreatureHandler.h"
|
#include "../CCreatureHandler.h"
|
||||||
#include "JsonRandom.h"
|
#include "JsonRandom.h"
|
||||||
#include "../CModHandler.h"
|
#include "../CModHandler.h"
|
||||||
@@ -150,8 +151,18 @@ CDwellingInstanceConstructor::CDwellingInstanceConstructor()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CDwellingInstanceConstructor::hasNameTextID() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void CDwellingInstanceConstructor::initTypeData(const JsonNode & input)
|
void CDwellingInstanceConstructor::initTypeData(const JsonNode & input)
|
||||||
{
|
{
|
||||||
|
if (input.Struct().count("name") == 0)
|
||||||
|
logMod->warn("Dwelling %s missing name!", getJsonKey());
|
||||||
|
|
||||||
|
VLC->generaltexth->registerString(getNameTextID(), input["name"].String());
|
||||||
|
|
||||||
const JsonVector & levels = input["creatures"].Vector();
|
const JsonVector & levels = input["creatures"].Vector();
|
||||||
const auto totalLevels = levels.size();
|
const auto totalLevels = levels.size();
|
||||||
|
|
||||||
@@ -272,9 +283,18 @@ CBankInstanceConstructor::CBankInstanceConstructor()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CBankInstanceConstructor::hasNameTextID() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void CBankInstanceConstructor::initTypeData(const JsonNode & input)
|
void CBankInstanceConstructor::initTypeData(const JsonNode & input)
|
||||||
{
|
{
|
||||||
//TODO: name = input["name"].String();
|
if (input.Struct().count("name") == 0)
|
||||||
|
logMod->warn("Bank %s missing name!", getJsonKey());
|
||||||
|
|
||||||
|
VLC->generaltexth->registerString(getNameTextID(), input["name"].String());
|
||||||
|
|
||||||
levels = input["levels"].Vector();
|
levels = input["levels"].Vector();
|
||||||
bankResetDuration = static_cast<si32>(input["resetDuration"].Float());
|
bankResetDuration = static_cast<si32>(input["resetDuration"].Float());
|
||||||
}
|
}
|
||||||
|
@@ -127,6 +127,7 @@ protected:
|
|||||||
void initTypeData(const JsonNode & input) override;
|
void initTypeData(const JsonNode & input) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
bool hasNameTextID() const override;
|
||||||
|
|
||||||
CDwellingInstanceConstructor();
|
CDwellingInstanceConstructor();
|
||||||
CGObjectInstance * create(std::shared_ptr<const ObjectTemplate> tmpl = nullptr) const override;
|
CGObjectInstance * create(std::shared_ptr<const ObjectTemplate> tmpl = nullptr) const override;
|
||||||
@@ -218,6 +219,8 @@ public:
|
|||||||
CGObjectInstance * create(std::shared_ptr<const ObjectTemplate> tmpl = nullptr) const override;
|
CGObjectInstance * create(std::shared_ptr<const ObjectTemplate> tmpl = nullptr) const override;
|
||||||
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const override;
|
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const override;
|
||||||
|
|
||||||
|
bool hasNameTextID() const override;
|
||||||
|
|
||||||
std::unique_ptr<IObjectInfo> getObjectInfo(std::shared_ptr<const ObjectTemplate> tmpl) const override;
|
std::unique_ptr<IObjectInfo> getObjectInfo(std::shared_ptr<const ObjectTemplate> tmpl) const override;
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
|
@@ -559,6 +559,9 @@ void ObjectTemplate::recalculate()
|
|||||||
calculateBlockedOffsets();
|
calculateBlockedOffsets();
|
||||||
calculateBlockMapOffset();
|
calculateBlockMapOffset();
|
||||||
calculateVisitableOffset();
|
calculateVisitableOffset();
|
||||||
|
|
||||||
|
if (visitable && visitDir == 0)
|
||||||
|
logMod->warn("Template for %s is visitable but has no visitable directions!", animationFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
@@ -172,7 +172,7 @@ namespace TriggeredEventsDetail
|
|||||||
{
|
{
|
||||||
si32 subtype = *subtypes.begin();
|
si32 subtype = *subtypes.begin();
|
||||||
auto handler = VLC->objtypeh->getHandlerFor(type, subtype);
|
auto handler = VLC->objtypeh->getHandlerFor(type, subtype);
|
||||||
identifier = handler->typeName;
|
identifier = handler->getTypeName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1159,8 +1159,8 @@ void CMapLoaderJson::MapObjectLoader::construct()
|
|||||||
|
|
||||||
auto appearance = new ObjectTemplate;
|
auto appearance = new ObjectTemplate;
|
||||||
|
|
||||||
appearance->id = Obj(handler->type);
|
appearance->id = Obj(handler->getIndex());
|
||||||
appearance->subid = handler->subtype;
|
appearance->subid = handler->getSubIndex();
|
||||||
appearance->readJson(configuration["template"], false);
|
appearance->readJson(configuration["template"], false);
|
||||||
|
|
||||||
// Will be destroyed soon and replaced with shared template
|
// Will be destroyed soon and replaced with shared template
|
||||||
|
@@ -468,6 +468,9 @@ void MainWindow::addGroupIntoCatalog(const std::string & groupName, bool useCust
|
|||||||
itemGroup = itms.front();
|
itemGroup = itms.front();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (VLC->objtypeh->knownObjects().count(ID) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
auto knownSubObjects = VLC->objtypeh->knownSubObjects(ID);
|
auto knownSubObjects = VLC->objtypeh->knownSubObjects(ID);
|
||||||
for(auto secondaryID : knownSubObjects)
|
for(auto secondaryID : knownSubObjects)
|
||||||
{
|
{
|
||||||
@@ -477,10 +480,7 @@ void MainWindow::addGroupIntoCatalog(const std::string & groupName, bool useCust
|
|||||||
if(staticOnly && !factory->isStaticObject())
|
if(staticOnly && !factory->isStaticObject())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto subGroupName = QString::fromStdString(factory->subTypeName);
|
auto subGroupName = QString::fromStdString(factory->getNameTranslated());
|
||||||
auto customName = factory->getCustomName();
|
|
||||||
if(customName)
|
|
||||||
subGroupName = tr(customName->c_str());
|
|
||||||
|
|
||||||
auto * itemType = new QStandardItem(subGroupName);
|
auto * itemType = new QStandardItem(subGroupName);
|
||||||
for(int templateId = 0; templateId < templates.size(); ++templateId)
|
for(int templateId = 0; templateId < templates.size(); ++templateId)
|
||||||
|
@@ -106,8 +106,8 @@ void MapController::repairMap()
|
|||||||
if(obj->ID != Obj::HERO && obj->ID != Obj::PRISON && (obj->typeName.empty() || obj->subTypeName.empty()))
|
if(obj->ID != Obj::HERO && obj->ID != Obj::PRISON && (obj->typeName.empty() || obj->subTypeName.empty()))
|
||||||
{
|
{
|
||||||
auto handler = VLC->objtypeh->getHandlerFor(obj->ID, obj->subID);
|
auto handler = VLC->objtypeh->getHandlerFor(obj->ID, obj->subID);
|
||||||
obj->typeName = handler->typeName;
|
obj->typeName = handler->getTypeName();
|
||||||
obj->subTypeName = handler->subTypeName;
|
obj->subTypeName = handler->getSubTypeName();
|
||||||
}
|
}
|
||||||
//fix flags
|
//fix flags
|
||||||
if(obj->getOwner() == PlayerColor::UNFLAGGABLE)
|
if(obj->getOwner() == PlayerColor::UNFLAGGABLE)
|
||||||
|
Reference in New Issue
Block a user