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

first part of town configuration:

- moved almost all loading to TownHandler
- CBuildings and CStructures are now part of CTown
- merged hall.json into buildings.json

Should not cause any crashes or glitches
This commit is contained in:
Ivan Savenko 2012-09-02 10:33:41 +00:00
parent 3e346e737a
commit 44cc848edc
23 changed files with 816 additions and 786 deletions

View File

@ -1267,7 +1267,7 @@ bool VCAI::tryBuildStructure(const CGTownInstance * t, int building, unsigned in
BOOST_FOREACH(int buildID, toBuild)
{
const CBuilding *b = VLC->buildh->buildings[t->subID][buildID];
const CBuilding *b = t->town->buildings[buildID];
int canBuild = cb->canBuildStructure(t, buildID);
if(canBuild == EBuildingState::ALLOWED)
@ -1282,7 +1282,7 @@ bool VCAI::tryBuildStructure(const CGTownInstance * t, int building, unsigned in
}
else if(canBuild == EBuildingState::NO_RESOURCES)
{
TResources cost = VLC->buildh->buildings[t->subID][buildID]->resources;
TResources cost = t->town->buildings[buildID]->resources;
for (int i = 0; i < GameConstants::RESOURCE_QUANTITY; i++)
{
int diff = currentRes[i] - cost[i] + income[i];

View File

@ -49,7 +49,7 @@ int hordeToDwellingID(int bid)//helper, converts horde buiding ID into correspon
}
}
CBuildingRect::CBuildingRect(CCastleBuildings * Par, const CGTownInstance *Town, const Structure *Str)
CBuildingRect::CBuildingRect(CCastleBuildings * Par, const CGTownInstance *Town, const CStructure *Str)
:CShowableAnim(0, 0, Str->defName, CShowableAnim::BASE | CShowableAnim::USE_RLE),
parent(Par),
town(Town),
@ -120,7 +120,7 @@ void CBuildingRect::clickRight(tribool down, bool previousState)
if( !CSDL_Ext::isTransparent(area, GH.current->motion.x-pos.x, GH.current->motion.y-pos.y) ) //inside building image
{
int bid = hordeToDwellingID(str->ID);
const CBuilding *bld = CGI->buildh->buildings[str->townID].find(bid)->second;
const CBuilding *bld = town->town->buildings[bid];
if (bid < EBuilding::DWELL_FIRST)
{
std::vector<CComponent*> comps(1, new CComponent(CComponent::building, bld->tid, bld->bid));
@ -214,7 +214,7 @@ std::string getBuildingSubtitle(int tid, int bid)//hover text for building
bid = hordeToDwellingID(bid);
if (bid<30)//non-dwellings - only buiding name
return CGI->buildh->buildings[tid].find(bid)->second->Name();
return CGI->townh->towns[tid].buildings[bid]->Name();
else//dwellings - recruit %creature%
{
int creaID = t->creatures[(bid-30)%GameConstants::CREATURES_PER_TOWN].second.back();//taking last of available creatures
@ -445,7 +445,7 @@ public:
};
SORTHELP<CBuildingRect> buildSorter;
SORTHELP<Structure> structSorter;
SORTHELP<CStructure> structSorter;
CCastleBuildings::CCastleBuildings(const CGTownInstance* Town):
town(Town),
@ -459,10 +459,9 @@ CCastleBuildings::CCastleBuildings(const CGTownInstance* Town):
//Generate buildings list
for (std::set<si32>::const_iterator building=town->builtBuildings.begin(); building!=town->builtBuildings.end(); building++)
{
std::map<int, Structure*>::iterator structure;
structure = CGI->townh->structures[town->subID].find(*building);
auto structure = town->town->clientInfo.structures.find(*building);
if(structure != CGI->townh->structures[town->subID].end() && structure->second)
if(structure != town->town->clientInfo.structures.end() && structure->second)
{
if(structure->second->group<0) // no group - just add it
buildings.push_back(new CBuildingRect(this, town, structure->second));
@ -471,18 +470,18 @@ CCastleBuildings::CCastleBuildings(const CGTownInstance* Town):
}
}
Structure * shipyard = CGI->townh->structures[town->subID][6];
CStructure * shipyard = town->town->clientInfo.structures[6];
//ship in shipyard
if(shipyard && vstd::contains(groups, shipyard->group))
{
std::vector <const CGObjectInstance *> vobjs = LOCPLINT->cb->getVisitableObjs(town->bestLocation());
if(!vobjs.empty() && (vobjs.front()->ID == 8 || vobjs.front()->ID == GameConstants::HEROI_TYPE)) //there is visitable obj at shipyard output tile and it's a boat or hero (on boat)
{
groups[shipyard->group].push_back(CGI->townh->structures[town->subID][20]);
groups[shipyard->group].push_back(town->town->clientInfo.structures[20]);
}
}
//Create building for each group
for (std::map< int, std::vector<const Structure*> >::iterator group = groups.begin(); group != groups.end(); group++)
for (std::map< int, std::vector<const CStructure*> >::iterator group = groups.begin(); group != groups.end(); group++)
{
std::sort(group->second.begin(), group->second.end(), structSorter);
buildings.push_back(new CBuildingRect(this, town, group->second.back()));
@ -521,10 +520,10 @@ void CCastleBuildings::checkRules()
int buildingID = animRule[i].buildID;
//check if this building have been upgraded (Ship is upgrade of Shipyard)
int groupID = CGI->townh->structures[town->subID][animRule[i].buildID]->group;
int groupID = town->town->clientInfo.structures[animRule[i].buildID]->group;
if (groupID != -1)
{
std::map< int, std::vector<const Structure*> >::const_iterator git= groups.find(groupID);
std::map< int, std::vector<const CStructure*> >::const_iterator git= groups.find(groupID);
if ( git == groups.end() || git->second.empty() )
continue;
buildingID = git->second.back()->ID;
@ -548,10 +547,9 @@ void CCastleBuildings::checkRules()
void CCastleBuildings::addBuilding(int building)
{
OBJ_CONSTRUCTION_CAPTURING_ALL;
std::map<int, Structure*>::const_iterator structure;
structure = CGI->townh->structures[town->subID].find(building);
auto structure = town->town->clientInfo.structures.find(building);
if(structure != CGI->townh->structures[town->subID].end()) //we have info about that structure
if(structure != town->town->clientInfo.structures.end()) //we have info about that structure
{
if(structure->second->group<0) //no group - just add it
{
@ -586,10 +584,9 @@ void CCastleBuildings::addBuilding(int building)
void CCastleBuildings::removeBuilding(int building)
{
OBJ_CONSTRUCTION_CAPTURING_ALL;
std::map<int, Structure*>::const_iterator structure;
structure = CGI->townh->structures[town->subID].find(building);
auto structure = town->town->clientInfo.structures.find(building);
if(structure != CGI->townh->structures[town->subID].end()) //we have info about that structure
if(structure != town->town->clientInfo.structures.end()) //we have info about that structure
{
if(structure->second->group<0) //no group - just add it
{
@ -642,7 +639,7 @@ void CCastleBuildings::buildingClicked(int building)
{
tlog5<<"You've clicked on "<<building<<std::endl;
building = hordeToDwellingID(building);
const CBuilding *b = CGI->buildh->buildings[town->subID].find(building)->second;
const CBuilding *b = town->town->buildings.find(building)->second;
if(building >= EBuilding::DWELL_FIRST)
{
@ -784,7 +781,7 @@ void CCastleBuildings::enterBlacksmith(int ArtifactID)
const CGHeroInstance *hero = town->visitingHero;
if(!hero)
{
LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[273]) % CGI->buildh->buildings[town->subID].find(16)->second->Name()));
LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[273]) % town->town->buildings.find(16)->second->Name()));
return;
}
int price = CGI->arth->artifacts[ArtifactID]->price;
@ -797,7 +794,7 @@ void CCastleBuildings::enterBuilding(int building)
std::vector<CComponent*> comps(1, new CComponent(CComponent::building, town->subID, building));
LOCPLINT->showInfoDialog(
CGI->buildh->buildings[town->subID].find(building)->second->Description(),comps);
town->town->buildings.find(building)->second->Description(),comps);
}
void CCastleBuildings::enterCastleGate()
@ -833,9 +830,9 @@ void CCastleBuildings::enterFountain(int building)
{
std::vector<CComponent*> comps(1, new CComponent(CComponent::building,town->subID,building));
std::string descr = CGI->buildh->buildings[town->subID].find(building)->second->Description();
std::string descr = town->town->buildings.find(building)->second->Description();
if ( building == 21)//we need description for mystic pond as well
descr += "\n\n"+CGI->buildh->buildings[town->subID].find(17)->second->Description();
descr += "\n\n"+town->town->buildings.find(17)->second->Description();
if (town->bonusValue.first == 0)//fountain was builded this week
descr += "\n\n"+ CGI->generaltexth->allTexts[677];
else//fountain produced something;
@ -1182,7 +1179,7 @@ CTownInfo::CTownInfo(int posX, int posY, const CGTownInstance* Town, bool townHa
return;
picture = new CAnimImage("ITMCL.DEF", town->fortLevel()-1);
}
building = CGI->buildh->buildings[town->subID][buildID];
building = town->town->buildings[buildID];
pos = picture->pos;
}
@ -1330,7 +1327,7 @@ CHallInterface::CBuildingBox::CBuildingBox(int x, int y, const CGTownInstance *
}
CHallInterface::CHallInterface(const CGTownInstance *Town):
CWindowObject(PLAYER_COLORED | BORDERED, CGI->buildh->hall[Town->subID].first),
CWindowObject(PLAYER_COLORED | BORDERED, Town->town->clientInfo.hallBackground),
town(Town)
{
OBJ_CONSTRUCTION_CAPTURING_ALL;
@ -1341,12 +1338,12 @@ CHallInterface::CHallInterface(const CGTownInstance *Town):
Rect barRect(5, 556, 740, 18);
statusBar = new CGStatusBar(new CPicture(*background, barRect, 5, 556, false));
title = new CLabel(399, 12, FONT_MEDIUM, CENTER, Colors::Cornsilk, CGI->buildh->buildings[town->subID][town->hallLevel()+EBuilding::VILLAGE_HALL]->Name());
title = new CLabel(399, 12, FONT_MEDIUM, CENTER, Colors::Cornsilk, town->town->buildings[town->hallLevel()+EBuilding::VILLAGE_HALL]->Name());
exit = new CAdventureMapButton(CGI->generaltexth->hcommands[8], "",
boost::bind(&CHallInterface::close,this), 748, 556, "TPMAGE1.DEF", SDLK_RETURN);
exit->assignedKeys.insert(SDLK_ESCAPE);
const std::vector< std::vector< std::vector<int> > > &boxList = CGI->buildh->hall[town->subID].second;
auto & boxList = town->town->clientInfo.hallSlots;
boxes.resize(boxList.size());
for(size_t row=0; row<boxList.size(); row++) //for each row
{
@ -1356,7 +1353,7 @@ CHallInterface::CHallInterface(const CGTownInstance *Town):
for(size_t item=0; item<boxList[row][col].size(); item++)//we are looking for the first not build structure
{
int buildingID = boxList[row][col][item];
building = CGI->buildh->buildings[town->subID][buildingID];
building = town->town->buildings[buildingID];
if (buildingID == 18 || buildingID == 24)
{
@ -1407,7 +1404,7 @@ std::string CBuildWindow::getTextForState(int state)
{
if (vstd::contains(town->builtBuildings, *i))
continue;//skipping constructed buildings
ret+= CGI->buildh->buildings[town->subID][*i]->Name() + ", ";
ret+= town->town->buildings[*i]->Name() + ", ";
}
ret.erase(ret.size()-2);
}
@ -1479,7 +1476,7 @@ CFortScreen::CFortScreen(const CGTownInstance * town):
if (fortSize > GameConstants::CREATURES_PER_TOWN && town->creatures.back().second.empty())
fortSize--;
const CBuilding *fortBuilding = CGI->buildh->buildings[town->subID][town->fortLevel()+6];
const CBuilding *fortBuilding = town->town->buildings[town->fortLevel()+6];
title = new CLabel(400, 12, FONT_BIG, CENTER, Colors::Cornsilk, fortBuilding->Name());
std::string text = boost::str(boost::format(CGI->generaltexth->fcommands[6]) % fortBuilding->Name());
@ -1610,7 +1607,7 @@ CFortScreen::RecruitArea::RecruitArea(int posX, int posY, const CGTownInstance *
values.push_back(new LabeledValue(sizes, CGI->generaltexth->allTexts[194], CGI->generaltexth->fcommands[5], town->creatureGrowth(level)));
creatureName = new CLabel(78, 11, FONT_SMALL, CENTER, Colors::Cornsilk, creature->namePl);
dwellingName = new CLabel(78, 101, FONT_SMALL, CENTER, Colors::Cornsilk, CGI->buildh->buildings[town->subID][buildingID]->Name());
dwellingName = new CLabel(78, 101, FONT_SMALL, CENTER, Colors::Cornsilk, town->town->buildings[buildingID]->Name());
if (vstd::contains(town->builtBuildings, buildingID))
{

View File

@ -17,7 +17,7 @@ class CResDataBar;
class CSpell;
class CTextBox;
class CTownList;
struct Structure;
struct CStructure;
class CGHeroInstance;
class CGarrisonInt;
class CCreature;
@ -39,13 +39,13 @@ class CBuildingRect : public CShowableAnim
public:
CCastleBuildings * parent;
const CGTownInstance * town;
const Structure* str;
const CStructure* str;
SDL_Surface* border;
SDL_Surface* area;
ui32 stateCounter;//For building construction - current stage in animation
CBuildingRect(CCastleBuildings * Par, const CGTownInstance *Town, const Structure *Str); //c-tor
CBuildingRect(CCastleBuildings * Par, const CGTownInstance *Town, const CStructure *Str); //c-tor
~CBuildingRect(); //d-tor
bool operator<(const CBuildingRect & p2) const;
void hover(bool on);
@ -115,7 +115,7 @@ class CCastleBuildings : public CIntObject
{
CPicture *background;
//List of buildings for each group
std::map< int, std::vector<const Structure*> > groups;
std::map< int, std::vector<const CStructure*> > groups;
//Vector with all blittable buildings
std::vector<CBuildingRect*> buildings;

View File

@ -32,5 +32,4 @@ void CGameInfo::setFromLib()
objh = VLC->objh;
spellh = VLC->spellh;
dobjinfo = VLC->dobjinfo;
buildh = VLC->buildh;
}

View File

@ -61,7 +61,6 @@ public:
ConstTransitivePtr<CDefObjInfoHandler> dobjinfo;
CGeneralTextHandler * generaltexth;
CMapHandler * mh;
ConstTransitivePtr<CBuildingHandler> buildh;
CTownHandler * townh;
//CTownHandler * townh;

View File

@ -3067,9 +3067,8 @@ void CBonusSelection::updateBonusSelection()
picName = graphics->ERMUtoPicture[faction][buildID];
picNumber = -1;
tlog1<<CGI->buildh->buildings.size()<<"\t"<<faction<<"\t"<<CGI->buildh->buildings[faction].size()<<"\t"<<buildID<<"\n";
if (vstd::contains(CGI->buildh->buildings[faction], buildID))
desc = CGI->buildh->buildings[faction].find(buildID)->second->Description();
if (vstd::contains(CGI->townh->towns[faction].buildings, buildID))
desc = CGI->townh->towns[faction].buildings.find(buildID)->second->Description();
}
break;
case 3: //artifact

View File

@ -904,7 +904,7 @@ std::string CComponent::getDescription()
case spell: return CGI->spellh->spells[subtype]->descriptions[val];
case morale: return CGI->generaltexth->heroscrn[ 4 - (val>0) + (val<0)];
case luck: return CGI->generaltexth->heroscrn[ 7 - (val>0) + (val<0)];
case building: return CGI->buildh->buildings[subtype][val]->Description();
case building: return CGI->townh->towns[subtype].buildings[val]->Description();
case hero: return CGI->heroh->heroes[subtype]->name;
case flag: return "";
}
@ -936,7 +936,7 @@ std::string CComponent::getSubtitleInternal()
case spell: return CGI->spellh->spells[subtype]->name;
case morale: return "";
case luck: return "";
case building: return CGI->buildh->buildings[subtype][val]->Name();
case building: return CGI->townh->towns[subtype].buildings[val]->Name();
case hero: return CGI->heroh->heroes[subtype]->name;
case flag: return CGI->generaltexth->capColors[subtype];
}
@ -2437,9 +2437,9 @@ CMarketplaceWindow::CMarketplaceWindow(const IMarket *Market, const CGHeroInstan
{
switch (mode)
{
break; case EMarketMode::CREATURE_RESOURCE: title = CGI->buildh->buildings[6][21]->Name();
break; case EMarketMode::RESOURCE_ARTIFACT: title = CGI->buildh->buildings[market->o->subID][17]->Name();
break; case EMarketMode::ARTIFACT_RESOURCE: title = CGI->buildh->buildings[market->o->subID][17]->Name();
break; case EMarketMode::CREATURE_RESOURCE: title = CGI->townh->towns[6].buildings[21]->Name();
break; case EMarketMode::RESOURCE_ARTIFACT: title = CGI->townh->towns[market->o->subID].buildings[17]->Name();
break; case EMarketMode::ARTIFACT_RESOURCE: title = CGI->townh->towns[market->o->subID].buildings[17]->Name();
break; default: title = CGI->generaltexth->allTexts[158];
}
}

View File

@ -1,95 +1,9 @@
// Town properties, ordered by city type (0 to 8)
// defnames: Buildings coordinates inside a city
// blit_order: Buildings not mentioned in the file will be blitted first.
// Then buildings in the list will be drawn in that order.
// creatures_basic: ids of the basic creatures in each dwelling, ordered by level. 8th is WoG and is ignored.
// creatures_upgraded: ids of the upgraded creatures in each dwelling, ordered by level
// horde: horde building creature levels (-1 if not present)
// mage_guild: maximum level of the mage guild
// primary_resource: (1,3,4,5 for rares and 127 for wood+ore)
// war_machine: type of war machine that this city can build
{
"schema" :
{
"town_type" :
{
"type" : "array",
"items" :
{
"type" : "object",
"properties" :
{
"blit_order" : { "type" : "array", "items" : {"type":"number"}, "default" :[] },
"creatures" : { "type" : "array", "items" : { "type" : "array", "items" : {"type":"number"} } },
"horde" : { "type" : "array", "items" : {"type":"number", "default" : -1} },
"primary_resource" : { "type" : "number", "default" : 127},
"mage_guild" : { "type" : "number", "default" : 5},
"war_machine" : { "type" : "number"},
"defnames" :
{
"type" : "array",
"items" :
{
"type" : "object",
"properties" :
{
"id" : { "type" : "number" },
"x" : { "type" : "number" },
"y" : { "type" : "number" },
"defname" : { "type" : "string" },
"border" : { "type" : "string", "default" : ""},
"area" : { "type" : "string", "default" : ""}
}
}
},
"building_requirements" :
{
"type" : "array",
"items" :
{
"type" : "object",
"properties" :
{
"id" :
{
"type" : "number"
},
"requires" :
{
"type" : "array",
"items" : {"type":"number"}
}
}
}
}
}
}
},
"town_groups" :
{
"type" : "array",
"items" :
{
"type" : "object",
"properties" :
{
"id" : { "type" : "number" },
"groups" :
{
"type" : "array",
"items" : { "type" : "array", "items" : {"type":"number"}, }
}
}
}
}
},
"town_type" :
"towns" :
[
{
// 0 - Castle
"defnames" :
"structures" :
[
{ "id" : 16, "defname" : "TBCSBLAK.def", "x" : 213, "y" : 251, "border" : "TOCSBLAK.bmp", "area" : "TZCSBLAK.bmp" },
{ "id" : 8, "defname" : "TBCSCAS2.def", "x" : 478, "y" : 66, "border" : "TOCSCAS2.bmp", "area" : "TZCSCAS2.bmp" },
@ -130,30 +44,63 @@
{ "id" : 43, "defname" : "TBCSUP_6.def", "x" : 303, "y" : 0, "border" : "TOCSANG2.bmp", "area" : "TZCSANG2.bmp" },
{ "id" : 20, "defname" : "TBCSBOAT.def", "x" : 478, "y" : 134, "border" : "TOCSDKMN.bmp", "area" : "TZCSDKMN.bmp" }
],
"groups" :
[
[ 0, 1, 2, 3, 4 ],
[ 6, 20 ],
[ 7, 8, 9 ],
[ 10, 11, 12, 13 ],
[ 30, 37 ],
[ 31, 38 ],
[ 32, 39, 18, 19 ],
[ 33, 40 ],
[ 34, 41 ],
[ 35, 42 ],
[ 36, 43 ]
],
"hallBackground": "TPTHBKCS.BMP",
"hallSlots":
[
[ [ 10, 11, 12, 13 ], [ 7, 8, 9 ], [ 5, 22 ], [ 16 ] ],
[ [ 14, 15 ], [ 0, 1, 2, 3 ], [ 6, 17 ] ],
[ [ 21 ], [ 18, 19 ] ],
[ [ 30, 37 ], [ 31, 38 ], [ 32, 39 ], [ 33, 40 ] ],
[ [ 34, 41 ], [ 35, 42 ], [ 36, 43 ] ]
],
"blit_order" : [ 0, 1, 2, 3, 10, 11, 12, 13, 5, 22, 30, 37, 16, 6, 20, 18, 19, 34, 41 ],
"creatures" : [ [0, 1], [2, 3], [4, 5], [6, 7], [8, 9], [10, 11], [12, 13] ],
"horde" : [ 2, null ],
"horde" : [ 2, -1 ],
"primary_resource" : 127,
"mage_guild" : 4,
"war_machine" : 4,
"building_requirements" :
"buildings" :
[
{ "id" : 0 },
{ "id" : 1, "requires" : [ 0 ] },
{ "id" : 2, "requires" : [ 1 ] },
{ "id" : 3, "requires" : [ 2 ] },
{ "id" : 4, "requires" : [ 3 ] },
{ "id" : 5 },
{ "id" : 6 },
{ "id" : 7 },
{ "id" : 8, "requires" : [ 7 ] },
{ "id" : 9, "requires" : [ 8 ] },
{ "id" : 10 },
{ "id" : 11, "requires" : [ 10, 5 ] },
{ "id" : 12, "requires" : [ 11, 0, 14, 16 ] },
{ "id" : 13, "requires" : [ 12, 9 ] },
{ "id" : 14 },
{ "id" : 15, "requires" : [ 14 ] },
{ "id" : 16 },
{ "id" : 17, "requires" : [ 6 ] },
{ "id" : 18, "requires" : [ 32 ] },
{ "id" : 19, "requires" : [ 39 ] },
{ "id" : 20, "requires" : [ 6 ] },
{ "id" : 20 },
{ "id" : 21, "requires" : [ 33 ] },
{ "id" : 22, "requires" : [ 5 ] },
{ "id" : 26 },
{ "id" : 30, "requires" : [ 7 ] },
{ "id" : 31, "requires" : [ 30 ] },
{ "id" : 32, "requires" : [ 33 ] },
@ -173,7 +120,7 @@
{
// 1 - Rampart
"defnames" :
"structures" :
[
{ "id" : 16, "defname" : "TBRMBLAK.def", "x" : 558, "y" : 105, "border" : "TORAID.bmp", "area" : "TZRAID.bmp" },
{ "id" : 9, "defname" : "TBRMCAS3.def", "x" : 79, "y" : 18, "border" : "TORCAS2.bmp", "area" : "TZRCAS2.bmp" },
@ -218,6 +165,30 @@
{ "id" : 12, "defname" : "TBRMHAL3.def", "x" : 538, "y" : 187, "border" : "TORHAL3.bmp", "area" : "TZRHAL3.bmp" },
{ "id" : 11, "defname" : "TBRMHAL2.def", "x" : 538, "y" : 187, "border" : "TORHAL2.bmp", "area" : "TZRHAL2.bmp" }
],
"groups" :
[
[ 0, 1, 2, 3, 4 ],
[ 6, 20 ],
[ 7, 8, 9 ],
[ 10, 11, 12, 13 ],
[ 30, 37 ],
[ 32, 39 ],
[ 33, 40 ],
[ 35, 42 ],
[ 36, 43 ],
[ 24, 25, 34, 41 ],
[ 17, 21 ],
[ 31, 18, 38, 19 ]
],
"hallBackground": "TPTHBKRM.BMP",
"hallSlots":
[
[ [ 10, 11, 12, 13 ], [ 7, 8, 9 ], [ 5 ], [ 16 ] ],
[ [ 14, 15 ], [ 0, 1, 2, 3, 4 ], [ 17, 21 ] ],
[ [ 22 ], [ 24, 25 ], [ 18, 19 ] ],
[ [ 30, 37 ], [ 31, 38 ], [ 32, 39 ], [ 33, 40 ] ],
[ [ 34, 41 ], [ 35, 42 ], [ 36, 43 ] ]
],
"blit_order" : [ 33, 40, 35, 42, 16, 32, 39, 0, 1, 2, 3, 4, 31, 18, 38, 19, 34, 24, 41, 25, 5, 30, 37, 14, 10, 11, 12, 13, 17, 21, 22, -1, 27, 28, 29, 15 ],
"creatures" : [ [14, 15], [16, 17], [18, 19], [20, 21], [22, 23], [24, 25], [26, 27] ],
"horde" : [ 1, 4 ],
@ -225,24 +196,32 @@
"primary_resource" : 4,
"war_machine" : 6,
"building_requirements" :
"buildings" :
[
{ "id" : 0 },
{ "id" : 1, "requires" : [ 0 ] },
{ "id" : 2, "requires" : [ 1 ] },
{ "id" : 3, "requires" : [ 2 ] },
{ "id" : 4, "requires" : [ 3 ] },
{ "id" : 5 },
{ "id" : 7 },
{ "id" : 8, "requires" : [ 7 ] },
{ "id" : 9, "requires" : [ 8 ] },
{ "id" : 10 },
{ "id" : 11, "requires" : [ 10, 5 ] },
{ "id" : 12, "requires" : [ 11, 0, 14, 16 ] },
{ "id" : 13, "requires" : [ 12, 9 ] },
{ "id" : 14 },
{ "id" : 15, "requires" : [ 14 ] },
{ "id" : 16 },
{ "id" : 17 },
{ "id" : 18, "requires" : [ 31 ] },
{ "id" : 19, "requires" : [ 38 ] },
{ "id" : 21, "requires" : [ 17 ] },
{ "id" : 22, "requires" : [ 18 ] },
{ "id" : 24, "requires" : [ 34 ] },
{ "id" : 25, "requires" : [ 41 ] },
{ "id" : 26 },
{ "id" : 30, "requires" : [ 7 ] },
{ "id" : 31, "requires" : [ 30 ] },
{ "id" : 32, "requires" : [ 30 ] },
@ -262,7 +241,7 @@
{
// 2 - Tower
"defnames" :
"structures" :
[
{ "id" : 16, "defname" : "TBTWBLAK.def", "x" : 478, "y" : 211, "border" : "TOTBLKA.bmp", "area" : "TZTBLKA.bmp" },
{ "id" : 9, "defname" : "TBTWCAS3.def", "x" : 301, "y" : 0, "border" : "TOTCAS3.bmp", "area" : "TZTCAS3.bmp" },
@ -302,30 +281,61 @@
{ "id" : 43, "defname" : "TBTWUP_6.def", "x" : 75, "y" : 91, "border" : "TOTTIT2.bmp", "area" : "TZTTIT2.bmp" },
{ "id" : 8, "defname" : "TBTWCAS2.def", "x" : 301, "y" : 0, "border" : "TOTCAS2.bmp", "area" : "TZTCAS2.bmp" }
],
"groups" :
[
[ 0, 1, 2, 3, 4 ],
[ 6, 20 ],
[ 7, 8, 9 ],
[ 10, 11, 12, 13 ],
[ 30, 37 ],
[ 32, 39 ],
[ 33, 40 ],
[ 34, 41 ],
[ 35, 42 ],
[ 36, 43 ],
[ 18, 19, 31, 38 ]
],
"hallBackground": "TPTHBKTW.BMP",
"hallSlots":
[
[ [ 10, 11, 12, 13 ], [ 7, 8, 9 ], [ 5 ], [ 16 ] ],
[ [ 14, 15 ], [ 0, 1, 2, 3, 4 ], [ 22 ], [ 23 ] ],
[ [ 17 ], [ 21 ], [ 18, 19 ] ],
[ [ 30, 37 ], [ 31, 38 ], [ 32, 39 ], [ 33, 40 ] ],
[ [ 34, 41 ], [ 35, 42 ], [ 36, 43 ] ]
],
"blit_order" : [ 36, 43, 32, 39, 10, 11, 12, 13, 32, 35, 42, 15, 5, 18, 19 ],
"creatures" : [ [28, 29], [30, 31], [32, 33], [34, 35], [36, 37], [38, 39], [40, 41] ],
"horde" : [ 1, null ],
"horde" : [ 1, -1 ],
"primary_resource" : 5,
"mage_guild" : 5,
"war_machine" : 5,
"building_requirements" :
"buildings" :
[
{ "id" : 0 },
{ "id" : 1, "requires" : [ 0 ] },
{ "id" : 2, "requires" : [ 1 ] },
{ "id" : 3, "requires" : [ 2 ] },
{ "id" : 4, "requires" : [ 3 ] },
{ "id" : 5 },
{ "id" : 7 },
{ "id" : 8, "requires" : [ 7 ] },
{ "id" : 9, "requires" : [ 8 ] },
{ "id" : 10 },
{ "id" : 11, "requires" : [ 10, 5 ] },
{ "id" : 12, "requires" : [ 11, 0, 14, 16 ] },
{ "id" : 13, "requires" : [ 12, 9 ] },
{ "id" : 14 },
{ "id" : 15, "requires" : [ 14 ] },
{ "id" : 16 },
{ "id" : 17, "requires" : [ 14 ] },
{ "id" : 18, "requires" : [ 31 ] },
{ "id" : 19, "requires" : [ 38 ] },
{ "id" : 21, "requires" : [ 7 ] },
{ "id" : 22, "requires" : [ 0 ] },
{ "id" : 23, "requires" : [ 0 ] },
{ "id" : 26 },
{ "id" : 30, "requires" : [ 7 ] },
{ "id" : 31, "requires" : [ 30 ] },
{ "id" : 32, "requires" : [ 30 ] },
@ -345,7 +355,7 @@
{
// 3 - Inferno
"defnames" :
"structures" :
[
{ "id" : 16, "defname" : "TBINBLAK.def", "x" : 684, "y" : 253, "border" : "TOIBLKA.bmp", "area" : "TZIBLKA.bmp" },
{ "id" : 9, "defname" : "TBINCAS3.def", "x" : 222, "y" : 18, "border" : "TOICAS3A.bmp", "area" : "TZICAS3A.bmp" },
@ -386,24 +396,55 @@
{ "id" : 43, "defname" : "TBINUP_6.def", "x" : 420, "y" : 105, "border" : "TOIDVL2.bmp", "area" : "TZIDVL2.bmp" },
{ "id" : 8, "defname" : "TBINCAS2.def", "x" : 222, "y" : 44, "border" : "TOICAS1A.bmp", "area" : "TZICAS1A.bmp" }
],
"groups" :
[
[ 0, 1, 2, 3, 4 ],
[ 6, 20 ],
[ 7, 8, 9 ],
[ 10, 11, 12, 13 ],
[ 30, 37 ],
[ 31, 38 ],
[ 33, 40 ],
[ 34, 41 ],
[ 35, 42 ],
[ 36, 43 ],
[ 18, 19, 30, 37 ],
[ 32, 39, 24, 25 ]
],
"hallBackground": "TPTHBKIN.BMP",
"hallSlots":
[
[ [ 10, 11, 12, 13 ], [ 7, 8, 9 ], [ 5 ], [ 16 ] ],
[ [ 14, 15 ], [ 0, 1, 2, 3, 4 ], [ 23 ], [ 21 ] ],
[ [ 22 ], [ 18, 19 ], [ 24, 25 ] ],
[ [ 30, 37 ], [ 31, 38 ], [ 32, 39 ], [ 33, 40 ] ],
[ [ 34, 41 ], [ 35, 42 ], [ 36, 43 ] ]
],
"blit_order" : [ 26, 21, 7, 8, 9, 22, 31, 38, 36, 43, 10, 11, 12, 13, 5, 32, 39, 24, 25, 33, 40, 34, 41, 30, 37, 18, 19, 14, 15, 16, 35, 42 ],
"creatures" : [ [42, 43], [44, 45], [46, 47], [48, 49], [50, 51], [52, 53], [54, 55] ],
"horde" : [ 0, 2 ],
"mage_guild" : 5,
"primary_resource" : 1,
"war_machine" : 5,
"building_requirements" :
"buildings" :
[
{ "id" : 0 },
{ "id" : 1, "requires" : [ 0 ] },
{ "id" : 2, "requires" : [ 1 ] },
{ "id" : 3, "requires" : [ 2 ] },
{ "id" : 4, "requires" : [ 3 ] },
{ "id" : 5 },
{ "id" : 7 },
{ "id" : 8, "requires" : [ 7 ] },
{ "id" : 9, "requires" : [ 8 ] },
{ "id" : 10 },
{ "id" : 11, "requires" : [ 10, 5 ] },
{ "id" : 12, "requires" : [ 11, 0, 14, 16 ] },
{ "id" : 13, "requires" : [ 12, 9 ] },
{ "id" : 14 },
{ "id" : 15, "requires" : [ 14 ] },
{ "id" : 16 },
{ "id" : 18, "requires" : [ 30 ] },
{ "id" : 19, "requires" : [ 37 ] },
{ "id" : 21, "requires" : [ 7 ] },
@ -411,6 +452,7 @@
{ "id" : 23, "requires" : [ 0 ] },
{ "id" : 24, "requires" : [ 32 ] },
{ "id" : 25, "requires" : [ 39 ] },
{ "id" : 26 },
{ "id" : 30, "requires" : [ 7 ] },
{ "id" : 31, "requires" : [ 30 ] },
{ "id" : 32, "requires" : [ 30 ] },
@ -430,7 +472,7 @@
{
// 4 - Necropolis
"defnames" :
"structures" :
[
{ "id" : 16, "defname" : "TBNCBLAK.def", "x" : 382, "y" : 252, "border" : "TONSMITA.bmp", "area" : "TZNSMITA.bmp" },
{ "id" : 8, "defname" : "TBNCCAS2.def", "x" : 139, "y" : 66, "border" : "TONCAS2.bmp", "area" : "TZNCAS2.bmp" },
@ -475,29 +517,63 @@
{ "id" : 43, "defname" : "TBNCUP_6.def", "x" : 662, "y" : 23, "border" : "TONBON2.bmp", "area" : "TZNBON2.bmp" },
{ "id" : 20, "defname" : "TBNCBOAT.def", "x" : 617, "y" : 265, "border" : "TONSHPNA.bmp", "area" : "TZNSHPNA.bmp" }
],
"groups" :
[
[ 0, 1, 2, 3, 4 ],
[ 6, 20 ],
[ 7, 8, 9 ],
[ 10, 11, 12, 13 ],
[ 31, 38 ],
[ 32, 39 ],
[ 33, 40 ],
[ 34, 41 ],
[ 35, 42 ],
[ 36, 43 ],
[ 30, 37, 18, 19 ]
],
"hallBackground": "TPTHBKNC.BMP",
"hallSlots":
[
[ [ 10, 11, 12, 13 ], [ 7, 8, 9 ], [ 5 ], [ 16 ] ],
[ [ 14, 15 ], [ 0, 1, 2, 3, 4 ], [ 21 ], [ 6 ] ],
[ [ 17 ], [ 22 ], [ 18, 19 ] ],
[ [ 30, 37 ], [ 31, 38 ], [ 32, 39 ], [ 33, 40 ] ],
[ [ 34, 41 ], [ 35, 42 ], [ 36, 43 ] ]
],
"blit_order" : [ 17, 0, 1, 2, 3, 4, 7, 8, 9, 32, 39, 26, 15, 14, 34, 41, 16, 5, 33, 40, 31, 38, 6, 30, 18, 37, 19, 22, 20 ],
"creatures" : [ [56, 57], [58, 59], [60, 61], [62, 63], [64, 65], [66, 67], [68, 69] ],
"horde" : [ 0, null ],
"horde" : [ 0, -1 ],
"mage_guild" : 5,
"primary_resource" : 127,
"war_machine" : 6,
"building_requirements" :
"buildings" :
[
{ "id" : 0 },
{ "id" : 1, "requires" : [ 0 ] },
{ "id" : 2, "requires" : [ 1 ] },
{ "id" : 3, "requires" : [ 2 ] },
{ "id" : 4, "requires" : [ 3 ] },
{ "id" : 5 },
{ "id" : 6 },
{ "id" : 7 },
{ "id" : 8, "requires" : [ 7 ] },
{ "id" : 9, "requires" : [ 8 ] },
{ "id" : 10 },
{ "id" : 11, "requires" : [ 10, 5 ] },
{ "id" : 12, "requires" : [ 11, 0, 14, 16 ] },
{ "id" : 13, "requires" : [ 12, 9 ] },
{ "id" : 14 },
{ "id" : 15, "requires" : [ 14 ] },
{ "id" : 16 },
{ "id" : 17, "requires" : [ 7 ] },
{ "id" : 18, "requires" : [ 22, 30 ] },
{ "id" : 19, "requires" : [ 22, 37 ] },
{ "id" : 20, "requires" : [ 6 ] },
{ "id" : 20 },
{ "id" : 21, "requires" : [ 0 ] },
{ "id" : 22, "requires" : [ 30 ] },
{ "id" : 26 },
{ "id" : 30, "requires" : [ 7 ] },
{ "id" : 31, "requires" : [ 30 ] },
{ "id" : 32, "requires" : [ 30 ] },
@ -517,7 +593,7 @@
{
// 5 - Dungeon
"defnames" :
"structures" :
[
{ "id" : 16, "defname" : "TBDNBLAK.def", "x" : 544, "y" : 248, "border" : "TODSMITH.bmp", "area" : "TZDSMITH.bmp" },
{ "id" : 9, "defname" : "TBDNCAS3.def", "x" : 363, "y" : 87, "border" : "TODCAS3.bmp", "area" : "TZDCAS3.bmp" },
@ -557,28 +633,61 @@
{ "id" : 43, "defname" : "TBDNUP_6.def", "x" : 550, "y" : 0, "border" : "TODDRA2A.bmp", "area" : "TZDDRA2A.bmp" },
{ "id" : 8, "defname" : "TBDNCAS2.def", "x" : 363, "y" : 87, "border" : "TODCAS2.bmp", "area" : "TZDCAS2.bmp" }
],
"groups" :
[
[ 0, 1, 2, 3, 4 ],
[ 6, 20 ],
[ 7, 8, 9 ],
[ 10, 11, 12, 13 ],
[ 31, 38 ],
[ 32, 39 ],
[ 33, 40 ],
[ 34, 41 ],
[ 35, 42 ],
[ 36, 43 ],
[ 30, 37, 18, 19 ]
],
"hallBackground": "TPTHBKDG.BMP",
"hallSlots":
[
[ [ 10, 11, 12, 13 ], [ 7, 8, 9 ], [ 5 ], [ 16 ] ],
[ [ 14, 15 ], [ 0, 1, 2, 3, 4 ], [ 21 ], [ 22 ] ],
[ [ 17 ], [ 23 ], [ 18, 19 ] ],
[ [ 30, 37 ], [ 31, 38 ], [ 32, 39 ], [ 33, 40 ] ],
[ [ 34, 41 ], [ 35, 42 ], [ 36, 43 ] ]
],
"blit_order" : [ 0, 1, 2, 3, 4, 21, 35, 42, 5, 30, 18, 37, 19, 32, 39, 26, 7, 8, 9, 23 ],
"creatures" : [ [70, 71], [72, 73], [74, 75], [76, 77], [78, 79], [80, 81], [82, 83] ],
"horde" : [ 0, null ],
"horde" : [ 0, -1 ],
"mage_guild" : 5,
"primary_resource" : 3,
"war_machine" : 4,
"building_requirements" :
"buildings" :
[
{ "id" : 0 },
{ "id" : 1, "requires" : [ 0 ] },
{ "id" : 2, "requires" : [ 1 ] },
{ "id" : 3, "requires" : [ 2 ] },
{ "id" : 4, "requires" : [ 3 ] },
{ "id" : 5 },
{ "id" : 7 },
{ "id" : 8, "requires" : [ 7 ] },
{ "id" : 9, "requires" : [ 8 ] },
{ "id" : 10 },
{ "id" : 11, "requires" : [ 10, 5 ] },
{ "id" : 12, "requires" : [ 11, 0, 14, 16 ] },
{ "id" : 13, "requires" : [ 12, 9 ] },
{ "id" : 14 },
{ "id" : 15, "requires" : [ 14 ] },
{ "id" : 16 },
{ "id" : 17, "requires" : [ 14 ] },
{ "id" : 18, "requires" : [ 30 ] },
{ "id" : 19, "requires" : [ 37 ] },
{ "id" : 21, "requires" : [ 0 ] },
{ "id" : 22 },
{ "id" : 23 },
{ "id" : 26 },
{ "id" : 30, "requires" : [ 7 ] },
{ "id" : 31, "requires" : [ 30 ] },
{ "id" : 32, "requires" : [ 30 ] },
@ -598,7 +707,7 @@
{
// 6 - Stronghold
"defnames" :
"structures" :
[
{ "id" : 31, "defname" : "TBSTDW_1.def", "x" : 266, "y" : 246, "border" : "TOSWOL1.bmp", "area" : "TZSWOL1.bmp" },
{ "id" : 43, "defname" : "TBSTUP_6.def", "x" : 604, "y" : 0, "border" : "TOSBEH2A.bmp", "area" : "TZSBEH2A.bmp" },
@ -637,30 +746,61 @@
{ "id" : 42, "defname" : "TBSTUP_5.def", "x" : 616, "y" : 93, "border" : "TOSCYC2A.bmp", "area" : "TZSCYC2A.bmp" },
{ "id" : 16, "defname" : "TBSTBLAK.def", "x" : 660, "y" : 286, "border" : "TOSBLK1.bmp", "area" : "TZSBLK1.bmp" }
],
"groups" :
[
[ 0, 1, 2, 3, 4 ],
[ 6, 20 ],
[ 7, 8, 9 ],
[ 10, 11, 12, 13 ],
[ 31, 38 ],
[ 32, 39 ],
[ 33, 40 ],
[ 34, 41 ],
[ 35, 42 ],
[ 36, 43 ],
[ 30, 37, 18, 19 ]
],
"hallBackground": "TPTHBKTW.BMP",
"hallSlots":
[
[ [ 10, 11, 12, 13 ], [ 7, 8, 9 ], [ 5 ], [ 16 ] ],
[ [ 14, 15 ], [ 0, 1, 2 ], [ 23 ], [ 17 ] ],
[ [ 21 ], [ 22 ], [ 18, 19 ] ],
[ [ 30, 37 ], [ 31, 38 ], [ 32, 39 ], [ 33, 40 ] ],
[ [ 34, 41 ], [ 35, 42 ], [ 36, 43 ] ]
],
"blit_order" : [ 33, 40, 30, 18, 37, 19, 31, 38, 23, 26, 5, 32, 39, 15, 14, 21, 16, 22 ],
"creatures" : [ [84, 85], [86, 87], [88, 89], [90, 91], [92, 93], [94, 95], [96, 97] ],
"horde" : [ 0, null ],
"horde" : [ 0, -1 ],
"mage_guild" : 3,
"primary_resource" : 127,
"war_machine" : 5,
"building_requirements" :
"buildings" :
[
{ "id" : 0 },
{ "id" : 1, "requires" : [ 0 ] },
{ "id" : 2, "requires" : [ 1 ] },
{ "id" : 3, "requires" : [ 2 ] },
{ "id" : 4, "requires" : [ 3 ] },
{ "id" : 5 },
{ "id" : 7 },
{ "id" : 8, "requires" : [ 7 ] },
{ "id" : 9, "requires" : [ 8 ] },
{ "id" : 10 },
{ "id" : 11, "requires" : [ 10, 5 ] },
{ "id" : 12, "requires" : [ 11, 0, 14, 16 ] },
{ "id" : 13, "requires" : [ 12, 9 ] },
{ "id" : 14 },
{ "id" : 15, "requires" : [ 14 ] },
{ "id" : 16 },
{ "id" : 17, "requires" : [ 7 ] },
{ "id" : 18, "requires" : [ 30 ] },
{ "id" : 19, "requires" : [ 37 ] },
{ "id" : 21, "requires" : [ 14 ] },
{ "id" : 22, "requires" : [ 16 ] },
{ "id" : 23, "requires" : [ 7 ] },
{ "id" : 26 },
{ "id" : 30, "requires" : [ 7 ] },
{ "id" : 31, "requires" : [ 30 ] },
{ "id" : 32, "requires" : [ 30 ] },
@ -680,7 +820,7 @@
{
// 7 - Fortress
"defnames" :
"structures" :
[
{ "id" : 16, "defname" : "TBFRBLAK.def", "x" : 360, "y" : 160, "border" : "TOFAIDA.bmp", "area" : "TZFAIDA.bmp" },
{ "id" : 8, "defname" : "TBFRCAS2.def", "x" : 368, "y" : 98, "border" : "TOFCAS2.bmp", "area" : "TZFCAS2.bmp" },
@ -721,29 +861,62 @@
{ "id" : 29, "defname" : "TBFRWTRW.def", "x" : 320, "y" : 141 },
{ "id" : 20, "defname" : "TBFRBOAT.def", "x" : 197, "y" : 294, "border" : "TOFDCK1.bmp", "area" : "TZFDCK1.bmp" }
],
"groups" :
[
[ 0, 1, 2, 3, 4 ],
[ 6, 20 ],
[ 7, 8, 9 ],
[ 10, 11, 12, 13 ],
[ 31, 38 ],
[ 32, 39 ],
[ 33, 40 ],
[ 34, 41 ],
[ 35, 42 ],
[ 36, 43 ],
[ 30, 37, 18, 19 ]
],
"hallBackground": "TPTHBKFR.BMP",
"hallSlots":
[
[ [ 10, 11, 12, 13 ], [ 7, 8, 9 ], [ 5 ], [ 16 ] ],
[ [ 14, 15 ], [ 0, 1, 2 ], [ 6 ] ],
[ [ 17 ], [ 21, 22 ], [ 18, 19 ] ],
[ [ 30, 37 ], [ 31, 38 ], [ 32, 39 ], [ 33, 40 ] ],
[ [ 34, 41 ], [ 35, 42 ], [ 36, 43 ] ]
],
"blit_order" : [ 16, 15, 14, 34, 41, 31, 38, 10, 11, 12, 13, 29, 0, 1, 2, 33, 40, 30, 18, 37, 19, 5, 36, 43, 26 ],
"creatures" : [ [98, 99], [100, 101], [104, 105], [106, 107], [102, 103], [108, 109], [110, 111] ],
"horde" : [ 0, null ],
"horde" : [ 0, -1 ],
"mage_guild" : 3,
"primary_resource" : 127,
"war_machine" : 6,
"building_requirements" :
"buildings" :
[
{ "id" : 0 },
{ "id" : 1, "requires" : [ 0 ] },
{ "id" : 2, "requires" : [ 1 ] },
{ "id" : 3, "requires" : [ 2 ] },
{ "id" : 4, "requires" : [ 3 ] },
{ "id" : 5 },
{ "id" : 6 },
{ "id" : 7 },
{ "id" : 8, "requires" : [ 7 ] },
{ "id" : 9, "requires" : [ 8 ] },
{ "id" : 10 },
{ "id" : 11, "requires" : [ 10, 5 ] },
{ "id" : 12, "requires" : [ 11, 0, 14, 16 ] },
{ "id" : 13, "requires" : [ 12, 9 ] },
{ "id" : 14 },
{ "id" : 15, "requires" : [ 14 ] },
{ "id" : 16 },
{ "id" : 17, "requires" : [ 11, 21 ] },
{ "id" : 18, "requires" : [ 30 ] },
{ "id" : 19, "requires" : [ 37 ] },
{ "id" : 20 },
{ "id" : 21, "requires" : [ 7 ] },
{ "id" : 22, "requires" : [ 21 ] },
{ "id" : 26 },
{ "id" : 30, "requires" : [ 7 ] },
{ "id" : 31, "requires" : [ 30 ] },
{ "id" : 32, "requires" : [ 30 ] },
@ -763,7 +936,7 @@
{
// 8 - Conflux
"defnames" :
"structures" :
[
{ "id" : 16, "defname" : "TBELBLAK.def", "x" : 449, "y" : 151, "border" : "TOELBLAK.bmp", "area" : "TZELBLAK.bmp" },
{ "id" : 8, "defname" : "TBELCAS2.def", "x" : 349, "y" : 101, "border" : "TOELCAS2.bmp", "area" : "TZELCAS2.bmp" },
@ -808,28 +981,61 @@
{ "id" : 43, "defname" : "TBELUP_6.def", "x" : 43, "y" : 0, "border" : "TOELUP_6.bmp", "area" : "TZELUP_6.bmp" },
{ "id" : 20, "defname" : "TBELBOAT.def", "x" : 239, "y" : 215, "border" : "TOELBOAT.bmp", "area" : "TZELBOAT.bmp" }
],
"groups" :
[
[ 0, 1, 2, 3, 4 ],
[ 6, 20 ],
[ 7, 8, 9 ],
[ 10, 11, 12, 13 ],
[ 31, 38 ],
[ 32, 39 ],
[ 33, 40 ],
[ 34, 41 ],
[ 35, 42 ],
[ 36, 43 ],
[ 30, 37, 18, 19 ]
],
"hallBackground": "TPTHBKFR.BMP",
"hallSlots":
[
[ [ 10, 11, 12, 13 ], [ 7, 8, 9 ], [ 5 ], [ 16 ] ],
[ [ 14, 15 ], [ 0, 1, 2, 3, 4 ], [ 6 ] ],
[ [ 21 ], [ 17 ], [ 18, 19 ] ],
[ [ 30, 37 ], [ 31, 38 ], [ 32, 39 ], [ 33, 40 ] ],
[ [ 34, 41 ], [ 35, 42 ], [ 36, 43 ] ]
],
"blit_order" : [ -1, 27, 28, 16, 34, 41, 6, 20, 33, 40, 36, 43, 21, 0, 1, 2, 3, 4, 5, 15, 14, 17, 35, 42, 30, 18, 37, 19, 10, 11, 12, 13, 29 ],
"creatures" : [ [118, 119], [112, 127], [115, 123], [114, 129], [113, 125], [120, 121], [130, 131] ],
"horde" : [ 0, null ],
"horde" : [ 0, -1 ],
"mage_guild" : 5,
"primary_resource" : 1,
"war_machine" : 4,
"building_requirements" :
"buildings" :
[
{ "id" : 0 },
{ "id" : 1, "requires" : [ 0 ] },
{ "id" : 2, "requires" : [ 1 ] },
{ "id" : 3, "requires" : [ 2 ] },
{ "id" : 4, "requires" : [ 3 ] },
{ "id" : 5 },
{ "id" : 6 },
{ "id" : 7 },
{ "id" : 8, "requires" : [ 7 ] },
{ "id" : 9, "requires" : [ 8 ] },
{ "id" : 10 },
{ "id" : 11, "requires" : [ 10, 5 ] },
{ "id" : 12, "requires" : [ 11, 0, 14, 16 ] },
{ "id" : 13, "requires" : [ 12, 9 ] },
{ "id" : 14 },
{ "id" : 15, "requires" : [ 14 ] },
{ "id" : 16 },
{ "id" : 17, "requires" : [ 14 ] },
{ "id" : 18, "requires" : [ 30 ] },
{ "id" : 19, "requires" : [ 37 ] },
{ "id" : 20 },
{ "id" : 21, "requires" : [ 0 ] },
{ "id" : 26 },
{ "id" : 30, "requires" : [ 7 ] },
{ "id" : 31, "requires" : [ 30, 0 ] },
{ "id" : 32, "requires" : [ 30, 0 ] },
@ -846,100 +1052,5 @@
{ "id" : 43, "requires" : [ 36 ] }
]
}
],
//A group contains a vector of building IDs
//In the town screen only the last built structure from the group is displayed
//Eg. when there is Mage Guild Level 3, then we don't display Mage Guild Level 1 and 2
"town_groups" :
[
{
// Applies to all castles
"id" : -1,
"groups" :
[
[ 0, 1, 2, 3, 4 ],
[ 6, 20 ],
[ 7, 8, 9 ],
[ 10, 11, 12, 13 ],
[ 30, 37 ],
[ 31, 38 ],
[ 32, 39 ],
[ 33, 40 ],
[ 34, 41 ],
[ 35, 42 ],
[ 36, 43 ],
[ 24, 25 ],
[ 18, 19 ]
]
},
{
"id" : 1,
"groups" :
[
[ 24, 25, 34, 41 ],
[ 17, 21 ],
[ 31, 18, 38, 19 ]
]
},
{
"id" : 2,
"groups" :
[
[ 18, 19, 31, 38 ]
]
},
{
"id" : 3,
"groups" :
[
[ 18, 19, 30, 37 ],
[ 32, 39, 24, 25 ]
]
},
{
"id" : 4,
"groups" :
[
[ 30, 37, 18, 19 ]
]
},
{
"id" : 5,
"groups" :
[
[ 30, 37, 18, 19 ]
]
},
{
"id" : 6,
"groups" :
[
[ 21 ],
[ 30, 37, 18, 19 ]
]
},
{
"id" : 7,
"groups" :
[
[ 30, 37, 18, 19 ]
]
},
{
"id" : 8,
"groups" :
[
[ 30, 37, 18, 19 ]
]
}
]
}

View File

@ -1,114 +0,0 @@
{
// for each castle:
// id: town ID
// boxes: row buildings containing sets of ids for each box
"town": [
{
"id": 0,
"image": "TPTHBKCS.BMP",
"boxes": [
[ [ 10, 11, 12, 13 ], [ 7, 8, 9 ], [ 5, 22 ], [ 16 ] ],
[ [ 14, 15 ], [ 0, 1, 2, 3 ], [ 6, 17 ] ],
[ [ 21 ], [ 18, 19 ] ],
[ [ 30, 37 ], [ 31, 38 ], [ 32, 39 ], [ 33, 40 ] ],
[ [ 34, 41 ], [ 35, 42 ], [ 36, 43 ] ]
]
},
{
"id": 1,
"image": "TPTHBKRM.BMP",
"boxes": [
[ [ 10, 11, 12, 13 ], [ 7, 8, 9 ], [ 5 ], [ 16 ] ],
[ [ 14, 15 ], [ 0, 1, 2, 3, 4 ], [ 17, 21 ] ],
[ [ 22 ], [ 24, 25 ], [ 18, 19 ] ],
[ [ 30, 37 ], [ 31, 38 ], [ 32, 39 ], [ 33, 40 ] ],
[ [ 34, 41 ], [ 35, 42 ], [ 36, 43 ] ]
]
},
{
"id": 2,
"image": "TPTHBKTW.BMP",
"boxes": [
[ [ 10, 11, 12, 13 ], [ 7, 8, 9 ], [ 5 ], [ 16 ] ],
[ [ 14, 15 ], [ 0, 1, 2, 3, 4 ], [ 22 ], [ 23 ] ],
[ [ 17 ], [ 21 ], [ 18, 19 ] ],
[ [ 30, 37 ], [ 31, 38 ], [ 32, 39 ], [ 33, 40 ] ],
[ [ 34, 41 ], [ 35, 42 ], [ 36, 43 ] ]
]
},
{
"id": 3,
"image": "TPTHBKIN.BMP",
"boxes": [
[ [ 10, 11, 12, 13 ], [ 7, 8, 9 ], [ 5 ], [ 16 ] ],
[ [ 14, 15 ], [ 0, 1, 2, 3, 4 ], [ 23 ], [ 21 ] ],
[ [ 22 ], [ 18, 19 ], [ 24, 25 ] ],
[ [ 30, 37 ], [ 31, 38 ], [ 32, 39 ], [ 33, 40 ] ],
[ [ 34, 41 ], [ 35, 42 ], [ 36, 43 ] ]
]
},
{
"id": 4,
"image": "TPTHBKNC.BMP",
"boxes": [
[ [ 10, 11, 12, 13 ], [ 7, 8, 9 ], [ 5 ], [ 16 ] ],
[ [ 14, 15 ], [ 0, 1, 2, 3, 4 ], [ 21 ], [ 6 ] ],
[ [ 17 ], [ 22 ], [ 18, 19 ] ],
[ [ 30, 37 ], [ 31, 38 ], [ 32, 39 ], [ 33, 40 ] ],
[ [ 34, 41 ], [ 35, 42 ], [ 36, 43 ] ]
]
},
{
"id": 5,
"image": "TPTHBKDG.BMP",
"boxes": [
[ [ 10, 11, 12, 13 ], [ 7, 8, 9 ], [ 5 ], [ 16 ] ],
[ [ 14, 15 ], [ 0, 1, 2, 3, 4 ], [ 21 ], [ 22 ] ],
[ [ 17 ], [ 23 ], [ 18, 19 ] ],
[ [ 30, 37 ], [ 31, 38 ], [ 32, 39 ], [ 33, 40 ] ],
[ [ 34, 41 ], [ 35, 42 ], [ 36, 43 ] ]
]
},
{
"id": 6,
"image": "TPTHBKTW.BMP",
"boxes": [
[ [ 10, 11, 12, 13 ], [ 7, 8, 9 ], [ 5 ], [ 16 ] ],
[ [ 14, 15 ], [ 0, 1, 2 ], [ 23 ], [ 17 ] ],
[ [ 21 ], [ 22 ], [ 18, 19 ] ],
[ [ 30, 37 ], [ 31, 38 ], [ 32, 39 ], [ 33, 40 ] ],
[ [ 34, 41 ], [ 35, 42 ], [ 36, 43 ] ]
]
},
{
"id": 7,
"image": "TPTHBKFR.BMP",
"boxes": [
[ [ 10, 11, 12, 13 ], [ 7, 8, 9 ], [ 5 ], [ 16 ] ],
[ [ 14, 15 ], [ 0, 1, 2 ], [ 6 ] ],
[ [ 17 ], [ 21, 22 ], [ 18, 19 ] ],
[ [ 30, 37 ], [ 31, 38 ], [ 32, 39 ], [ 33, 40 ] ],
[ [ 34, 41 ], [ 35, 42 ], [ 36, 43 ] ]
]
},
{
"id": 8,
"image": "TPTHBKFR.BMP",
"boxes": [
[ [ 10, 11, 12, 13 ], [ 7, 8, 9 ], [ 5 ], [ 16 ] ],
[ [ 14, 15 ], [ 0, 1, 2, 3, 4 ], [ 6 ] ],
[ [ 21 ], [ 17 ], [ 18, 19 ] ],
[ [ 30, 37 ], [ 31, 38 ], [ 32, 39 ], [ 33, 40 ] ],
[ [ 34, 41 ], [ 35, 42 ], [ 36, 43 ] ]
]
}
]
}

View File

@ -1,10 +1,6 @@
#include "StdInc.h"
#include "CBuildingHandler.h"
#include "CGeneralTextHandler.h"
#include "VCMI_Lib.h"
#include "Filesystem/CResourceLoader.h"
#include "JsonNode.h"
#include "GameConstants.h"
/*
@ -17,175 +13,6 @@
*
*/
CBuilding * readBuilding(CLegacyConfigParser & parser, int townID, int buildID)
{
CBuilding * ret = new CBuilding;
ret->tid = townID;
ret->bid = buildID;
for (size_t i=0; i< ret->resources.size(); i++)
ret->resources[i] = parser.readNumber();
parser.endLine();
return ret;
}
void CBuildingHandler::loadBuildings()
{
CLegacyConfigParser parser("DATA/BUILDING.TXT");
buildings.resize(GameConstants::F_NUMBER);
parser.endLine(); // header
parser.endLine();
//Unique buildings
for (size_t town=0; town<GameConstants::F_NUMBER; town++)
{
parser.endLine(); //header
parser.endLine();
int buildID = 17;
do
{
buildings[town][buildID] = readBuilding(parser, town, buildID);
buildID++;
}
while (!parser.isNextEntryEmpty());
}
// Common buildings
parser.endLine(); // header
parser.endLine();
parser.endLine();
int buildID = 0;
do
{
buildings[0][buildID] = readBuilding(parser, 0, buildID);
for (size_t town=1; town<GameConstants::F_NUMBER; town++)
{
buildings[town][buildID] = new CBuilding(*buildings[0][buildID]);
buildings[town][buildID]->tid = town;
}
buildID++;
}
while (!parser.isNextEntryEmpty());
parser.endLine(); //header
parser.endLine();
//Dwellings
for (size_t town=0; town<GameConstants::F_NUMBER; town++)
{
parser.endLine(); //header
parser.endLine();
int buildID = 30;
do
{
buildings[town][buildID] = readBuilding(parser, town, buildID);
buildID++;
}
while (!parser.isNextEntryEmpty());
}
// Grail. It may not have entries in building.txt
for (size_t town=0; town<GameConstants::F_NUMBER; town++)
{
if (!vstd::contains(buildings[town], 26))
{
buildings[town][26] = new CBuilding();
buildings[town][26]->tid = town;
buildings[town][26]->bid = 26;
}
}
/////done reading BUILDING.TXT*****************************
const JsonNode config(ResourceID("config/hall.json"));
BOOST_FOREACH(const JsonNode &town, config["town"].Vector())
{
int tid = town["id"].Float();
hall[tid].first = town["image"].String();
(hall[tid].second).resize(5); //rows
int row_num = 0;
BOOST_FOREACH(const JsonNode &row, town["boxes"].Vector())
{
BOOST_FOREACH(const JsonNode &box, row.Vector())
{
(hall[tid].second)[row_num].push_back(std::vector<int>()); //push new box
std::vector<int> &box_vec = (hall[tid].second)[row_num].back();
BOOST_FOREACH(const JsonNode &value, box.Vector())
{
box_vec.push_back(value.Float());
}
}
row_num ++;
}
assert (row_num == 5);
}
// Buildings dependencies. Which building depend on which other building.
const JsonNode buildingsConf(ResourceID("config/buildings.json"));
// Iterate for each city type
int townID = 0;
BOOST_FOREACH(const JsonNode &town_node, buildingsConf["town_type"].Vector())
{
BOOST_FOREACH(const JsonNode &node, town_node["building_requirements"].Vector())
{
int id = node["id"].Float();
CBuilding * build = buildings[townID][id];
if (build)
{
BOOST_FOREACH(const JsonNode &building, node["requires"].Vector())
{
build->requirements.insert(building.Float());
}
}
}
townID++;
}
}
CBuildingHandler::~CBuildingHandler()
{
for(std::vector< bmap<int, ConstTransitivePtr<CBuilding> > >::iterator i=buildings.begin(); i!=buildings.end(); i++)
for(std::map<int, ConstTransitivePtr<CBuilding> >::iterator j=i->begin(); j!=i->end(); j++)
j->second.dellNull();
}
static std::string emptyStr = "";
const std::string & CBuilding::Name() const
{
if(name.length())
return name;
else if(vstd::contains(VLC->generaltexth->buildings,tid) && vstd::contains(VLC->generaltexth->buildings[tid],bid))
return VLC->generaltexth->buildings[tid][bid].first;
tlog2 << "Warning: Cannot find name text for building " << bid << "for " << tid << "town.\n";
return emptyStr;
}
const std::string & CBuilding::Description() const
{
if(description.length())
return description;
else if(vstd::contains(VLC->generaltexth->buildings,tid) && vstd::contains(VLC->generaltexth->buildings[tid],bid))
return VLC->generaltexth->buildings[tid][bid].second;
tlog2 << "Warning: Cannot find description text for building " << bid << "for " << tid << "town.\n";
return emptyStr;
}
CBuilding::CBuilding( int TID, int BID )
{
tid = TID;
bid = BID;
}
int CBuildingHandler::campToERMU( int camp, int townType, std::set<si32> builtBuildings )
{
using namespace boost::assign;

View File

@ -1,9 +1,5 @@
#pragma once
#include "../lib/ConstTransitivePtr.h"
#include "ResourceSet.h"
/*
* CBuildingHandler.h, part of VCMI engine
*
@ -14,39 +10,8 @@
*
*/
//enum EbuildingType {NEUTRAL=-1, CASTLE, RAMPART, TOWER, INFERNO, NECROPOLIS, DUNGEON, STRONGHOLD, FORTRESS, CONFLUX};
class DLL_LINKAGE CBuilding //a typical building encountered in every castle ;]
{
public:
si32 tid, bid; //town ID and structure ID
TResources resources;
std::string name;
std::string description;
std::set<int> requirements; //set of required buildings
const std::string &Name() const;
const std::string &Description() const;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & tid & bid & resources & name & description & requirements;
}
CBuilding(int TID = -1, int BID = -1);
};
class DLL_LINKAGE CBuildingHandler
{
public:
typedef bmap<int, ConstTransitivePtr<CBuilding> > TBuildingsMap;
std::vector< TBuildingsMap > buildings; ///< vector by castle ID, second the building ID (in ERM-U format)
bmap<int, std::pair<std::string,std::vector< std::vector< std::vector<int> > > > > hall; //map<castle ID, pair<hall bg name, std::vector< std::vector<building id> >[5]> - external vector is the vector of buildings in the row, internal is the list of buildings for the specific slot
void loadBuildings(); //main loader
~CBuildingHandler(); //d-tor
static int campToERMU(int camp, int townType, std::set<si32> builtBuildings);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & buildings & hall;
}
};

View File

@ -1053,30 +1053,12 @@ void CGameState::init(StartInfo * si)
}
/******************RESOURCES****************************************************/
TResources startresAI, startresHuman;
const JsonNode config(ResourceID("config/startres.json"));
const JsonVector &vector = config["difficulty"].Vector();
const JsonNode &level = vector[scenarioOps->difficulty];
const JsonNode &human = level["human"];
const JsonNode &ai = level["ai"];
startresHuman[0] = human["wood"].Float();
startresHuman[1] = human["mercury"].Float();
startresHuman[2] = human["ore"].Float();
startresHuman[3] = human["sulfur"].Float();
startresHuman[4] = human["crystal"].Float();
startresHuman[5] = human["gems"].Float();
startresHuman[6] = human["gold"].Float();
startresHuman[7] = human["mithril"].Float();
startresAI[0] = ai["wood"].Float();
startresAI[1] = ai["mercury"].Float();
startresAI[2] = ai["ore"].Float();
startresAI[3] = ai["sulfur"].Float();
startresAI[4] = ai["crystal"].Float();
startresAI[5] = ai["gems"].Float();
startresAI[6] = ai["gold"].Float();
startresAI[7] = ai["mithril"].Float();
TResources startresAI(level["ai"]);
TResources startresHuman(level["human"]);
for (std::map<ui8,PlayerState>::iterator i = players.begin(); i!=players.end(); i++)
{

View File

@ -7267,7 +7267,7 @@ GrowthInfo::Entry::Entry(const std::string &format, int _count)
GrowthInfo::Entry::Entry(int subID, EBuilding::EBuilding building, int _count)
: count(_count)
{
description = boost::str(boost::format("%s %+d") % VLC->buildh->buildings[subID][building]->Name() % count);
description = boost::str(boost::format("%s %+d") % VLC->townh->towns[subID].buildings[building]->Name() % count);
}
CTownAndVisitingHero::CTownAndVisitingHero()

View File

@ -17,148 +17,26 @@
*
*/
CTownHandler::CTownHandler()
static std::string emptyStr = "";
const std::string & CBuilding::Name() const
{
VLC->townh = this;
if(name.length())
return name;
else if(vstd::contains(VLC->generaltexth->buildings,tid) && vstd::contains(VLC->generaltexth->buildings[tid],bid))
return VLC->generaltexth->buildings[tid][bid].first;
tlog2 << "Warning: Cannot find name text for building " << bid << "for " << tid << "town.\n";
return emptyStr;
}
CTownHandler::~CTownHandler()
const std::string & CBuilding::Description() const
{
for( std::vector<std::map<int, Structure*> >::iterator i= structures.begin(); i!=structures.end(); i++)
for( std::map<int, Structure*>::iterator j = i->begin(); j!=i->end(); j++)
delete j->second;
}
void CTownHandler::loadStructures()
{
int townID;
for (townID=0; townID<GameConstants::F_NUMBER; townID++)
{
CTown town;
town.typeID=townID;
town.bonus=towns.size();
if (town.bonus==8) town.bonus=3;
towns.push_back(town);
}
for(int x=0;x<towns.size();x++)
towns[x].creatures.resize(GameConstants::CREATURES_PER_TOWN);
structures.resize(GameConstants::F_NUMBER);
// read city properties
const JsonNode config(ResourceID("config/buildings.json"));
// Iterate for each city type
townID = 0;
BOOST_FOREACH(const JsonNode &town_node, config["town_type"].Vector()) {
int level;
std::map<int, Structure*> &town = structures[townID];
// Read buildings coordinates for that city
BOOST_FOREACH(const JsonNode &node, town_node["defnames"].Vector()) {
Structure *vinya = new Structure;
const JsonNode *value;
vinya->group = -1;
vinya->townID = townID;
vinya->ID = node["id"].Float();
vinya->defName = node["defname"].String();
vinya->name = vinya->defName; //TODO - use normal names
vinya->pos.x = node["x"].Float();
vinya->pos.y = node["y"].Float();
vinya->pos.z = 0;
value = &node["border"];
if (!value->isNull())
vinya->borderName = value->String();
value = &node["area"];
if (!value->isNull())
vinya->areaName = value->String();
town[vinya->ID] = vinya;
}
// Read buildings blit order for that city
int itr = 1;
BOOST_FOREACH(const JsonNode &node, town_node["blit_order"].Vector()) {
int buildingID = node.Float();
/* Find the building and set its order. */
std::map<int, Structure*>::iterator i2 = town.find(buildingID);
if (i2 != (town.end()))
i2->second->pos.z = itr++;
else
tlog3 << "Warning1: No building " << buildingID << " in the castle " << townID << std::endl;
}
// Read creatures belonging to that city
level = 0;
BOOST_FOREACH(const JsonNode &list, town_node["creatures"].Vector())
{
BOOST_FOREACH(const JsonNode &node, list.Vector())
{
towns[townID].creatures[level].push_back(node.Float());
}
level ++;
}
// Horde building creature level
level = 0;
BOOST_FOREACH(const JsonNode &node, town_node["horde"].Vector()) {
towns[townID].hordeLvl[level] = node.Float();
level ++;
}
// Misc.
towns[townID].mageLevel = town_node["mage_guild"].Float();
towns[townID].primaryRes = town_node["primary_resource"].Float();
towns[townID].warMachine = town_node["war_machine"].Float();
townID ++;
}
int group_num=0;
// Iterate for each city
BOOST_FOREACH(const JsonNode &town_node, config["town_groups"].Vector()) {
townID = town_node["id"].Float();
// Iterate for each group for that city
BOOST_FOREACH(const JsonNode &group, town_node["groups"].Vector()) {
group_num ++;
// Iterate for each bulding value in the group
BOOST_FOREACH(const JsonNode &value, group.Vector()) {
int buildingID = value.Float();
std::vector<std::map<int, Structure*> >::iterator i;
std::map<int, Structure*>::iterator i2;
if (townID >= 0) {
if ((i = structures.begin() + townID) != structures.end()) {
if ((i2=(i->find(buildingID)))!=(i->end()))
i2->second->group = group_num;
else
tlog3 << "Warning3: No building "<<buildingID<<" in the castle "<<townID<<std::endl;
}
else
tlog3 << "Warning3: Castle "<<townID<<" not defined."<<std::endl;
} else {
// Set group for selected building in ALL castles
for (i=structures.begin();i!=structures.end();i++) {
for(i2=i->begin(); i2!=i->end(); i2++) {
if(i2->first == buildingID) {
i2->second->group = group_num;
break;
}
}
}
}
}
}
}
if(description.length())
return description;
else if(vstd::contains(VLC->generaltexth->buildings,tid) && vstd::contains(VLC->generaltexth->buildings[tid],bid))
return VLC->generaltexth->buildings[tid][bid].second;
tlog2 << "Warning: Cannot find description text for building " << bid << "for " << tid << "town.\n";
return emptyStr;
}
const std::string & CTown::Name() const
@ -176,3 +54,264 @@ const std::vector<std::string> & CTown::Names() const
else
return VLC->generaltexth->townNames[typeID];
}
CTownHandler::CTownHandler()
{
VLC->townh = this;
}
JsonNode readBuilding(CLegacyConfigParser & parser)
{
JsonNode ret;
JsonNode & cost = ret["cost"];
const std::string resources [] = {"wood", "mercury", "ore", "sulfur", "crystal", "gems", "gold"};
BOOST_FOREACH(const std::string & resID, resources)
cost[resID].Float() = parser.readNumber();
parser.endLine();
return ret;
}
void CTownHandler::loadLegacyData(JsonNode & dest)
{
CLegacyConfigParser parser("DATA/BUILDING.TXT");
dest.Vector().resize(GameConstants::F_NUMBER);
parser.endLine(); // header
parser.endLine();
//Unique buildings
for (size_t town=0; town<GameConstants::F_NUMBER; town++)
{
JsonVector & buildList = dest.Vector()[town].Vector();
buildList.resize( 30 ); //prepare vector for first set of buildings
parser.endLine(); //header
parser.endLine();
int buildID = 17;
do
{
buildList[buildID] = readBuilding(parser);
buildID++;
}
while (!parser.isNextEntryEmpty());
}
// Common buildings
parser.endLine(); // header
parser.endLine();
parser.endLine();
int buildID = 0;
do
{
JsonNode building = readBuilding(parser);
for (size_t town=0; town<GameConstants::F_NUMBER; town++)
dest.Vector()[town].Vector()[buildID] = building;
buildID++;
}
while (!parser.isNextEntryEmpty());
parser.endLine(); //header
parser.endLine();
//Dwellings
for (size_t town=0; town<GameConstants::F_NUMBER; town++)
{
parser.endLine(); //header
parser.endLine();
do
{
dest.Vector()[town].Vector().push_back(readBuilding(parser));
}
while (!parser.isNextEntryEmpty());
}
}
void CTownHandler::loadBuilding(CTown &town, const JsonNode & source)
{
CBuilding * ret = new CBuilding;
ret->name = source["name"].String();
ret->description = source["description"].String();
ret->tid = town.typeID;
ret->bid = source["id"].Float();
ret->resources = TResources(source["cost"]);
BOOST_FOREACH(const JsonNode &building, source["requires"].Vector())
ret->requirements.insert(building.Float());
town.buildings[ret->bid] = ret;
}
void CTownHandler::loadBuildings(CTown &town, const JsonNode & source)
{
BOOST_FOREACH(const JsonNode &node, source.Vector())
{
loadBuilding(town, node);
}
}
void CTownHandler::loadStructure(CTown &town, const JsonNode & source)
{
CStructure * ret = new CStructure;
ret->ID = source["id"].Float();
ret->pos.x = source["x"].Float();
ret->pos.y = source["y"].Float();
ret->pos.z = 0;
ret->defName = source["defname"].String();
ret->borderName = source["border"].String();
ret->areaName = source["area"].String();
ret->group = -1;
ret->townID = town.typeID;
town.clientInfo.structures[ret->ID] = ret;
}
void CTownHandler::loadStructures(CTown &town, const JsonNode & source)
{
BOOST_FOREACH(const JsonNode &node, source["structures"].Vector())
{
loadStructure(town, node);
}
// Read buildings blit order for that city
int itr = 1;
BOOST_FOREACH(const JsonNode &node, source["blit_order"].Vector())
{
int buildingID = node.Float();
/* Find the building and set its order. */
auto i2 = town.clientInfo.structures.find(buildingID);
if (i2 != (town.clientInfo.structures.end()))
i2->second->pos.z = itr++;
}
// Iterate for each group for that city
int groupID = 0;
BOOST_FOREACH(const JsonNode &group, source["groups"].Vector())
{
groupID++;
// Iterate for each bulding value in the group
BOOST_FOREACH(const JsonNode &value, group.Vector())
{
auto buildingIter = town.clientInfo.structures.find(value.Float());
if (buildingIter != town.clientInfo.structures.end())
{
buildingIter->second->group = groupID;
}
}
}
}
void CTownHandler::loadTownHall(CTown &town, const JsonNode & source)
{
BOOST_FOREACH(const JsonNode &row, source.Vector())
{
std::vector< std::vector<int> > hallRow;
BOOST_FOREACH(const JsonNode &box, row.Vector())
{
std::vector<int> hallBox;
BOOST_FOREACH(const JsonNode &value, box.Vector())
{
hallBox.push_back(value.Float());
}
hallRow.push_back(hallBox);
}
town.clientInfo.hallSlots.push_back(hallRow);
}
}
void CTownHandler::loadTown(std::vector<CTown> &towns, const JsonNode & source)
{
towns.push_back(CTown());
CTown & town = towns.back();
//TODO: allow loading name and names vector from json and from h3 txt's
town.typeID = towns.size() - 1;
town.bonus = town.typeID;
if (town.bonus==8)
town.bonus=3;
town.clientInfo.hallBackground = source["hallBackground"].String();
town.mageLevel = source["mage_guild"].Float();
town.primaryRes = source["primary_resource"].Float();
town.warMachine = source["war_machine"].Float();
// Horde building creature level
BOOST_FOREACH(const JsonNode &node, source["horde"].Vector())
{
town.hordeLvl[town.hordeLvl.size()] = node.Float();
}
BOOST_FOREACH(const JsonNode &list, source["creatures"].Vector())
{
std::vector<si32> level;
BOOST_FOREACH(const JsonNode &node, list.Vector())
{
level.push_back(node.Float());
}
town.creatures.push_back(level);
}
loadTownHall(town, source["hallSlots"]);
loadBuildings(town, source["buildings"]);
loadStructures(town, source);
}
void CTownHandler::loadTowns(std::vector<CTown> &towns, const JsonNode & source)
{
BOOST_FOREACH(const JsonNode & node, source.Vector())
{
loadTown(towns, node);
}
// ensure that correct number of town have been loaded. Safe to remove
assert(towns.size() == GameConstants::F_NUMBER);
}
void CTownHandler::load()
{
JsonNode buildingsConf(ResourceID("config/buildings.json"));
JsonNode legacyConfig;
loadLegacyData(legacyConfig);
// semi-manually merge legacy config with towns json
// legacy config have only one item: town buildings stored in 2d vector
size_t townsToMerge = std::min(buildingsConf["towns"].Vector().size(), legacyConfig.Vector().size());
for (size_t i=0; i< townsToMerge; i++)
{
JsonNode & buildings = buildingsConf["towns"].Vector()[i]["buildings"];
BOOST_FOREACH(JsonNode & building, buildings.Vector())
{
if (vstd::contains(building.Struct(), "id"))
{
JsonNode & legacyBuilding = legacyConfig.Vector()[i].Vector()[building["id"].Float()];
if (!legacyBuilding.isNull())
JsonNode::merge(building, legacyBuilding);
}
}
}
loadTowns(towns, buildingsConf["towns"]);
}

View File

@ -1,6 +1,7 @@
#pragma once
#include "ConstTransitivePtr.h"
#include "ResourceSet.h"
#include "int3.h"
/*
@ -13,66 +14,137 @@
*
*/
class CBuilding;
class CSpell;
class CHero;
class CGTownInstance;
class DLL_LINKAGE CTown
class CLegacyConfigParser;
class JsonNode;
/// a typical building encountered in every castle ;]
/// this is structure available to both client and server
/// contains all mechanics-related data about town structures
class DLL_LINKAGE CBuilding
{
std::string name; //name of type
std::string name;
std::string description;
public:
si32 tid, bid; //town ID and structure ID
TResources resources;
std::set<int> requirements; //set of required buildings
std::vector<std::string> names; //names of the town instances
std::vector<std::vector<int> > creatures; //level (from 0) -> list of creatures on this tier
std::map<int,int> hordeLvl; //[0] - first horde building creature level; [1] - second horde building (-1 if not present)
ui32 mageLevel; //max available mage guild level
int bonus; //pic number
ui16 primaryRes, warMachine;
ui8 typeID;
const std::vector<std::string> & Names() const;
const std::string &Name() const;
void Name(const std::string & val) { name = val; }
const std::string &Description() const;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & names & creatures & hordeLvl & mageLevel & bonus
& primaryRes & warMachine & typeID;
h & tid & bid & resources & name & description & requirements;
}
friend class CTownHandler;
};
struct DLL_LINKAGE Structure
/// This is structure used only by client
/// Consists of all gui-related data about town structures
/// Should be mode from lib to client
struct DLL_LINKAGE CStructure
{
int ID;
int3 pos;
std::string defName, borderName, areaName, name;
std::string defName, borderName, areaName;
int townID, group;
bool operator<(const Structure & p2) const
bool operator<(const CStructure & p2) const
{
if(pos.z != p2.pos.z)
return (pos.z) < (p2.pos.z);
else
return (ID) < (p2.ID);
}
template <typename Handler> void serialize(Handler &h, const int version)
{
h & ID & pos & defName & borderName & areaName & townID & group;
}
};
class DLL_LINKAGE CTown
{
std::string name; //name of type
std::vector<std::string> names; //names of the town instances
public:
ui32 typeID;
/// level -> list of creatures on this tier
/// TODO: replace with pointers to CCreature?
std::vector<std::vector<si32> > creatures;
bmap<int, ConstTransitivePtr<CBuilding> > buildings;
// should be removed at least from configs in favour of auto-detection
std::map<int,int> hordeLvl; //[0] - first horde building creature level; [1] - second horde building (-1 if not present)
ui32 mageLevel; //max available mage guild level
int bonus; //pic number
ui16 primaryRes, warMachine;
// Client-only data. Should be moved away from lib
struct ClientInfo
{
std::string hallBackground;
std::vector< std::vector< std::vector<int> > > hallSlots; /// vector[row][column] = list of buildings in this slot
bmap<int, ConstTransitivePtr<CStructure> > structures;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & hallBackground & hallSlots & structures;
}
} clientInfo;
const std::vector<std::string> & Names() const;
const std::string & Name() const;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & name & names & typeID & creatures & buildings & hordeLvl & mageLevel & bonus
& primaryRes & warMachine & clientInfo;
}
friend class CTownHandler;
};
class DLL_LINKAGE CTownHandler
{
/// loads CBuilding's into town
void loadBuilding(CTown &town, const JsonNode & source);
void loadBuildings(CTown &town, const JsonNode & source);
/// loads CStructure's into town
void loadStructure(CTown &town, const JsonNode & source);
void loadStructures(CTown &town, const JsonNode & source);
/// loads town hall vector (hallSlots)
void loadTownHall(CTown &town, const JsonNode & source);
/// load town and insert it into towns vector
void loadTown(std::vector<CTown> &towns, const JsonNode & source);
/// main loading function, accepts merged JSON source and add all entries from it into game
/// all entries in JSON should be checked for validness before using this function
void loadTowns(std::vector<CTown> &towns, const JsonNode & source);
/// load all available data from h3 txt(s) into json structure using format similar to vcmi configs
/// returns 2d array [townID] [buildID] of buildings
void loadLegacyData(JsonNode & dest);
public:
std::vector<CTown> towns;
std::vector<std::map<int, Structure*> > structures; // <town ID, <structure ID, structure>>
CTownHandler(); //c-tor
~CTownHandler(); //d-tor
void loadStructures();
CTownHandler(); //c-tor, set pointer in VLC to this
/// "entry point" for towns loading.
/// reads legacy txt's from H3 + vcmi json, merges them
/// and loads resulting structure to game using loadTowns method
void load();
template <typename Handler> void serialize(Handler &h, const int version)
{
h & towns;
if(!h.saving)
loadStructures();
}
};

View File

@ -547,7 +547,7 @@ int CGameInfoCallback::canBuildStructure( const CGTownInstance *t, int ID )
if(t->builded >= GameConstants::MAX_BUILDING_PER_TURN)
ret = EBuildingState::CANT_BUILD_TODAY; //building limit
CBuilding * pom = VLC->buildh->buildings[t->subID][ID];
CBuilding * pom = t->town->buildings[ID];
if(!pom)
return EBuildingState::BUILDING_ERROR;
@ -603,7 +603,7 @@ std::set<int> CGameInfoCallback::getBuildingRequiments( const CGTownInstance *t,
std::set<int> used;
used.insert(ID);
std::set<int> reqs = VLC->buildh->buildings[t->subID][ID]->requirements;
std::set<int> reqs = t->town->buildings[ID]->requirements;
while(true)
{
@ -614,8 +614,8 @@ std::set<int> CGameInfoCallback::getBuildingRequiments( const CGTownInstance *t,
{
used.insert(*i);
for(
std::set<int>::iterator j=VLC->buildh->buildings[t->subID][*i]->requirements.begin();
j!= VLC->buildh->buildings[t->subID][*i]->requirements.end();
std::set<int>::iterator j= t->town->buildings[*i]->requirements.begin();
j!= t->town->buildings[*i]->requirements.end();
j++)
{
reqs.insert(*j);//creating full list of requirements

View File

@ -236,6 +236,38 @@ const JsonNode & JsonNode::operator[](std::string child) const
return it->second;
return nullNode;
}
////////////////////////////////////////////////////////////////////////////////
void JsonNode::merge(JsonNode & dest, JsonNode & source)
{
switch (source.getType())
{
break; case DATA_NULL: dest.setType(DATA_NULL);
break; case DATA_BOOL: std::swap(dest.Bool(), source.Bool());
break; case DATA_FLOAT: std::swap(dest.Float(), source.Float());
break; case DATA_STRING: std::swap(dest.String(), source.String());
break; case DATA_VECTOR:
{
//reserve place and *move* data from source to dest
source.Vector().reserve(source.Vector().size() + dest.Vector().size());
std::move(source.Vector().begin(), source.Vector().end(),
std::back_inserter(dest.Vector()));
}
break; case DATA_STRUCT:
{
//recursively merge all entries from struct
BOOST_FOREACH(auto & node, source.Struct())
merge(dest[node.first], node.second);
}
}
}
void JsonNode::mergeCopy(JsonNode & dest, JsonNode source)
{
// uses copy created in stack to safely merge two nodes
merge(dest, source);
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -94,6 +94,17 @@ public:
//error value for const operator[]
static const JsonNode nullNode;
/// recursivly merges source into dest, replacing identical fields
/// struct : recursively calls this function
/// arrays : append array in dest with data from source
/// values : value in source will replace value in dest
/// null : if value in source is present but set to null it will delete entry in dest
/// this function will destroy data in source
static void merge(JsonNode & dest, JsonNode & source);
/// this function will preserve data stored in source by creating copy
static void mergeCopy(JsonNode & dest, JsonNode source);
};
class JsonWriter

View File

@ -1,12 +1,26 @@
#include "StdInc.h"
#include "ResourceSet.h"
#include "GameConstants.h"
#include "JsonNode.h"
Res::ResourceSet::ResourceSet()
{
resize(GameConstants::RESOURCE_QUANTITY, 0);
}
Res::ResourceSet::ResourceSet(const JsonNode & node)
{
resize(GameConstants::RESOURCE_QUANTITY, 0);
at(0) = node["wood"].Float();
at(1) = node["mercury"].Float();
at(2) = node["ore"].Float();
at(3) = node["sulfur"].Float();
at(4) = node["crystal"].Float();
at(5) = node["gems"].Float();
at(6) = node["gold"].Float();
at(7) = node["mithril"].Float();
}
bool Res::ResourceSet::nonZero() const
{
for(int i = 0; i < size(); i++)

View File

@ -3,6 +3,8 @@
typedef si32 TResource;
typedef si64 TResourceCap; //to avoid overflow when adding integers. Signed values are easier to control.
class JsonNode;
namespace Res
{
class ResourceSet;
@ -18,6 +20,8 @@ namespace Res
{
public:
DLL_LINKAGE ResourceSet();
// read resources set from json. Format example: { "gold": 500, "wood":5 }
DLL_LINKAGE ResourceSet(const JsonNode & node);
#define scalarOperator(OPSIGN) \

View File

@ -87,7 +87,7 @@ void LibClasses::init()
tlog0<<"\tCreature handler: "<<pomtime.getDiff()<<std::endl;
townh = new CTownHandler;
townh->loadStructures();
townh->load();
tlog0<<"\tTown handler: "<<pomtime.getDiff()<<std::endl;
objh = new CObjectHandler;
@ -98,10 +98,6 @@ void LibClasses::init()
dobjinfo->load();
tlog0<<"\tDef information handler: "<<pomtime.getDiff()<<std::endl;
buildh = new CBuildingHandler;
buildh->loadBuildings();
tlog0<<"\tBuilding handler: "<<pomtime.getDiff()<<std::endl;
spellh = new CSpellHandler;
spellh->loadSpells();
tlog0<<"\tSpell handler: "<<pomtime.getDiff()<<std::endl;
@ -118,7 +114,6 @@ void LibClasses::clear()
delete townh;
delete objh;
delete dobjinfo;
delete buildh;
delete spellh;
delete modh;
makeNull();
@ -133,7 +128,6 @@ void LibClasses::makeNull()
townh = NULL;
objh = NULL;
dobjinfo = NULL;
buildh = NULL;
spellh = NULL;
modh = NULL;
}

View File

@ -30,7 +30,6 @@ public:
CHeroHandler * heroh;
CCreatureHandler * creh;
CSpellHandler * spellh;
CBuildingHandler * buildh;
CObjectHandler * objh;
CDefObjInfoHandler * dobjinfo;
CTownHandler * townh;
@ -48,7 +47,7 @@ public:
void callWhenDeserializing(); //should be called only by serialize !!!
template <typename Handler> void serialize(Handler &h, const int version)
{
h & heroh & arth & creh & townh & objh & dobjinfo & buildh & spellh & modh & IS_AI_ENABLED;;
h & heroh & arth & creh & townh & objh & dobjinfo & spellh & modh & IS_AI_ENABLED;;
if(!h.saving)
{
callWhenDeserializing();

View File

@ -2417,7 +2417,7 @@ bool CGameHandler::disbandCreature( si32 id, ui8 pos )
bool CGameHandler::buildStructure( si32 tid, si32 bid, bool force /*=false*/ )
{
CGTownInstance * t = static_cast<CGTownInstance*>(gs->map->objects[tid].get());
CBuilding * b = VLC->buildh->buildings[t->subID][bid];
CBuilding * b = t->town->buildings[bid];
if(!force)
{
@ -3729,7 +3729,7 @@ void CGameHandler::playerMessage( ui8 player, const std::string &message )
CGTownInstance *town = gs->getTown(gs->getPlayer(player)->currentSelection);
if (town)
{
BOOST_FOREACH (CBuildingHandler::TBuildingsMap::value_type &build, VLC->buildh->buildings[town->subID])
BOOST_FOREACH (auto & build, town->town->buildings)
{
if (!vstd::contains(town->builtBuildings, build.first)
&& !build.second->Name().empty())