1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

- Implementation of overrides for towns

- Converted dwellings.json into new format
- Implemented "mapObject" entry in town format
- Removed capital/fort/village fields from town in favor of overrides
This commit is contained in:
Ivan Savenko 2014-06-15 19:43:01 +03:00
parent 7cfd9a0903
commit 836c466f81
27 changed files with 340 additions and 288 deletions

View File

@ -500,7 +500,7 @@ void CKingdomInterface::generateObjectsList(const std::vector<const CGObjectInst
OwnedObjectInfo &info = visibleObjects[object->subID];
if (info.count++ == 0)
{
info.hoverText = CGI->creh->creatures[CGI->objh->cregens.find(object->subID)->second]->namePl;
info.hoverText = object->getHoverText();
info.imageID = object->subID;
}
}

View File

@ -1,108 +0,0 @@
{
// Indicate which dwelling produces which creature
// Note that it is 1<->n connection since
// a creature can be produced by more than one dwelling.
"dwellings": [
{ "dwelling": 0, "creature": 106 },
{ "dwelling": 1, "creature": 96 },
{ "dwelling": 2, "creature": 74 },
{ "dwelling": 3, "creature": 66 },
{ "dwelling": 4, "creature": 68 },
{ "dwelling": 5, "creature": 10 },
{ "dwelling": 6, "creature": 14 },
{ "dwelling": 7, "creature": 112 },
{ "dwelling": 8, "creature": 12 },
{ "dwelling": 9, "creature": 94 },
{ "dwelling": 10, "creature": 54 },
{ "dwelling": 11, "creature": 104 },
{ "dwelling": 12, "creature": 16 },
{ "dwelling": 13, "creature": 113 },
{ "dwelling": 14, "creature": 52 },
{ "dwelling": 15, "creature": 18 },
{ "dwelling": 16, "creature": 114 },
{ "dwelling": 17, "creature": 30 },
{ "dwelling": 18, "creature": 36 },
{ "dwelling": 19, "creature": 86 },
{ "dwelling": 20, "creature": 98 },
{ "dwelling": 21, "creature": 84 },
{ "dwelling": 22, "creature": 44 },
{ "dwelling": 23, "creature": 102 },
{ "dwelling": 24, "creature": 26 },
{ "dwelling": 25, "creature": 4 },
{ "dwelling": 26, "creature": 72 },
{ "dwelling": 27, "creature": 46 },
{ "dwelling": 28, "creature": 110 },
{ "dwelling": 29, "creature": 42 },
{ "dwelling": 30, "creature": 100 },
{ "dwelling": 31, "creature": 34 },
{ "dwelling": 32, "creature": 80 },
{ "dwelling": 33, "creature": 76 },
{ "dwelling": 34, "creature": 78 },
{ "dwelling": 35, "creature": 8 },
{ "dwelling": 36, "creature": 38 },
{ "dwelling": 37, "creature": 48 },
{ "dwelling": 38, "creature": 90 },
{ "dwelling": 39, "creature": 88 },
{ "dwelling": 40, "creature": 50 },
{ "dwelling": 41, "creature": 82 },
{ "dwelling": 42, "creature": 92 },
{ "dwelling": 43, "creature": 28 },
{ "dwelling": 44, "creature": 40 },
{ "dwelling": 45, "creature": 22 },
{ "dwelling": 46, "creature": 70 },
{ "dwelling": 47, "creature": 115 },
{ "dwelling": 48, "creature": 60 },
{ "dwelling": 49, "creature": 108 },
{ "dwelling": 50, "creature": 20 },
{ "dwelling": 51, "creature": 24 },
{ "dwelling": 52, "creature": 64 },
{ "dwelling": 53, "creature": 62 },
{ "dwelling": 54, "creature": 56 },
{ "dwelling": 55, "creature": 58 },
{ "dwelling": 56, "creature": 0 },
{ "dwelling": 57, "creature": 2 },
{ "dwelling": 58, "creature": 6 },
{ "dwelling": 59, "creature": 118 },
{ "dwelling": 60, "creature": 120 },
{ "dwelling": 61, "creature": 130 },
{ "dwelling": 62, "creature": 132 },
{ "dwelling": 63, "creature": 133 },
{ "dwelling": 64, "creature": 134 },
{ "dwelling": 65, "creature": 135 },
{ "dwelling": 66, "creature": 136 },
{ "dwelling": 67, "creature": 137 },
{ "dwelling": 68, "creature": 24 },
{ "dwelling": 69, "creature": 112 },
{ "dwelling": 70, "creature": 113 },
{ "dwelling": 71, "creature": 114 },
{ "dwelling": 72, "creature": 115 },
{ "dwelling": 73, "creature": 138 },
{ "dwelling": 74, "creature": 139 },
{ "dwelling": 75, "creature": 140 },
{ "dwelling": 76, "creature": 141 },
{ "dwelling": 77, "creature": 142 },
{ "dwelling": 78, "creature": 143 },
{ "dwelling": 79, "creature": 144 },
{ "dwelling": 80, "creature": 150 },
{ "dwelling": 81, "creature": 151 },
{ "dwelling": 82, "creature": 152 },
{ "dwelling": 83, "creature": 153 },
{ "dwelling": 84, "creature": 154 },
{ "dwelling": 85, "creature": 155 },
{ "dwelling": 86, "creature": 156 },
{ "dwelling": 87, "creature": 157 },
{ "dwelling": 88, "creature": 158 },
{ "dwelling": 89, "creature": 171 },
{ "dwelling": 90, "creature": 170 },
{ "dwelling": 91, "creature": 168 },
{ "dwelling": 92, "creature": 172 },
{ "dwelling": 93, "creature": 164 },
{ "dwelling": 94, "creature": 169 },
{ "dwelling": 95, "creature": 173 },
{ "dwelling": 96, "creature": 192 },
{ "dwelling": 97, "creature": 193 },
{ "dwelling": 98, "creature": 194 },
{ "dwelling": 99, "creature": 195 },
{ "dwelling": 100, "creature": 196 }
]
}

View File

@ -66,11 +66,13 @@
},
"town" :
{
"adventureMap" :
"mapObject" :
{
"castle" : "AVCcasx0.def",
"village" : "AVCCAST0.DEF",
"capitol" : "AVCCASZ0.DEF"
"templates" : {
"castle" : { "animation" : "AVCcasx0.def" },
"village" : { "animation" : "AVCCAST0.DEF" },
"capitol" : { "animation" : "AVCCASZ0.DEF" }
}
},
"structures" :
{

View File

@ -66,11 +66,13 @@
},
"town" :
{
"adventureMap" :
"mapObject" :
{
"castle" : "avchforx.def",
"village" : "AVCHFOR0.DEF",
"capitol" : "AVCHFORZ.DEF"
"templates" : {
"castle" : { "animation" : "avchforx.def" },
"village" : { "animation" : "AVCHFOR0.DEF" },
"capitol" : { "animation" : "AVCHFORZ.DEF" }
}
},
"structures" :
{

View File

@ -66,11 +66,13 @@
},
"town" :
{
"adventureMap" :
"mapObject" :
{
"castle" : "AVCdunx0.def",
"village" : "AVCDUNG0.DEF",
"capitol" : "AVCDUNZ0.DEF"
"templates" : {
"castle" : { "animation" : "AVCdunx0.def" },
"village" : { "animation" : "AVCDUNG0.DEF" },
"capitol" : { "animation" : "AVCDUNZ0.DEF" }
}
},
"structures" :
{

View File

@ -66,11 +66,13 @@
},
"town" :
{
"adventureMap" :
"mapObject" :
{
"castle" : "AVCftrx0.def",
"village" : "AVCFTRT0.DEF",
"capitol" : "AVCFORZ0.DEF"
"templates" : {
"castle" : { "animation" : "AVCftrx0.def" },
"village" : { "animation" : "AVCFTRT0.DEF" },
"capitol" : { "animation" : "AVCFORZ0.DEF" }
}
},
"structures" :
{

View File

@ -66,11 +66,13 @@
},
"town" :
{
"adventureMap" :
"mapObject" :
{
"castle" : "AVCinfx0.def",
"village" : "AVCINFT0.DEF",
"capitol" : "AVCINFZ0.DEF"
"templates" : {
"castle" : { "animation" : "AVCinfx0.def" },
"village" : { "animation" : "AVCINFT0.DEF" },
"capitol" : { "animation" : "AVCINFZ0.DEF" }
}
},
"structures" :
{

View File

@ -66,11 +66,13 @@
},
"town" :
{
"adventureMap" :
"mapObject" :
{
"castle" : "AVCnecx0.def",
"village" : "AVCNECR0.DEF",
"capitol" : "AVCNECZ0.DEF"
"templates" : {
"castle" : { "animation" : "AVCnecx0.def" },
"village" : { "animation" : "AVCNECR0.DEF" },
"capitol" : { "animation" : "AVCNECZ0.DEF" }
}
},
"structures" :
{

View File

@ -66,11 +66,13 @@
},
"town" :
{
"adventureMap" :
"mapObject" :
{
"castle" : "AVCramx0.def",
"village" : "AVCRAMP0.DEF",
"capitol" : "AVCRAMZ0.DEF"
"templates" : {
"castle" : { "animation" : "AVCramx0.def" },
"village" : { "animation" : "AVCRAMP0.DEF" },
"capitol" : { "animation" : "AVCRAMZ0.DEF" }
}
},
"structures" :
{

View File

@ -66,11 +66,13 @@
},
"town" :
{
"adventureMap" :
"mapObject" :
{
"castle" : "AVCstrx0.def",
"village" : "AVCSTRO0.DEF",
"capitol" : "AVCSTRZ0.DEF"
"templates" : {
"castle" : { "animation" : "AVCstrx0.def" },
"village" : { "animation" : "AVCSTRO0.DEF" },
"capitol" : { "animation" : "AVCSTRZ0.DEF" }
}
},
"structures" :
{

View File

@ -66,11 +66,13 @@
},
"town" :
{
"adventureMap" :
"mapObject" :
{
"castle" : "AVCtowx0.def",
"village" : "AVCTOWR0.DEF",
"capitol" : "AVCTOWZ0.DEF"
"templates" : {
"castle" : { "animation" : "AVCtowx0.def" },
"village" : { "animation" : "AVCTOWR0.DEF" },
"capitol" : { "animation" : "AVCTOWZ0.DEF" }
}
},
"structures" :
{

View File

@ -49,6 +49,7 @@
[
"config/objects/generic.json",
"config/objects/moddables.json",
"config/objects/dwellings.json",
"config/objects/rewardable.json"
],

View File

@ -0,0 +1,126 @@
{
"creatureGeneratorCommon" : {
"index" :17,
"handler": "dwelling",
"base" : {
"base" : {
"visitableFrom" : [ "---", "+++", "+++" ],
"mask" : [ "VVV", "VBB", "VAA" ]
}
},
"types" : {
"basiliskPit" : { "index" : 0, "creatures" : [ [ "basilisk" ] ] },
"behemothCrag" : { "index" : 1, "creatures" : [ [ "behemoth" ] ], "guards" : true },
"pillarOfEyes" : { "index" : 2, "creatures" : [ [ "beholder" ] ] },
"hallOfDarkness" : { "index" : 3, "creatures" : [ [ "blackKnight" ] ], "guards" : true },
"dragonVault" : { "index" : 4, "creatures" : [ [ "boneDragon" ] ], "guards" : true },
"trainingGrounds" : { "index" : 5, "creatures" : [ [ "cavalier" ] ], "guards" : true },
"centaurStables" : { "index" : 6, "creatures" : [ [ "centaur" ] ] },
"airConflux" : { "index" : 7, "creatures" : [ [ "airElemental" ] ] },
"portalOfGlory" : { "index" : 8, "creatures" : [ [ "angel" ] ], "guards" : true },
"cyclopsCave" : { "index" : 9, "creatures" : [ [ "cyclop" ] ], "guards" : true },
"forsakenPalace" : { "index" : 10, "creatures" : [ [ "devil" ] ], "guards" : true },
"serpentFlyHive" : { "index" : 11, "creatures" : [ [ "serpentFly" ] ] },
"dwarfCottage" : { "index" : 12, "creatures" : [ [ "dwarf" ] ] },
"earthConflux" : { "index" : 13, "creatures" : [ [ "earthElemental" ] ], "guards" : true },
"fireLake" : { "index" : 14, "creatures" : [ [ "efreet" ] ], "guards" : true },
"homestead" : { "index" : 15, "creatures" : [ [ "woodElf" ] ] },
"fireConflux" : { "index" : 16, "creatures" : [ [ "fireElemental" ] ] },
"parapet" : { "index" : 17, "creatures" : [ [ "stoneGargoyle" ] ] },
"altarOfWishes" : { "index" : 18, "creatures" : [ [ "genie" ] ], "guards" : true },
"wolfPen" : { "index" : 19, "creatures" : [ [ "goblinWolfRider" ] ] },
"gnollHut" : { "index" : 20, "creatures" : [ [ "gnoll" ] ] },
"goblinBarracks" : { "index" : 21, "creatures" : [ [ "goblin" ] ] },
"hallOfSins" : { "index" : 22, "creatures" : [ [ "gog" ] ] },
"gorgonLair" : { "index" : 23, "creatures" : [ [ "gorgon" ] ], "guards" : true },
"dragonCliffs" : { "index" : 24, "creatures" : [ [ "greenDragon" ] ], "guards" : true },
"griffinTower" : { "index" : 25, "creatures" : [ [ "griffin" ] ] },
"harpyLoft" : { "index" : 26, "creatures" : [ [ "harpy" ] ] },
"kennels" : { "index" : 27, "creatures" : [ [ "hellHound" ] ] },
"hydraPond" : { "index" : 28, "creatures" : [ [ "hydra" ] ], "guards" : true },
"impCrucible" : { "index" : 29, "creatures" : [ [ "imp" ] ] },
"lizardDen" : { "index" : 30, "creatures" : [ [ "lizardman" ] ] },
"mageTower" : { "index" : 31, "creatures" : [ [ "mage" ] ] },
"manticoreLair" : { "index" : 32, "creatures" : [ [ "manticore" ] ], "guards" : true },
"medusaChapel" : { "index" : 33, "creatures" : [ [ "medusa" ] ] },
"labyrinth" : { "index" : 34, "creatures" : [ [ "minotaur" ] ], "guards" : true },
"monastery" : { "index" : 35, "creatures" : [ [ "monk" ] ], "guards" : true },
"goldenPavilion" : { "index" : 36, "creatures" : [ [ "naga" ] ], "guards" : true },
"demonGate" : { "index" : 37, "creatures" : [ [ "demon" ] ] },
"ogreFort" : { "index" : 38, "creatures" : [ [ "ogre" ] ] },
"orcTower" : { "index" : 39, "creatures" : [ [ "orc" ] ] },
"hellHole" : { "index" : 40, "creatures" : [ [ "pitFiend" ] ], "guards" : true },
"dragonCave" : { "index" : 41, "creatures" : [ [ "redDragon" ] ], "guards" : true },
"cliffNest" : { "index" : 42, "creatures" : [ [ "roc" ] ], "guards" : true },
"workshop" : { "index" : 43, "creatures" : [ [ "gremlin" ] ] },
"cloudTemple" : { "index" : 44, "creatures" : [ [ "giant" ] ], "guards" : true },
"dendroidArches" : { "index" : 45, "creatures" : [ [ "dendroidGuard" ] ], "guards" : true },
"warren" : { "index" : 46, "creatures" : [ [ "troglodyte" ] ] },
"waterConflux" : { "index" : 47, "creatures" : [ [ "waterElemental" ] ] },
"tombOfSouls" : { "index" : 48, "creatures" : [ [ "wight" ] ] },
"wyvernNest" : { "index" : 49, "creatures" : [ [ "wyvern" ] ], "guards" : true },
"enchantedSpring" : { "index" : 50, "creatures" : [ [ "pegasus" ] ] },
"unicornGladeBig" : { "index" : 51, "creatures" : [ [ "unicorn" ] ], "guards" : true },
"mausoleum" : { "index" : 52, "creatures" : [ [ "lich" ] ], "guards" : true },
"estate" : { "index" : 53, "creatures" : [ [ "vampire" ] ] },
"cursedTemple" : { "index" : 54, "creatures" : [ [ "skeleton" ] ] },
"graveyard" : { "index" : 55, "creatures" : [ [ "walkingDead" ] ] },
"guardhouse" : { "index" : 56, "creatures" : [ [ "pikeman" ] ] },
"archersTower" : { "index" : 57, "creatures" : [ [ "archer" ] ] },
"barracks" : { "index" : 58, "creatures" : [ [ "swordsman" ] ] },
"magicLantern" : { "index" : 59, "creatures" : [ [ "pixie" ] ] },
"altarOfThought" : { "index" : 60, "creatures" : [ [ "psychicElemental" ] ], "guards" : true },
"pyre" : { "index" : 61, "creatures" : [ [ "firebird" ] ], "guards" : true },
"frozenCliffs" : { "index" : 62, "creatures" : [ [ "azureDragon" ] ], "guards" : true },
"crystalCavern" : { "index" : 63, "creatures" : [ [ "crystalDragon" ] ], "guards" : true },
"magicForest" : { "index" : 64, "creatures" : [ [ "fairieDragon" ] ], "guards" : true },
"sulfurousLair" : { "index" : 65, "creatures" : [ [ "rustDragon" ] ], "guards" : true },
"enchantersHollow" : { "index" : 66, "creatures" : [ [ "enchanter" ] ], "guards" : true },
"treetopTower" : { "index" : 67, "creatures" : [ [ "sharpshooter" ] ], "guards" : true },
"unicornGlade" : { "index" : 68, "creatures" : [ [ "unicorn" ] ], "guards" : true },
"altarOfAir" : { "index" : 69, "creatures" : [ [ "airElemental" ] ] },
"altarOfEarth" : { "index" : 70, "creatures" : [ [ "earthElemental" ] ], "guards" : true },
"altarOfFire" : { "index" : 71, "creatures" : [ [ "fireElemental" ] ] },
"altarOfWater" : { "index" : 72, "creatures" : [ [ "waterElemental" ] ] },
"thatchedHut" : { "index" : 73, "creatures" : [ [ "halfling" ] ] },
"hovel" : { "index" : 74, "creatures" : [ [ "peasant" ] ] },
"boarGlen" : { "index" : 75, "creatures" : [ [ "boar" ] ] },
"tombOfCurses" : { "index" : 76, "creatures" : [ [ "mummy" ] ] },
"nomadTent" : { "index" : 77, "creatures" : [ [ "nomad" ] ] },
"rogueCavern" : { "index" : 78, "creatures" : [ [ "rogue" ] ] },
"trollBridge" : { "index" : 79, "creatures" : [ [ "troll" ] ], "guards" : true }
}
},
// subtype: unique special dwellings - golem factory and elemental conflux
"creatureGeneratorSpecial" : {
"index" :20,
"handler": "dwelling",
"types" : {
"elementalConflux" : {
"index" : 0,
"creatures" : [ // 4 separate "levels" to give them separate growth
[ "airElemental" ],
[ "waterElemental" ],
[ "fireElemental" ],
[ "earthElemental" ]
],
"guards" : {
"earthElemental" : 12
}
},
"golemFactory" : {
"index" : 1,
"creatures" : [ // 4 separate "levels" to give them separate growth
[ "ironGolem" ],
[ "stoneGolem" ],
[ "goldGolem" ],
[ "diamondGolem" ]
],
"guards" : {
"goldGolem" : 9,
"diamondGolem" : 6
}
}
}
},
}

View File

@ -48,6 +48,16 @@
"visitableFrom" : [ "+++", "+-+", "+++" ],
"mask" : [ "VA" ]
}
},
"types" : {
"wood" : { "index" : 0 },
"mercury" : { "index" : 1 },
"ore" : { "index" : 2 },
"sulfur" : { "index" : 3 },
"crystal" : { "index" : 4 },
"gems" : { "index" : 5 },
"gold" : { "index" : 6 },
"mithril" : { "index" : 7 } // TODO: move to WoG?
}
},
@ -56,7 +66,7 @@
"index" :98,
"handler": "town",
"base" : {
"filter" : {
"filters" : {
// village image - fort not present
"village" : [ "noneOf", [ "fort" ] ],
// fort image - fort is here but not capitol
@ -125,21 +135,6 @@
// subtype: faction ID
"randomDwellingFaction" : { "index" :218, "handler": "dwelling" },
// subtype: not well defined, describes various dwellings that can be placed as random
"creatureGeneratorCommon" : {
"index" :17,
"handler": "dwelling",
"base" : {
"base" : {
"visitableFrom" : [ "---", "+++", "+++" ],
"mask" : [ "VVV", "VBB", "VAA" ]
}
}
},
// subtype: unique special dwellings - golem factory, elemental conflux
"creatureGeneratorSpecial" : { "index" :20, "handler": "dwelling" },
// don't have subtypes (at least now), but closely connected to this objects
"spellScroll" : { "index" :93, "handler": "artifact" },
"heroPlaceholder" : { "index" :214, "handler": "heroPlaceholder" }

View File

@ -622,23 +622,28 @@ std::pair<Obj,int> CGameState::pickObject (CGObjectInstance *obj)
std::pair<Obj, int> result(Obj::NO_OBJ, -1);
CreatureID cid = VLC->townh->factions[faction]->town->creatures[level][0];
//golem factory is not in list of cregens but can be placed as random object
static const CreatureID factoryCreatures[] = {CreatureID::STONE_GOLEM, CreatureID::IRON_GOLEM,
CreatureID::GOLD_GOLEM, CreatureID::DIAMOND_GOLEM};
std::vector<CreatureID> factory(factoryCreatures, factoryCreatures + ARRAY_COUNT(factoryCreatures));
if (vstd::contains(factory, cid))
result = std::make_pair(Obj::CREATURE_GENERATOR4, 1);
//NOTE: this will pick last dwelling with this creature (Mantis #900)
//check for block map equality is better but more complex solution
for(auto &iter : VLC->objh->cregens)
if (iter.second == cid)
result = std::make_pair(Obj::CREATURE_GENERATOR1, iter.first);
auto testID = [&](Obj primaryID) -> void
{
auto dwellingIDs = VLC->objtypeh->knownSubObjects(primaryID);
for (si32 entry : dwellingIDs)
{
auto handler = dynamic_cast<const CDwellingInstanceConstructor*>(VLC->objtypeh->getHandlerFor(primaryID, entry).get());
if (handler->producesCreature(VLC->creh->creatures[cid]))
result = std::make_pair(primaryID, entry);
}
};
testID(Obj::CREATURE_GENERATOR1);
if (result.first == Obj::NO_OBJ)
testID(Obj::CREATURE_GENERATOR4);
if (result.first == Obj::NO_OBJ)
{
logGlobal->errorStream() << "Error: failed to find creature for dwelling of "<< int(faction) << " of level " << int(level);
result = std::make_pair(Obj::CREATURE_GENERATOR1, RandomGeneratorUtil::nextItem(VLC->objh->cregens, rand)->first);
logGlobal->errorStream() << "Error: failed to find dwelling for "<< VLC->townh->factions[faction]->name << " of level " << int(level);
result = std::make_pair(Obj::CREATURE_GENERATOR1, *RandomGeneratorUtil::nextItem(VLC->objtypeh->knownSubObjects(Obj::CREATURE_GENERATOR1), rand));
}
return result;

View File

@ -128,7 +128,7 @@ boost::optional<si32> CIdentifierStorage::getIdentifier(std::string scope, std::
if (idList.size() == 1)
return idList.front().id;
if (!silent)
logGlobal->errorStream() << "Failed to resolve identifier " << name << " from mod " << scope;
logGlobal->errorStream() << "Failed to resolve identifier " << name << " of type " << type << " from mod " << scope;
return boost::optional<si32>();
}
@ -141,7 +141,7 @@ boost::optional<si32> CIdentifierStorage::getIdentifier(std::string type, const
if (idList.size() == 1)
return idList.front().id;
if (!silent)
logGlobal->errorStream() << "Failed to resolve identifier " << name.String() << " from mod " << type;
logGlobal->errorStream() << "Failed to resolve identifier " << name.String() << " of type " << type << " from mod " << name.meta;
return boost::optional<si32>();
}
@ -155,7 +155,7 @@ boost::optional<si32> CIdentifierStorage::getIdentifier(const JsonNode & name, b
if (idList.size() == 1)
return idList.front().id;
if (!silent)
logGlobal->errorStream() << "Failed to resolve identifier " << name.String() << " from mod " << name.meta;
logGlobal->errorStream() << "Failed to resolve identifier " << name.String() << " of type " << pair2.first << " from mod " << name.meta;
return boost::optional<si32>();
}
@ -223,7 +223,9 @@ bool CIdentifierStorage::resolveIdentifier(const ObjectCallback & request)
}
if (request.optional && identifiers.empty()) // failed to resolve optinal ID
{
return true;
}
// error found. Try to generate some debug info
if (identifiers.size() == 0)
@ -244,16 +246,17 @@ void CIdentifierStorage::finalize()
{
bool errorsFound = false;
for(const ObjectCallback & request : scheduledRequests)
//Note: we may receive new requests during resolution phase -> end may change -> range for can't be used
for(auto it = scheduledRequests.begin(); it != scheduledRequests.end(); it++)
{
errorsFound |= !resolveIdentifier(request);
errorsFound |= !resolveIdentifier(*it);
}
if (errorsFound)
{
for(auto object : registeredObjects)
{
logGlobal->traceStream() << object.first << " -> " << object.second.id;
logGlobal->traceStream() << object.second.scope << " : " << object.first << " -> " << object.second.id;
}
logGlobal->errorStream() << "All known identifiers were dumped into log file";
}

View File

@ -554,10 +554,6 @@ void CTownHandler::loadClientData(CTown &town, const JsonNode & source)
info.tavernVideo = "TAVERN.BIK";
//end of legacy assignment
info.advMapVillage = source["adventureMap"]["village"].String();
info.advMapCastle = source["adventureMap"]["castle"].String();
info.advMapCapitol = source["adventureMap"]["capitol"].String();
loadTownHall(town, source["hallSlots"]);
loadStructures(town, source["structures"]);
loadSiegeScreen(town, source["siege"]);
@ -723,6 +719,8 @@ void CTownHandler::loadObject(std::string scope, std::string name, const JsonNod
auto object = loadFromJson(data, name);
object->index = factions.size();
factions.push_back(object);
if (object->town)
{
auto & info = object->town->clientInfo;
@ -730,9 +728,16 @@ void CTownHandler::loadObject(std::string scope, std::string name, const JsonNod
info.icons[0][1] = 8 + object->index * 4 + 1;
info.icons[1][0] = 8 + object->index * 4 + 2;
info.icons[1][1] = 8 + object->index * 4 + 3;
}
factions.push_back(object);
VLC->modh->identifiers.requestIdentifier(scope, "object", "town", [=](si32 index)
{
// register town once objects are loaded
JsonNode config = data["town"]["mapObject"];
config["faction"].String() = object->identifier;
config["faction"].meta = scope;
VLC->objtypeh->loadSubObject(object->identifier, config, index, object->index);
});
}
VLC->modh->identifiers.registerObject(scope, "faction", name, object->index);
}
@ -741,6 +746,9 @@ void CTownHandler::loadObject(std::string scope, std::string name, const JsonNod
{
auto object = loadFromJson(data, name);
object->index = index;
assert(factions[index] == nullptr); // ensure that this id was not loaded before
factions[index] = object;
if (object->town)
{
auto & info = object->town->clientInfo;
@ -748,10 +756,16 @@ void CTownHandler::loadObject(std::string scope, std::string name, const JsonNod
info.icons[0][1] = (GameConstants::F_NUMBER + object->index) * 2 + 1;
info.icons[1][0] = object->index * 2 + 0;
info.icons[1][1] = object->index * 2 + 1;
}
assert(factions[index] == nullptr); // ensure that this id was not loaded before
factions[index] = object;
VLC->modh->identifiers.requestIdentifier(scope, "object", "town", [=](si32 index)
{
// register town once objects are loaded
JsonNode config = data["town"]["mapObject"];
config["faction"].String() = object->identifier;
config["faction"].meta = scope;
VLC->objtypeh->loadSubObject(object->identifier, config, index, object->index);
});
}
VLC->modh->identifiers.registerObject(scope, "faction", name, object->index);
}
@ -761,31 +775,20 @@ void CTownHandler::afterLoadFinalization()
initializeRequirements();
for (CFaction * fact : factions)
{
// MODS COMPATIBILITY FOR 0.96
if (fact->town)
{
VLC->objtypeh->loadSubObject(fact->identifier, JsonNode(), Obj::TOWN, fact->index);
if (!fact->town->clientInfo.advMapCastle.empty())
{
JsonNode templ;
templ["animation"].String() = fact->town->clientInfo.advMapCastle;
VLC->objtypeh->getHandlerFor(Obj::TOWN, fact->index)->addTemplate(templ);
}
assert(fact->town->dwellings.size() == fact->town->dwellingNames.size());
for (size_t i=0; i<fact->town->dwellings.size(); i++)
{
//both unupgraded and upgraded get same dwelling
for (auto cre : fact->town->creatures[i])
{
if (VLC->objh->cregens.count(cre) == 0)
{
JsonNode templ;
templ["animation"].String() = fact->town->dwellings[i];
JsonNode templ;
templ["animation"].String() = fact->town->dwellings[i];
VLC->objtypeh->loadSubObject("", JsonNode(), Obj::CREATURE_GENERATOR1, 80 + cre);
VLC->objtypeh->getHandlerFor(Obj::CREATURE_GENERATOR1, 80 + cre)->addTemplate(templ);
VLC->objh->cregens[80 + cre] = cre; //map of dwelling -> creature id
}
VLC->objtypeh->loadSubObject("", JsonNode(), Obj::CREATURE_GENERATOR1, 100 + cre);
VLC->objtypeh->getHandlerFor(Obj::CREATURE_GENERATOR1, 100 + cre)->addTemplate(templ);
}
}
}

View File

@ -190,10 +190,6 @@ public:
/// NOTE: index in vector is meaningless. Vector used instead of list for a bit faster access
std::vector<ConstTransitivePtr<CStructure> > structures;
std::string advMapVillage;
std::string advMapCastle;
std::string advMapCapitol;
std::string siegePrefix;
std::vector<Point> siegePositions;
CreatureID siegeShooter; // shooter creature ID
@ -201,7 +197,7 @@ public:
template <typename Handler> void serialize(Handler &h, const int version)
{
h & icons & iconSmall & iconLarge & tavernVideo & musicTheme & townBackground & guildBackground & guildWindow & buildingsIcons & hallBackground;
h & advMapVillage & advMapCastle & advMapCapitol & hallSlots & structures;
h & hallSlots & structures;
h & siegePrefix & siegePositions & siegeShooter;
}
} clientInfo;

View File

@ -737,7 +737,7 @@ void JsonUtils::mergeCopy(JsonNode & dest, JsonNode source)
void JsonUtils::inherit(JsonNode & descendant, const JsonNode & base)
{
JsonNode inheritedNode(base);
JsonNode inheritedNode(base);
merge(inheritedNode,descendant);
descendant.swap(inheritedNode);
}

View File

@ -45,11 +45,11 @@ DLL_LINKAGE void preinitDLL(CConsoleHandler *Console)
DLL_LINKAGE void loadDLLClasses()
{
try
// try
{
VLC->init();
}
HANDLE_EXCEPTION;
// HANDLE_EXCEPTION;
}
const IBonusTypeHandler * LibClasses::getBth() const

View File

@ -13,6 +13,7 @@
#include "../NetPacks.h"
#include "../CGeneralTextHandler.h"
#include "../mapObjects/CObjectClassesHandler.h"
using namespace boost::assign;
@ -24,54 +25,18 @@ void CGDwelling::initObj()
switch(ID)
{
case Obj::CREATURE_GENERATOR1:
case Obj::CREATURE_GENERATOR4:
{
CreatureID crid = VLC->objh->cregens[subID];
const CCreature *crs = VLC->creh->creatures[crid];
VLC->objtypeh->getHandlerFor(ID, subID)->configureObject(this, cb->gameState()->getRandomGenerator());
creatures.resize(1);
creatures[0].second.push_back(crid);
if (subID >= VLC->generaltexth->creGens.size()) //very messy workaround
{
auto & dwellingNames = VLC->townh->factions[crs->faction]->town->dwellingNames;
assert (dwellingNames.size() > crs->level - 1);
hoverName = dwellingNames[crs->level - 1];
}
else
hoverName = VLC->generaltexth->creGens[subID];
if(crs->level > 4)
putStack(SlotID(0), new CStackInstance(crs, (crs->growth) * 3));
if (getOwner() != PlayerColor::NEUTRAL)
cb->gameState()->players[getOwner()].dwellings.push_back (this);
}
break;
//putStack(SlotID(0), new CStackInstance(CreatureID::GOLD_GOLEM, 9));
//putStack(SlotID(1), new CStackInstance(CreatureID::DIAMOND_GOLEM, 6));
case Obj::CREATURE_GENERATOR4:
creatures.resize(4);
if(subID == 1) //Golem Factory
{
creatures[0].second.push_back(CreatureID::STONE_GOLEM);
creatures[1].second.push_back(CreatureID::IRON_GOLEM);
creatures[2].second.push_back(CreatureID::GOLD_GOLEM);
creatures[3].second.push_back(CreatureID::DIAMOND_GOLEM);
//guards
putStack(SlotID(0), new CStackInstance(CreatureID::GOLD_GOLEM, 9));
putStack(SlotID(1), new CStackInstance(CreatureID::DIAMOND_GOLEM, 6));
}
else if(subID == 0) // Elemental Conflux
{
creatures[0].second.push_back(CreatureID::AIR_ELEMENTAL);
creatures[1].second.push_back(CreatureID::FIRE_ELEMENTAL);
creatures[2].second.push_back(CreatureID::EARTH_ELEMENTAL);
creatures[3].second.push_back(CreatureID::WATER_ELEMENTAL);
//guards
putStack(SlotID(0), new CStackInstance(CreatureID::EARTH_ELEMENTAL, 12));
}
else
{
assert(0);
}
hoverName = VLC->generaltexth->creGens4[subID];
break;
//putStack(SlotID(0), new CStackInstance(CreatureID::EARTH_ELEMENTAL, 12));
break;
case Obj::REFUGEE_CAMP:
//is handled within newturn func
@ -811,12 +776,10 @@ void CGTownInstance::setType(si32 ID, si32 subID)
void CGTownInstance::updateAppearance()
{
if (!hasFort())
appearance.animationFile = town->clientInfo.advMapVillage;
else if(hasCapitol())
appearance.animationFile = town->clientInfo.advMapCapitol;
else
appearance.animationFile = town->clientInfo.advMapCastle;
//FIXME: not the best way to do this
auto app = VLC->objtypeh->getHandlerFor(ID, subID)->getOverride(cb->gameState()->getTile(visitablePos())->terType, this);
if (app)
appearance = app.get();
}
std::string CGTownInstance::nodeName() const

View File

@ -153,6 +153,7 @@ void CObjectClassesHandler::loadObjectEntry(const JsonNode & entry, ObjectContai
}
obj->objects[id] = handler;
logGlobal->debugStream() << "Loaded object " << obj->id << ":" << id;
}
CObjectClassesHandler::ObjectContainter * CObjectClassesHandler::loadFromJson(const JsonNode & json)
@ -198,8 +199,9 @@ void CObjectClassesHandler::loadSubObject(std::string name, JsonNode config, si3
config["index"].Float() = subID.get();
}
std::string oldMeta = config.meta; // FIXME: move into inheritNode?
JsonUtils::inherit(config, objects.at(ID)->base);
logGlobal->errorStream() << "JSON: " << config;
config.setMeta(oldMeta);
loadObjectEntry(config, objects[ID]);
}
@ -339,9 +341,6 @@ void AObjectTypeHandler::addTemplate(ObjectTemplate templ)
void AObjectTypeHandler::addTemplate(JsonNode config)
{
logGlobal->errorStream() << "INPUT FOR: " << type << ":" << subtype << " " << config;
logGlobal->errorStream() << "BASE FOR: " << type << ":" << subtype << " " << base;
config.setType(JsonNode::DATA_STRUCT); // ensure that input is not null
JsonUtils::inherit(config, base);
ObjectTemplate tmpl;
@ -349,7 +348,6 @@ void AObjectTypeHandler::addTemplate(JsonNode config)
tmpl.subid = subtype;
tmpl.stringID = ""; // TODO?
tmpl.readJson(config);
logGlobal->errorStream() << "DATA FOR: " << type << ":" << subtype << " " << config;
addTemplate(tmpl);
}

View File

@ -68,7 +68,7 @@ public:
class CGObjectInstance;
class AObjectTypeHandler
class AObjectTypeHandler : public boost::noncopyable
{
RandomMapInfo rmgInfo;

View File

@ -157,15 +157,6 @@ static void readBankLevel(const JsonNode &level, BankConfig &bc)
CObjectHandler::CObjectHandler()
{
logGlobal->traceStream() << "\t\tReading cregens ";
const JsonNode config(ResourceID("config/dwellings.json"));
for(const JsonNode &dwelling : config["dwellings"].Vector())
{
cregens[dwelling["dwelling"].Float()] = CreatureID((si32)dwelling["creature"].Float());
}
logGlobal->traceStream() << "\t\tDone loading cregens!";
logGlobal->traceStream() << "\t\tReading resources prices ";
const JsonNode config2(ResourceID("config/resources.json"));
for(const JsonNode &price : config2["resources_prices"].Vector())
@ -342,10 +333,10 @@ void CGObjectInstance::setType(si32 ID, si32 subID)
this->ID = Obj(ID);
this->subID = subID;
this->appearance = VLC->objtypeh->getHandlerFor(ID, subID)->getTemplates(tile.terType).front();
//recalculate blockvis tiles - new appearance might have different blockmap than before
cb->gameState()->map->removeBlockVisTiles(this, true);
this->appearance = VLC->objtypeh->getHandlerFor(ID, subID)->getTemplates(tile.terType).at(0);
cb->gameState()->map->addBlockVisTiles(this);
}

View File

@ -187,7 +187,6 @@ struct BankConfig
class DLL_LINKAGE CObjectHandler
{
public:
std::map<si32, CreatureID> cregens; //type 17. dwelling subid -> creature ID
std::map <ui32, std::vector < ConstTransitivePtr<BankConfig> > > banksInfo; //[index][preset]
std::map <ui32, std::string> creBanksNames; //[crebank index] -> name of this creature bank
std::vector<ui32> resVals; //default values of resources in gold
@ -199,6 +198,6 @@ public:
template <typename Handler> void serialize(Handler &h, const int version)
{
h & cregens & banksInfo & creBanksNames & resVals;
h & banksInfo & creBanksNames & resVals;
}
};

View File

@ -26,23 +26,27 @@ bool CObstacleConstructor::isStaticObject()
return true;
}
CTownInstanceConstructor::CTownInstanceConstructor()
CTownInstanceConstructor::CTownInstanceConstructor():
faction(nullptr)
{
}
void CTownInstanceConstructor::initTypeData(const JsonNode & input)
{
VLC->modh->identifiers.requestIdentifier("faction", input["faction"],
[&](si32 index) { faction = VLC->townh->factions[index]; });
VLC->modh->identifiers.requestIdentifier("faction", input["faction"], [&](si32 index)
{
faction = VLC->townh->factions[index];
});
filtersJson = input["filters"];
}
void CTownInstanceConstructor::afterLoadFinalization()
{
assert(faction);
for (auto entry : filtersJson.Struct())
{
filters[entry.first] = LogicalExpression<BuildingID>(entry.second, [&](const JsonNode & node)
filters[entry.first] = LogicalExpression<BuildingID>(entry.second, [this](const JsonNode & node)
{
return BuildingID(VLC->modh->identifiers.getIdentifier("building." + faction->identifier, node.Vector()[0]).get());
});
@ -121,12 +125,13 @@ void CDwellingInstanceConstructor::initTypeData(const JsonNode & input)
availableCreatures[i].resize(creatures.size());
for (size_t j=0; j<creatures.size(); j++)
{
VLC->modh->identifiers.requestIdentifier("creature", creatures[j], [&] (si32 index)
VLC->modh->identifiers.requestIdentifier("creature", creatures[j], [=] (si32 index)
{
availableCreatures[i][j] = VLC->creh->creatures[index];
});
}
}
guards = input["guards"];
}
bool CDwellingInstanceConstructor::objectFilter(const CGObjectInstance *, const ObjectTemplate &) const
@ -137,17 +142,69 @@ bool CDwellingInstanceConstructor::objectFilter(const CGObjectInstance *, const
CGObjectInstance * CDwellingInstanceConstructor::create(ObjectTemplate tmpl) const
{
CGDwelling * obj = createTyped(tmpl);
for (auto entry : availableCreatures)
{
obj->creatures.resize(obj->creatures.size()+1);
obj->creatures.resize(availableCreatures.size());
for (auto & entry : availableCreatures)
{
for (const CCreature * cre : entry)
obj->creatures.back().second.push_back(cre->idNumber);
}
return obj;
}
void CDwellingInstanceConstructor::configureObject(CGObjectInstance * object, CRandomGenerator & rng) const
namespace
{
si32 loadValue(const JsonNode & value, CRandomGenerator & rng, si32 defaultValue = 0)
{
if (value.isNull())
return defaultValue;
if (value.getType() == JsonNode::DATA_FLOAT)
return value.Float();
si32 min = value["min"].Float();
si32 max = value["max"].Float();
return rng.getIntRange(min, max)();
}
std::vector<CStackBasicDescriptor> loadCreatures(const JsonNode & value, CRandomGenerator & rng)
{
std::vector<CStackBasicDescriptor> ret;
for (auto & pair : value.Struct())
{
CStackBasicDescriptor stack;
stack.type = VLC->creh->creatures[VLC->modh->identifiers.getIdentifier(pair.second.meta, "creature", pair.first).get()];
stack.count = loadValue(pair.second, rng);
ret.push_back(stack);
}
return ret;
}
}
void CDwellingInstanceConstructor::configureObject(CGObjectInstance * object, CRandomGenerator &rng) const
{
CGDwelling * dwelling = dynamic_cast<CGDwelling*>(object);
dwelling->creatures.clear();
dwelling->creatures.resize(availableCreatures.size());
for (auto & entry : availableCreatures)
{
for (const CCreature * cre : entry)
dwelling->creatures.back().second.push_back(cre->idNumber);
}
for (auto & stack : loadCreatures(guards, rng))
{
dwelling->putStack(SlotID(dwelling->stacksCount()), new CStackInstance(stack.type->idNumber, stack.count));
}
}
bool CDwellingInstanceConstructor::producesCreature(const CCreature * crea) const
{
for (auto & entry : availableCreatures)
{
for (const CCreature * cre : entry)
if (crea == cre)
return true;
}
return false;
}

View File

@ -91,14 +91,19 @@ public:
class CDwellingInstanceConstructor : public CDefaultObjectTypeHandler<CGDwelling>
{
std::vector<std::vector<const CCreature *>> availableCreatures;
JsonNode guards;
protected:
bool objectFilter(const CGObjectInstance *, const ObjectTemplate &) const;
public:
std::vector<std::vector<CCreature *>> availableCreatures;
CDwellingInstanceConstructor();
CGObjectInstance * create(ObjectTemplate tmpl) const;
void initTypeData(const JsonNode & input);
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const;
bool producesCreature(const CCreature * crea) const;
};