mirror of
https://github.com/vcmi/vcmi.git
synced 2025-04-11 11:31:52 +02:00
Next part of town configuration:
- town screen is mostly implemented, has some minor issues - factions are now separate from towns, neutrals have faction with id=9 - more constants to GameConstants: town-specific buildings, strings for terrains and resources - replaced most access to builtBuildings with isBuilt() method - replaced id's with enums for town subtype and buildings id's
This commit is contained in:
parent
44cc848edc
commit
0ca9f64573
AI/VCAI
CCallback.cppclient
AdventureMapClasses.cppCAdvmapInterface.cppCCastleInterface.cppCCastleInterface.hCKingdomInterface.cppCMusicHandler.cppGUIClasses.cppGraphics.cppGraphics.hNetPacksClient.cpp
config
buildings.jsoncreature_backgrounds.jsoncreatures.jsondefaultMods.jsonterrains.jsontown_pictures.json
lib
BattleState.cppCBattleCallback.cppCCreatureHandler.cppCGameState.cppCHeroHandler.cppCHeroHandler.hCModHandler.cppCModHandler.hCObjectHandler.cppCObjectHandler.hCTownHandler.cppCTownHandler.hGameConstants.hIGameCallback.cppJsonNode.cppResourceSet.cppmap.cpp
server
@ -1241,7 +1241,7 @@ bool VCAI::tryBuildStructure(const CGTownInstance * t, int building, unsigned in
|
|||||||
//erase all already built buildings
|
//erase all already built buildings
|
||||||
for (auto buildIter = toBuild.begin(); buildIter != toBuild.end();)
|
for (auto buildIter = toBuild.begin(); buildIter != toBuild.end();)
|
||||||
{
|
{
|
||||||
if (vstd::contains(t->builtBuildings, *buildIter))
|
if (t->hasBuilt(*buildIter))
|
||||||
toBuild.erase(buildIter++);
|
toBuild.erase(buildIter++);
|
||||||
else
|
else
|
||||||
buildIter++;
|
buildIter++;
|
||||||
@ -1991,7 +1991,7 @@ void VCAI::tryRealize(CGoal g)
|
|||||||
const CGTownInstance * VCAI::findTownWithTavern() const
|
const CGTownInstance * VCAI::findTownWithTavern() const
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(const CGTownInstance *t, cb->getTownsInfo())
|
BOOST_FOREACH(const CGTownInstance *t, cb->getTownsInfo())
|
||||||
if(vstd::contains(t->builtBuildings, EBuilding::TAVERN) && !t->visitingHero)
|
if(t->hasBuilt(EBuilding::TAVERN) && !t->visitingHero)
|
||||||
return t;
|
return t;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -165,17 +165,11 @@ bool CCallback::assembleArtifacts (const CGHeroInstance * hero, ui16 artifactSlo
|
|||||||
|
|
||||||
bool CCallback::buildBuilding(const CGTownInstance *town, si32 buildingID)
|
bool CCallback::buildBuilding(const CGTownInstance *town, si32 buildingID)
|
||||||
{
|
{
|
||||||
//CGTownInstance * t = const_cast<CGTownInstance *>(town);
|
|
||||||
|
|
||||||
if(town->tempOwner!=player)
|
if(town->tempOwner!=player)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(!canBuildStructure(town, buildingID))
|
if(!canBuildStructure(town, buildingID))
|
||||||
return false;
|
return false;
|
||||||
// const CBuilding *b = CGI->buildh->buildings[t->subID][buildingID];
|
|
||||||
// for(int i=0;i<b->resources.size();i++)
|
|
||||||
// if(b->resources[i] > gs->players[player].resources[i])
|
|
||||||
// return false; //lack of resources
|
|
||||||
|
|
||||||
BuildStructure pack(town->id,buildingID);
|
BuildStructure pack(town->id,buildingID);
|
||||||
sendRequest(&pack);
|
sendRequest(&pack);
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "../lib/JsonNode.h"
|
#include "../lib/JsonNode.h"
|
||||||
#include "../lib/Filesystem/CResourceLoader.h"
|
#include "../lib/Filesystem/CResourceLoader.h"
|
||||||
#include "../lib/map.h"
|
#include "../lib/map.h"
|
||||||
|
#include "../lib/CModHandler.h"
|
||||||
#include "../lib/CObjectHandler.h"
|
#include "../lib/CObjectHandler.h"
|
||||||
#include "../lib/CGameState.h"
|
#include "../lib/CGameState.h"
|
||||||
#include "../lib/CGeneralTextHandler.h"
|
#include "../lib/CGeneralTextHandler.h"
|
||||||
@ -294,7 +295,7 @@ void CTownList::CTownItem::update()
|
|||||||
if (!town->hasFort())
|
if (!town->hasFort())
|
||||||
iconIndex += GameConstants::F_NUMBER*2;
|
iconIndex += GameConstants::F_NUMBER*2;
|
||||||
|
|
||||||
if(town->builded >= GameConstants::MAX_BUILDING_PER_TURN)
|
if(town->builded >= CGI->modh->settings.MAX_BUILDING_PER_TURN)
|
||||||
iconIndex++;
|
iconIndex++;
|
||||||
|
|
||||||
picture->setFrame(iconIndex + 2);
|
picture->setFrame(iconIndex + 2);
|
||||||
|
@ -760,6 +760,7 @@ void CAdvMapInt::show(SDL_Surface * to)
|
|||||||
void CAdvMapInt::selectionChanged()
|
void CAdvMapInt::selectionChanged()
|
||||||
{
|
{
|
||||||
const CGTownInstance *to = LOCPLINT->towns[townList.getSelectedIndex()];
|
const CGTownInstance *to = LOCPLINT->towns[townList.getSelectedIndex()];
|
||||||
|
if (selection != to)
|
||||||
select(to);
|
select(to);
|
||||||
}
|
}
|
||||||
void CAdvMapInt::centerOn(int3 on)
|
void CAdvMapInt::centerOn(int3 on)
|
||||||
@ -877,7 +878,7 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key)
|
|||||||
const CGTownInstance *townWithMarket = NULL;
|
const CGTownInstance *townWithMarket = NULL;
|
||||||
BOOST_FOREACH(const CGTownInstance *t, LOCPLINT->cb->getTownsInfo())
|
BOOST_FOREACH(const CGTownInstance *t, LOCPLINT->cb->getTownsInfo())
|
||||||
{
|
{
|
||||||
if(vstd::contains(t->builtBuildings, 14))
|
if(t->hasBuilt(EBuilding::MARKETPLACE))
|
||||||
{
|
{
|
||||||
townWithMarket = t;
|
townWithMarket = t;
|
||||||
break;
|
break;
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "../lib/CBuildingHandler.h"
|
#include "../lib/CBuildingHandler.h"
|
||||||
#include "../lib/CCreatureHandler.h"
|
#include "../lib/CCreatureHandler.h"
|
||||||
#include "../lib/CGeneralTextHandler.h"
|
#include "../lib/CGeneralTextHandler.h"
|
||||||
|
#include "../lib/CModHandler.h"
|
||||||
#include "../lib/CObjectHandler.h"
|
#include "../lib/CObjectHandler.h"
|
||||||
#include "../lib/CSpellHandler.h"
|
#include "../lib/CSpellHandler.h"
|
||||||
#include "../lib/CTownHandler.h"
|
#include "../lib/CTownHandler.h"
|
||||||
@ -36,19 +37,6 @@ using namespace boost::assign;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int hordeToDwellingID(int bid)//helper, converts horde buiding ID into corresponding dwelling ID
|
|
||||||
{
|
|
||||||
const CGTownInstance * t = LOCPLINT->castleInt->town;
|
|
||||||
switch (bid)
|
|
||||||
{
|
|
||||||
case 18: return t->town->hordeLvl[0] + 30;
|
|
||||||
case 19: return t->town->hordeLvl[0] + 37;
|
|
||||||
case 24: return t->town->hordeLvl[1] + 30;
|
|
||||||
case 25: return t->town->hordeLvl[1] + 37;
|
|
||||||
default: return bid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CBuildingRect::CBuildingRect(CCastleBuildings * Par, const CGTownInstance *Town, const CStructure *Str)
|
CBuildingRect::CBuildingRect(CCastleBuildings * Par, const CGTownInstance *Town, const CStructure *Str)
|
||||||
:CShowableAnim(0, 0, Str->defName, CShowableAnim::BASE | CShowableAnim::USE_RLE),
|
:CShowableAnim(0, 0, Str->defName, CShowableAnim::BASE | CShowableAnim::USE_RLE),
|
||||||
parent(Par),
|
parent(Par),
|
||||||
@ -80,10 +68,8 @@ CBuildingRect::~CBuildingRect()
|
|||||||
|
|
||||||
bool CBuildingRect::operator<(const CBuildingRect & p2) const
|
bool CBuildingRect::operator<(const CBuildingRect & p2) const
|
||||||
{
|
{
|
||||||
if(str->pos.z != p2.str->pos.z)
|
|
||||||
return (str->pos.z) < (p2.str->pos.z);
|
return (str->pos.z) < (p2.str->pos.z);
|
||||||
else
|
|
||||||
return (str->ID) < (p2.str->ID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBuildingRect::hover(bool on)
|
void CBuildingRect::hover(bool on)
|
||||||
@ -108,18 +94,18 @@ void CBuildingRect::hover(bool on)
|
|||||||
|
|
||||||
void CBuildingRect::clickLeft(tribool down, bool previousState)
|
void CBuildingRect::clickLeft(tribool down, bool previousState)
|
||||||
{
|
{
|
||||||
if( previousState && !down && area && (parent->selectedBuilding==this) )
|
if( previousState && !down && area && (parent->selectedBuilding==this) && str->building )
|
||||||
if (!CSDL_Ext::isTransparent(area, GH.current->motion.x-pos.x, GH.current->motion.y-pos.y) ) //inside building image
|
if (!CSDL_Ext::isTransparent(area, GH.current->motion.x-pos.x, GH.current->motion.y-pos.y) ) //inside building image
|
||||||
parent->buildingClicked(str->ID);
|
parent->buildingClicked(str->building->bid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBuildingRect::clickRight(tribool down, bool previousState)
|
void CBuildingRect::clickRight(tribool down, bool previousState)
|
||||||
{
|
{
|
||||||
if((!area) || (!((bool)down)) || (this!=parent->selectedBuilding))
|
if((!area) || (!((bool)down)) || (this!=parent->selectedBuilding) || str->building == nullptr)
|
||||||
return;
|
return;
|
||||||
if( !CSDL_Ext::isTransparent(area, GH.current->motion.x-pos.x, GH.current->motion.y-pos.y) ) //inside building image
|
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);
|
int bid = str->building->bid;
|
||||||
const CBuilding *bld = town->town->buildings[bid];
|
const CBuilding *bld = town->town->buildings[bid];
|
||||||
if (bid < EBuilding::DWELL_FIRST)
|
if (bid < EBuilding::DWELL_FIRST)
|
||||||
{
|
{
|
||||||
@ -208,13 +194,16 @@ void CBuildingRect::showAll(SDL_Surface * to)
|
|||||||
blitAtLoc(border,0,0,to);
|
blitAtLoc(border,0,0,to);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getBuildingSubtitle(int tid, int bid)//hover text for building
|
std::string getBuildingSubtitle(const CStructure * structure)//hover text for building
|
||||||
{
|
{
|
||||||
const CGTownInstance * t = LOCPLINT->castleInt->town;
|
const CGTownInstance * t = LOCPLINT->castleInt->town;
|
||||||
bid = hordeToDwellingID(bid);
|
if (!structure->building)
|
||||||
|
return "";
|
||||||
|
|
||||||
|
int bid = structure->building->bid;
|
||||||
|
|
||||||
if (bid<30)//non-dwellings - only buiding name
|
if (bid<30)//non-dwellings - only buiding name
|
||||||
return CGI->townh->towns[tid].buildings[bid]->Name();
|
return t->town->buildings[structure->building->bid]->Name();
|
||||||
else//dwellings - recruit %creature%
|
else//dwellings - recruit %creature%
|
||||||
{
|
{
|
||||||
int creaID = t->creatures[(bid-30)%GameConstants::CREATURES_PER_TOWN].second.back();//taking last of available creatures
|
int creaID = t->creatures[(bid-30)%GameConstants::CREATURES_PER_TOWN].second.back();//taking last of available creatures
|
||||||
@ -240,7 +229,7 @@ void CBuildingRect::mouseMoved (const SDL_MouseMotionEvent & sEvent)
|
|||||||
|| (*parent->selectedBuilding)<(*this)) //or we are on top
|
|| (*parent->selectedBuilding)<(*this)) //or we are on top
|
||||||
{
|
{
|
||||||
parent->selectedBuilding = this;
|
parent->selectedBuilding = this;
|
||||||
GH.statusbar->print(getBuildingSubtitle(str->townID, str->ID));
|
GH.statusbar->print(getBuildingSubtitle(str));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -453,177 +442,113 @@ CCastleBuildings::CCastleBuildings(const CGTownInstance* Town):
|
|||||||
{
|
{
|
||||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||||
|
|
||||||
background = new CPicture(graphics->townBgs[town->subID]);
|
background = new CPicture(town->town->clientInfo.townBackground);
|
||||||
pos.w = background->pos.w;
|
pos.w = background->pos.w;
|
||||||
pos.h = background->pos.h;
|
pos.h = background->pos.h;
|
||||||
|
|
||||||
|
recreate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCastleBuildings::recreate()
|
||||||
|
{
|
||||||
|
selectedBuilding = nullptr;
|
||||||
|
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||||
|
//clear existing buildings
|
||||||
|
BOOST_FOREACH(auto build, buildings)
|
||||||
|
delete build;
|
||||||
|
buildings.clear();
|
||||||
|
groups.clear();
|
||||||
|
|
||||||
//Generate buildings list
|
//Generate buildings list
|
||||||
for (std::set<si32>::const_iterator building=town->builtBuildings.begin(); building!=town->builtBuildings.end(); building++)
|
|
||||||
{
|
|
||||||
auto structure = town->town->clientInfo.structures.find(*building);
|
|
||||||
|
|
||||||
if(structure != town->town->clientInfo.structures.end() && structure->second)
|
auto buildingsCopy = town->builtBuildings;// a bit modified copy of built buildings
|
||||||
{
|
|
||||||
if(structure->second->group<0) // no group - just add it
|
|
||||||
buildings.push_back(new CBuildingRect(this, town, structure->second));
|
|
||||||
else // generate list for each group
|
|
||||||
groups[structure->second->group].push_back(structure->second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CStructure * shipyard = town->town->clientInfo.structures[6];
|
if(vstd::contains(town->builtBuildings, EBuilding::SHIPYARD))
|
||||||
//ship in shipyard
|
|
||||||
if(shipyard && vstd::contains(groups, shipyard->group))
|
|
||||||
{
|
{
|
||||||
std::vector <const CGObjectInstance *> vobjs = LOCPLINT->cb->getVisitableObjs(town->bestLocation());
|
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)
|
//there is visitable obj at shipyard output tile and it's a boat or hero (on boat)
|
||||||
|
if(!vobjs.empty() && (vobjs.front()->ID == 8 || vobjs.front()->ID == GameConstants::HEROI_TYPE))
|
||||||
{
|
{
|
||||||
groups[shipyard->group].push_back(town->town->clientInfo.structures[20]);
|
buildingsCopy.insert(EBuilding::SHIP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//Create building for each group
|
|
||||||
for (std::map< int, std::vector<const CStructure*> >::iterator group = groups.begin(); group != groups.end(); group++)
|
BOOST_FOREACH(const CStructure * structure, town->town->clientInfo.structures)
|
||||||
{
|
{
|
||||||
std::sort(group->second.begin(), group->second.end(), structSorter);
|
if (!structure->building)
|
||||||
buildings.push_back(new CBuildingRect(this, town, group->second.back()));
|
{
|
||||||
|
buildings.push_back(new CBuildingRect(this, town, structure));
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
std::sort(buildings.begin(),buildings.end(),buildSorter);
|
if (vstd::contains(buildingsCopy, structure->building->bid))
|
||||||
checkRules();
|
{
|
||||||
|
groups[structure->building->getBase()].push_back(structure);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_FOREACH(auto & entry, groups)
|
||||||
|
{
|
||||||
|
const CBuilding * build = town->town->buildings[entry.first];
|
||||||
|
|
||||||
|
const CStructure * toAdd = *boost::max_element(entry.second, [=](const CStructure * a, const CStructure * b)
|
||||||
|
{
|
||||||
|
return build->getDistance(a->building->bid)
|
||||||
|
< build->getDistance(b->building->bid);
|
||||||
|
});
|
||||||
|
|
||||||
|
buildings.push_back(new CBuildingRect(this, town, toAdd));
|
||||||
|
}
|
||||||
|
boost::sort(buildings, [] (const CBuildingRect * a, const CBuildingRect * b)
|
||||||
|
{
|
||||||
|
return *a < *b;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
CCastleBuildings::~CCastleBuildings()
|
CCastleBuildings::~CCastleBuildings()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCastleBuildings::checkRules()
|
void CCastleBuildings::addBuilding(int building)
|
||||||
{
|
{
|
||||||
//if town tonwID have building toCheck
|
//FIXME: implement faster method without complete recreation of town
|
||||||
//then set animation of building buildID to firstA..lastA
|
int base = town->town->buildings[building]->getBase();
|
||||||
//else set to firstB..lastB
|
|
||||||
struct AnimRule
|
|
||||||
{
|
|
||||||
int townID, buildID;
|
|
||||||
int toCheck;
|
|
||||||
size_t firstA, lastA;
|
|
||||||
size_t firstB, lastB;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const AnimRule animRule[2] =
|
recreate();
|
||||||
{
|
|
||||||
{5, 21, 4, 10, size_t(-1), 0, 10}, //Mana Vortex, Dungeon
|
|
||||||
{0, 6, 8, 1, size_t(-1), 0, 1} //Shipyard, Castle
|
|
||||||
};
|
|
||||||
|
|
||||||
for (size_t i=0; i<2; i++)
|
auto & structures = groups[base];
|
||||||
{
|
|
||||||
if ( town->subID != animRule[i].townID ) //wrong town
|
|
||||||
continue;
|
|
||||||
|
|
||||||
int buildingID = animRule[i].buildID;
|
|
||||||
//check if this building have been upgraded (Ship is upgrade of Shipyard)
|
|
||||||
int groupID = town->town->clientInfo.structures[animRule[i].buildID]->group;
|
|
||||||
if (groupID != -1)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_FOREACH(CBuildingRect * rect, buildings)
|
BOOST_FOREACH(CBuildingRect * rect, buildings)
|
||||||
{
|
{
|
||||||
if ( rect->str->ID == buildingID )
|
if (vstd::contains(structures, rect->str))
|
||||||
{
|
{
|
||||||
if (vstd::contains(town->builtBuildings, animRule[i].toCheck))
|
//reset animation
|
||||||
rect->set(0,animRule[i].firstA, animRule[i].lastA);
|
if (structures.size() == 1)
|
||||||
|
rect->stateCounter = 0; // transparency -> fully visible stage
|
||||||
else
|
else
|
||||||
rect->set(0,animRule[i].firstB, animRule[i].lastB);
|
rect->stateCounter = 16; // already in fully visible stage
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void CCastleBuildings::addBuilding(int building)
|
|
||||||
{
|
|
||||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
|
||||||
auto structure = town->town->clientInfo.structures.find(building);
|
|
||||||
|
|
||||||
if(structure != town->town->clientInfo.structures.end()) //we have info about that structure
|
|
||||||
{
|
|
||||||
if(structure->second->group<0) //no group - just add it
|
|
||||||
{
|
|
||||||
buildings.push_back(new CBuildingRect(this, town, structure->second));
|
|
||||||
buildings.back()->stateCounter = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//find last building in this group and replace it with new building if needed
|
|
||||||
groups[structure->second->group].push_back(structure->second);
|
|
||||||
int newBuilding = groups[structure->second->group].back()->ID;
|
|
||||||
if (newBuilding == building)
|
|
||||||
{
|
|
||||||
for (std::vector< CBuildingRect* >::iterator it=buildings.begin() ; it !=buildings.end(); it++ )
|
|
||||||
{
|
|
||||||
if ((*it)->str->ID == newBuilding)
|
|
||||||
{
|
|
||||||
delete *it;
|
|
||||||
buildings.erase(it);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buildings.push_back(new CBuildingRect(this, town, structure->second));
|
|
||||||
buildings.back()->stateCounter = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::sort(buildings.begin(),buildings.end(),buildSorter);
|
|
||||||
checkRules();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CCastleBuildings::removeBuilding(int building)
|
void CCastleBuildings::removeBuilding(int building)
|
||||||
{
|
{
|
||||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
//FIXME: implement faster method without complete recreation of town
|
||||||
auto structure = town->town->clientInfo.structures.find(building);
|
recreate();
|
||||||
|
|
||||||
if(structure != town->town->clientInfo.structures.end()) //we have info about that structure
|
|
||||||
{
|
|
||||||
if(structure->second->group<0) //no group - just add it
|
|
||||||
{
|
|
||||||
for (std::vector< CBuildingRect* >::iterator it=buildings.begin() ; it !=buildings.end(); it++ )
|
|
||||||
{
|
|
||||||
if ((*it)->str->ID == building)
|
|
||||||
{
|
|
||||||
delete *it;
|
|
||||||
buildings.erase(it);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
groups[structure->second->group].pop_back();
|
|
||||||
delete buildings[building];
|
|
||||||
if (!groups[structure->second->group].empty())
|
|
||||||
buildings.push_back(new CBuildingRect(this, town, structure->second));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::sort(buildings.begin(),buildings.end(),buildSorter);
|
|
||||||
checkRules();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCastleBuildings::show(SDL_Surface * to)
|
void CCastleBuildings::show(SDL_Surface * to)
|
||||||
{
|
{
|
||||||
CIntObject::show(to);
|
CIntObject::show(to);
|
||||||
for (std::vector< CBuildingRect* >::const_iterator it=buildings.begin() ; it !=buildings.end(); it++ )
|
BOOST_FOREACH(CBuildingRect * str, buildings)
|
||||||
(*it)->show(to);
|
str->show(to);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCastleBuildings::showAll(SDL_Surface * to)
|
void CCastleBuildings::showAll(SDL_Surface * to)
|
||||||
{
|
{
|
||||||
CIntObject::showAll(to);
|
CIntObject::showAll(to);
|
||||||
for (std::vector< CBuildingRect* >::const_iterator it=buildings.begin() ; it !=buildings.end(); it++ )
|
BOOST_FOREACH(CBuildingRect * str, buildings)
|
||||||
(*it)->showAll(to);
|
str->showAll(to);
|
||||||
}
|
}
|
||||||
|
|
||||||
const CGHeroInstance* CCastleBuildings::getHero()
|
const CGHeroInstance* CCastleBuildings::getHero()
|
||||||
@ -638,7 +563,6 @@ const CGHeroInstance* CCastleBuildings::getHero()
|
|||||||
void CCastleBuildings::buildingClicked(int building)
|
void CCastleBuildings::buildingClicked(int building)
|
||||||
{
|
{
|
||||||
tlog5<<"You've clicked on "<<building<<std::endl;
|
tlog5<<"You've clicked on "<<building<<std::endl;
|
||||||
building = hordeToDwellingID(building);
|
|
||||||
const CBuilding *b = town->town->buildings.find(building)->second;
|
const CBuilding *b = town->town->buildings.find(building)->second;
|
||||||
|
|
||||||
if(building >= EBuilding::DWELL_FIRST)
|
if(building >= EBuilding::DWELL_FIRST)
|
||||||
@ -689,11 +613,13 @@ void CCastleBuildings::buildingClicked(int building)
|
|||||||
case EBuilding::SPECIAL_1:
|
case EBuilding::SPECIAL_1:
|
||||||
switch(town->subID)
|
switch(town->subID)
|
||||||
{
|
{
|
||||||
case 1://Mystic Pond
|
case ETownType::RAMPART://Mystic Pond
|
||||||
enterFountain(building);
|
enterFountain(building);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: case 5: case 8://Artifact Merchant
|
case ETownType::TOWER:
|
||||||
|
case ETownType::DUNGEON://Artifact Merchant
|
||||||
|
case ETownType::CONFLUX:
|
||||||
if(town->visitingHero)
|
if(town->visitingHero)
|
||||||
GH.pushInt(new CMarketplaceWindow(town, town->visitingHero, EMarketMode::RESOURCE_ARTIFACT));
|
GH.pushInt(new CMarketplaceWindow(town, town->visitingHero, EMarketMode::RESOURCE_ARTIFACT));
|
||||||
else
|
else
|
||||||
@ -713,18 +639,18 @@ void CCastleBuildings::buildingClicked(int building)
|
|||||||
case EBuilding::SPECIAL_2:
|
case EBuilding::SPECIAL_2:
|
||||||
switch(town->subID)
|
switch(town->subID)
|
||||||
{
|
{
|
||||||
case 1: //Fountain of Fortune
|
case ETownType::RAMPART: //Fountain of Fortune
|
||||||
enterFountain(building);
|
enterFountain(building);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 6: //Freelancer's Guild
|
case ETownType::STRONGHOLD: //Freelancer's Guild
|
||||||
if(getHero())
|
if(getHero())
|
||||||
GH.pushInt(new CMarketplaceWindow(town, getHero(), EMarketMode::CREATURE_RESOURCE));
|
GH.pushInt(new CMarketplaceWindow(town, getHero(), EMarketMode::CREATURE_RESOURCE));
|
||||||
else
|
else
|
||||||
LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[273]) % b->Name())); //Only visiting heroes may use the %s.
|
LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[273]) % b->Name())); //Only visiting heroes may use the %s.
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 8: //Magic University
|
case ETownType::CONFLUX: //Magic University
|
||||||
if (getHero())
|
if (getHero())
|
||||||
GH.pushInt(new CUniversityWindow(getHero(), town));
|
GH.pushInt(new CUniversityWindow(getHero(), town));
|
||||||
else
|
else
|
||||||
@ -740,26 +666,26 @@ void CCastleBuildings::buildingClicked(int building)
|
|||||||
case EBuilding::SPECIAL_3:
|
case EBuilding::SPECIAL_3:
|
||||||
switch(town->subID)
|
switch(town->subID)
|
||||||
{
|
{
|
||||||
case 0: //Brotherhood of sword
|
case ETownType::CASTLE: //Brotherhood of sword
|
||||||
LOCPLINT->showTavernWindow(town);
|
LOCPLINT->showTavernWindow(town);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: //Castle Gate
|
case ETownType::INFERNO: //Castle Gate
|
||||||
enterCastleGate();
|
enterCastleGate();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4: //Skeleton Transformer
|
case ETownType::NECROPOLIS: //Skeleton Transformer
|
||||||
GH.pushInt( new CTransformerWindow(getHero(), town) );
|
GH.pushInt( new CTransformerWindow(getHero(), town) );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5: //Portal of Summoning
|
case ETownType::DUNGEON: //Portal of Summoning
|
||||||
if (town->creatures[GameConstants::CREATURES_PER_TOWN].second.empty())//No creatures
|
if (town->creatures[GameConstants::CREATURES_PER_TOWN].second.empty())//No creatures
|
||||||
LOCPLINT->showInfoDialog(CGI->generaltexth->tcommands[30]);
|
LOCPLINT->showInfoDialog(CGI->generaltexth->tcommands[30]);
|
||||||
else
|
else
|
||||||
enterDwelling(GameConstants::CREATURES_PER_TOWN);
|
enterDwelling(GameConstants::CREATURES_PER_TOWN);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 6: //Ballista Yard
|
case ETownType::STRONGHOLD: //Ballista Yard
|
||||||
enterBlacksmith(4);
|
enterBlacksmith(4);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -810,12 +736,12 @@ void CCastleBuildings::enterCastleGate()
|
|||||||
{
|
{
|
||||||
const CGTownInstance *t = Towns[i];
|
const CGTownInstance *t = Towns[i];
|
||||||
if (t->id != this->town->id && t->visitingHero == NULL && //another town, empty and this is
|
if (t->id != this->town->id && t->visitingHero == NULL && //another town, empty and this is
|
||||||
t->subID == 3 && vstd::contains(t->builtBuildings, 22))//inferno with castle gate
|
t->hasBuilt(EBuilding::CASTLE_GATE, ETownType::INFERNO))
|
||||||
{
|
{
|
||||||
availableTowns.push_back(t->id);//add to the list
|
availableTowns.push_back(t->id);//add to the list
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CPicture *titlePic = new CPicture (LOCPLINT->castleInt->bicons->ourImages[22].bitmap, 0,0, false);//will be deleted by selection window
|
CPicture *titlePic = new CPicture (LOCPLINT->castleInt->bicons->ourImages[EBuilding::CASTLE_GATE].bitmap, 0,0, false);//will be deleted by selection window
|
||||||
GH.pushInt (new CObjectListWindow(availableTowns, titlePic, CGI->generaltexth->jktexts[40],
|
GH.pushInt (new CObjectListWindow(availableTowns, titlePic, CGI->generaltexth->jktexts[40],
|
||||||
CGI->generaltexth->jktexts[41], boost::bind (&CCastleInterface::castleTeleport, LOCPLINT->castleInt, _1)));
|
CGI->generaltexth->jktexts[41], boost::bind (&CCastleInterface::castleTeleport, LOCPLINT->castleInt, _1)));
|
||||||
}
|
}
|
||||||
@ -831,8 +757,10 @@ void CCastleBuildings::enterFountain(int building)
|
|||||||
std::vector<CComponent*> comps(1, new CComponent(CComponent::building,town->subID,building));
|
std::vector<CComponent*> comps(1, new CComponent(CComponent::building,town->subID,building));
|
||||||
|
|
||||||
std::string descr = town->town->buildings.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"+town->town->buildings.find(17)->second->Description();
|
if ( building == EBuilding::FOUNTAIN_OF_FORTUNE)
|
||||||
|
descr += "\n\n"+town->town->buildings.find(EBuilding::MYSTIC_POND)->second->Description();
|
||||||
|
|
||||||
if (town->bonusValue.first == 0)//fountain was builded this week
|
if (town->bonusValue.first == 0)//fountain was builded this week
|
||||||
descr += "\n\n"+ CGI->generaltexth->allTexts[677];
|
descr += "\n\n"+ CGI->generaltexth->allTexts[677];
|
||||||
else//fountain produced something;
|
else//fountain produced something;
|
||||||
@ -948,9 +876,9 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, const CGTownInst
|
|||||||
townlist->onSelect = boost::bind(&CCastleInterface::townChange, this);
|
townlist->onSelect = boost::bind(&CCastleInterface::townChange, this);
|
||||||
|
|
||||||
recreateIcons();
|
recreateIcons();
|
||||||
CCS->musich->playMusicFromSet("town-theme", town->subID, true);
|
CCS->musich->playMusic(town->town->clientInfo.musicTheme, true);
|
||||||
|
|
||||||
bicons = CDefHandler::giveDefEss(graphics->buildingPics[town->subID]);
|
bicons = CDefHandler::giveDefEss(town->town->clientInfo.buildingsIcons);
|
||||||
}
|
}
|
||||||
|
|
||||||
CCastleInterface::~CCastleInterface()
|
CCastleInterface::~CCastleInterface()
|
||||||
@ -1013,7 +941,7 @@ void CCastleInterface::recreateIcons()
|
|||||||
if (!town->hasFort())
|
if (!town->hasFort())
|
||||||
iconIndex += GameConstants::F_NUMBER*2;
|
iconIndex += GameConstants::F_NUMBER*2;
|
||||||
|
|
||||||
if(town->builded >= GameConstants::MAX_BUILDING_PER_TURN)
|
if(town->builded >= CGI->modh->settings.MAX_BUILDING_PER_TURN)
|
||||||
iconIndex++;
|
iconIndex++;
|
||||||
|
|
||||||
icon->setFrame(iconIndex);
|
icon->setFrame(iconIndex);
|
||||||
@ -1319,7 +1247,7 @@ CHallInterface::CBuildingBox::CBuildingBox(int x, int y, const CGTownInstance *
|
|||||||
static int panelIndex[9] = { 3, 3, 3, 0, 0, 2, 2, 1, 2};
|
static int panelIndex[9] = { 3, 3, 3, 0, 0, 2, 2, 1, 2};
|
||||||
static int iconIndex[9] = {-1, -1, -1, 0, 0, 1, 2, -1, 1};
|
static int iconIndex[9] = {-1, -1, -1, 0, 0, 1, 2, -1, 1};
|
||||||
|
|
||||||
picture = new CAnimImage(graphics->buildingPics[town->subID], building->bid, 0, 2, 2);
|
picture = new CAnimImage(town->town->clientInfo.buildingsIcons, building->bid, 0, 2, 2);
|
||||||
panel = new CAnimImage("TPTHBAR", panelIndex[state], 0, 1, 73);
|
panel = new CAnimImage("TPTHBAR", panelIndex[state], 0, 1, 73);
|
||||||
if ( iconIndex[state] >=0 )
|
if ( iconIndex[state] >=0 )
|
||||||
icon = new CAnimImage("TPTHCHK", iconIndex[state], 0, 136, 56);
|
icon = new CAnimImage("TPTHCHK", iconIndex[state], 0, 136, 56);
|
||||||
@ -1355,17 +1283,7 @@ CHallInterface::CHallInterface(const CGTownInstance *Town):
|
|||||||
int buildingID = boxList[row][col][item];
|
int buildingID = boxList[row][col][item];
|
||||||
building = town->town->buildings[buildingID];
|
building = town->town->buildings[buildingID];
|
||||||
|
|
||||||
if (buildingID == 18 || buildingID == 24)
|
if(!vstd::contains(town->builtBuildings,buildingID))
|
||||||
{
|
|
||||||
if ( (buildingID == 18 && !vstd::contains(town->builtBuildings, town->town->hordeLvl[0]+37))
|
|
||||||
|| (buildingID == 24 && !vstd::contains(town->builtBuildings, town->town->hordeLvl[1]+37)) )
|
|
||||||
break; // horde present, no upgraded dwelling -> select 18 or 24
|
|
||||||
else
|
|
||||||
continue; //upgraded dwelling, no horde -> select 19 or 25
|
|
||||||
}
|
|
||||||
|
|
||||||
if(vstd::contains(town->builtBuildings,buildingID))
|
|
||||||
continue;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
int posX = pos.w/2 - boxList[row].size()*154/2 - (boxList[row].size()-1)*20 + 194*col,
|
int posX = pos.w/2 - boxList[row].size()*154/2 - (boxList[row].size()-1)*20 + 194*col,
|
||||||
@ -1419,7 +1337,7 @@ CBuildWindow::CBuildWindow(const CGTownInstance *Town, const CBuilding * Buildin
|
|||||||
{
|
{
|
||||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||||
|
|
||||||
new CAnimImage(graphics->buildingPics[town->subID], building->bid, 0, 125, 50);
|
new CAnimImage(town->town->clientInfo.buildingsIcons, building->bid, 0, 125, 50);
|
||||||
new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26));
|
new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26));
|
||||||
|
|
||||||
new CLabel(197, 30, FONT_MEDIUM, CENTER, Colors::Cornsilk,
|
new CLabel(197, 30, FONT_MEDIUM, CENTER, Colors::Cornsilk,
|
||||||
@ -1581,7 +1499,7 @@ CFortScreen::RecruitArea::RecruitArea(int posX, int posY, const CGTownInstance *
|
|||||||
addUsedEvents(LCLICK | RCLICK | HOVER);//Activate only if dwelling is present
|
addUsedEvents(LCLICK | RCLICK | HOVER);//Activate only if dwelling is present
|
||||||
|
|
||||||
icons = new CPicture("ZPCAINFO", 261, 3);
|
icons = new CPicture("ZPCAINFO", 261, 3);
|
||||||
buildingPic = new CAnimImage(graphics->buildingPics[town->subID], buildingID, 0, 4, 21);
|
buildingPic = new CAnimImage(town->town->clientInfo.buildingsIcons, buildingID, 0, 4, 21);
|
||||||
|
|
||||||
const CCreature* creature = NULL;
|
const CCreature* creature = NULL;
|
||||||
|
|
||||||
@ -1651,7 +1569,7 @@ CMageGuildScreen::CMageGuildScreen(CCastleInterface * owner):
|
|||||||
{
|
{
|
||||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||||
|
|
||||||
window = new CPicture(graphics->guildBgs[owner->town->subID], 332, 76);
|
window = new CPicture(owner->town->town->clientInfo.guildWindow , 332, 76);
|
||||||
|
|
||||||
resdatabar = new CMinorResDataBar;
|
resdatabar = new CMinorResDataBar;
|
||||||
resdatabar->pos.x += pos.x;
|
resdatabar->pos.x += pos.x;
|
||||||
|
@ -114,15 +114,14 @@ public:
|
|||||||
class CCastleBuildings : public CIntObject
|
class CCastleBuildings : public CIntObject
|
||||||
{
|
{
|
||||||
CPicture *background;
|
CPicture *background;
|
||||||
//List of buildings for each group
|
//List of buildings and structures that can represent them
|
||||||
std::map< int, std::vector<const CStructure*> > groups;
|
std::map< si32, std::vector<const CStructure*> > groups;
|
||||||
//Vector with all blittable buildings
|
// actual IntObject's visible on screen
|
||||||
std::vector< CBuildingRect * > buildings;
|
std::vector< CBuildingRect * > buildings;
|
||||||
|
|
||||||
const CGTownInstance * town;
|
const CGTownInstance * town;
|
||||||
|
|
||||||
const CGHeroInstance* getHero();//Select hero for buildings usage
|
const CGHeroInstance* getHero();//Select hero for buildings usage
|
||||||
void checkRules();//Check animation rules (special anims for Shipyard and Mana Vortex)
|
|
||||||
|
|
||||||
void enterBlacksmith(int ArtifactID);//support for blacksmith + ballista yard
|
void enterBlacksmith(int ArtifactID);//support for blacksmith + ballista yard
|
||||||
void enterBuilding(int building);//for buildings with simple description + pic left-click messages
|
void enterBuilding(int building);//for buildings with simple description + pic left-click messages
|
||||||
@ -134,6 +133,7 @@ class CCastleBuildings : public CIntObject
|
|||||||
void openMagesGuild();
|
void openMagesGuild();
|
||||||
void openTownHall();
|
void openTownHall();
|
||||||
|
|
||||||
|
void recreate();
|
||||||
public:
|
public:
|
||||||
CBuildingRect * selectedBuilding;
|
CBuildingRect * selectedBuilding;
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "../CCallback.h"
|
#include "../CCallback.h"
|
||||||
#include "../lib/CCreatureHandler.h" //creatures name for objects list
|
#include "../lib/CCreatureHandler.h" //creatures name for objects list
|
||||||
#include "../lib/CGeneralTextHandler.h"
|
#include "../lib/CGeneralTextHandler.h"
|
||||||
|
#include "../lib/CModHandler.h" //for buildings per turn
|
||||||
#include "../lib/CObjectHandler.h" //Hero/Town objects
|
#include "../lib/CObjectHandler.h" //Hero/Town objects
|
||||||
#include "../lib/CHeroHandler.h" // only for calculating required xp? worth it?
|
#include "../lib/CHeroHandler.h" // only for calculating required xp? worth it?
|
||||||
#include "CAnimation.h" //CAnimImage
|
#include "CAnimation.h" //CAnimImage
|
||||||
@ -797,7 +798,7 @@ CTownItem::CTownItem(const CGTownInstance* Town):
|
|||||||
if (!town->hasFort())
|
if (!town->hasFort())
|
||||||
iconIndex += GameConstants::F_NUMBER*2;
|
iconIndex += GameConstants::F_NUMBER*2;
|
||||||
|
|
||||||
if(town->builded >= GameConstants::MAX_BUILDING_PER_TURN)
|
if(town->builded >= CGI->modh->settings.MAX_BUILDING_PER_TURN)
|
||||||
iconIndex++;
|
iconIndex++;
|
||||||
|
|
||||||
picture = new CAnimImage("ITPT", iconIndex, 0, 5, 6);
|
picture = new CAnimImage("ITPT", iconIndex, 0, 5, 6);
|
||||||
|
@ -329,8 +329,6 @@ CMusicHandler::CMusicHandler():
|
|||||||
const std::string setEnemy[] = {"AITheme0", "AITheme1", "AITheme2"};
|
const std::string setEnemy[] = {"AITheme0", "AITheme1", "AITheme2"};
|
||||||
const std::string setBattle[] = {"Combat01", "Combat02", "Combat03", "Combat04"};
|
const std::string setBattle[] = {"Combat01", "Combat02", "Combat03", "Combat04"};
|
||||||
const std::string setTerrain[] = {"Dirt", "Sand", "Grass", "Snow", "Swamp", "Rough", "Underground", "Lava", "Water"};
|
const std::string setTerrain[] = {"Dirt", "Sand", "Grass", "Snow", "Swamp", "Rough", "Underground", "Lava", "Water"};
|
||||||
const std::string setTowns[] = {"CstleTown", "Rampart", "TowerTown", "InfernoTown",
|
|
||||||
"NecroTown", "Dungeon", "Stronghold", "FortressTown", "ElemTown"};
|
|
||||||
|
|
||||||
auto fillSet = [=](std::string setName, const std::string list[], size_t amount)
|
auto fillSet = [=](std::string setName, const std::string list[], size_t amount)
|
||||||
{
|
{
|
||||||
@ -340,7 +338,6 @@ CMusicHandler::CMusicHandler():
|
|||||||
fillSet("enemy-turn", setEnemy, ARRAY_COUNT(setEnemy));
|
fillSet("enemy-turn", setEnemy, ARRAY_COUNT(setEnemy));
|
||||||
fillSet("battle", setBattle, ARRAY_COUNT(setBattle));
|
fillSet("battle", setBattle, ARRAY_COUNT(setBattle));
|
||||||
fillSet("terrain", setTerrain, ARRAY_COUNT(setTerrain));
|
fillSet("terrain", setTerrain, ARRAY_COUNT(setTerrain));
|
||||||
fillSet("town-theme", setTowns, ARRAY_COUNT(setTowns));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMusicHandler::addEntryToSet(std::string set, int musicID, std::string musicURI)
|
void CMusicHandler::addEntryToSet(std::string set, int musicID, std::string musicURI)
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "../lib/CBuildingHandler.h"
|
#include "../lib/CBuildingHandler.h"
|
||||||
#include "../lib/CGeneralTextHandler.h"
|
#include "../lib/CGeneralTextHandler.h"
|
||||||
#include "../lib/CHeroHandler.h"
|
#include "../lib/CHeroHandler.h"
|
||||||
|
#include "../lib/CModHandler.h"
|
||||||
#include "../lib/CObjectHandler.h"
|
#include "../lib/CObjectHandler.h"
|
||||||
#include "../lib/CSpellHandler.h"
|
#include "../lib/CSpellHandler.h"
|
||||||
#include "../lib/CTownHandler.h"
|
#include "../lib/CTownHandler.h"
|
||||||
@ -162,7 +163,7 @@ void CTownTooltip::init(const InfoAboutTown &town)
|
|||||||
size_t imageIndex = town.tType->typeID * 2;
|
size_t imageIndex = town.tType->typeID * 2;
|
||||||
if (town.fortLevel == 0)
|
if (town.fortLevel == 0)
|
||||||
imageIndex += GameConstants::F_NUMBER * 2;
|
imageIndex += GameConstants::F_NUMBER * 2;
|
||||||
if (town.built >= GameConstants::MAX_BUILDING_PER_TURN)
|
if (town.built >= CGI->modh->settings.MAX_BUILDING_PER_TURN)
|
||||||
imageIndex++;
|
imageIndex++;
|
||||||
|
|
||||||
new CAnimImage("itpt", imageIndex, 0, 3, 2);
|
new CAnimImage("itpt", imageIndex, 0, 3, 2);
|
||||||
@ -861,7 +862,7 @@ const std::vector<std::string> CComponent::getFileName()
|
|||||||
case spell: return gen(spellsArr);
|
case spell: return gen(spellsArr);
|
||||||
case morale: return gen(moraleArr);
|
case morale: return gen(moraleArr);
|
||||||
case luck: return gen(luckArr);
|
case luck: return gen(luckArr);
|
||||||
case building: return std::vector<std::string>(4, graphics->buildingPics[subtype]);
|
case building: return std::vector<std::string>(4, CGI->townh->towns[subtype].clientInfo.buildingsIcons);
|
||||||
case hero: return gen(heroArr);
|
case hero: return gen(heroArr);
|
||||||
case flag: return gen(flagArr);
|
case flag: return gen(flagArr);
|
||||||
}
|
}
|
||||||
@ -1244,18 +1245,17 @@ void CSelWindow::madeChoice()
|
|||||||
LOCPLINT->cb->selectionMade(ret+1,ID);
|
LOCPLINT->cb->selectionMade(ret+1,ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CCreaturePic::CCreaturePic(int x, int y, const CCreature *cre, bool Big, bool Animated)
|
CCreaturePic::CCreaturePic(int x, int y, const CCreature *cre, bool Big, bool Animated)
|
||||||
{
|
{
|
||||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||||
pos.x+=x;
|
pos.x+=x;
|
||||||
pos.y+=y;
|
pos.y+=y;
|
||||||
|
|
||||||
|
assert(vstd::contains(CGI->townh->factions, cre->faction));
|
||||||
if(Big)
|
if(Big)
|
||||||
bg = new CPicture(graphics->backgrounds[cre->faction],0,0,false);
|
bg = new CPicture(CGI->townh->factions[cre->faction].creatureBg130);
|
||||||
else
|
else
|
||||||
bg = new CPicture(graphics->backgroundsm[cre->faction],0,0,false);
|
bg = new CPicture(CGI->townh->factions[cre->faction].creatureBg120);
|
||||||
bg->needRefresh = true;
|
bg->needRefresh = true;
|
||||||
anim = new CCreatureAnim(0, 0, cre->animDefName, Rect());
|
anim = new CCreatureAnim(0, 0, cre->animDefName, Rect());
|
||||||
anim->clipRect(cre->isDoubleWide()?170:150, 155, bg->pos.w, bg->pos.h);
|
anim->clipRect(cre->isDoubleWide()?170:150, 155, bg->pos.w, bg->pos.h);
|
||||||
@ -2437,10 +2437,17 @@ CMarketplaceWindow::CMarketplaceWindow(const IMarket *Market, const CGHeroInstan
|
|||||||
{
|
{
|
||||||
switch (mode)
|
switch (mode)
|
||||||
{
|
{
|
||||||
break; case EMarketMode::CREATURE_RESOURCE: title = CGI->townh->towns[6].buildings[21]->Name();
|
break; case EMarketMode::CREATURE_RESOURCE:
|
||||||
break; case EMarketMode::RESOURCE_ARTIFACT: title = CGI->townh->towns[market->o->subID].buildings[17]->Name();
|
title = CGI->townh->towns[ETownType::STRONGHOLD].buildings[EBuilding::FREELANCERS_GUILD]->Name();
|
||||||
break; case EMarketMode::ARTIFACT_RESOURCE: title = CGI->townh->towns[market->o->subID].buildings[17]->Name();
|
|
||||||
break; default: title = CGI->generaltexth->allTexts[158];
|
break; case EMarketMode::RESOURCE_ARTIFACT:
|
||||||
|
title = CGI->townh->towns[market->o->subID].buildings[EBuilding::ARTIFACT_MERCHANT]->Name();
|
||||||
|
|
||||||
|
break; case EMarketMode::ARTIFACT_RESOURCE:
|
||||||
|
title = CGI->townh->towns[market->o->subID].buildings[EBuilding::ARTIFACT_MERCHANT]->Name();
|
||||||
|
|
||||||
|
break; default:
|
||||||
|
title = CGI->generaltexth->allTexts[158];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -5253,7 +5260,7 @@ CUniversityWindow::CUniversityWindow(const CGHeroInstance * _hero, const IMarket
|
|||||||
titlePic = new CPicture("UNIVBLDG");
|
titlePic = new CPicture("UNIVBLDG");
|
||||||
else
|
else
|
||||||
if (market->o->ID == GameConstants::TOWNI_TYPE)
|
if (market->o->ID == GameConstants::TOWNI_TYPE)
|
||||||
titlePic = new CAnimImage(graphics->buildingPics[market->o->subID], 21);
|
titlePic = new CAnimImage(CGI->townh->towns[ETownType::CONFLUX].clientInfo.buildingsIcons, EBuilding::MAGIC_UNIVERSITY);
|
||||||
else
|
else
|
||||||
tlog0<<"Error: Image for university was not found!\n";//This should not happen
|
tlog0<<"Error: Image for university was not found!\n";//This should not happen
|
||||||
|
|
||||||
|
@ -87,13 +87,6 @@ void Graphics::loadPaletteAndColors()
|
|||||||
playerColors[i].unused = 255;
|
playerColors[i].unused = 255;
|
||||||
}
|
}
|
||||||
neutralColor->r = 0x84; neutralColor->g = 0x84; neutralColor->b = 0x84; neutralColor->unused = 255;//gray
|
neutralColor->r = 0x84; neutralColor->g = 0x84; neutralColor->b = 0x84; neutralColor->unused = 255;//gray
|
||||||
const JsonNode config(ResourceID("config/town_pictures.json"));
|
|
||||||
BOOST_FOREACH(const JsonNode &p, config["town_pictures"].Vector()) {
|
|
||||||
|
|
||||||
townBgs.push_back(p["town_background"].String());
|
|
||||||
guildBgs.push_back(p["guild_background"].String());
|
|
||||||
buildingPics.push_back(p["building_picture"].String());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::initializeBattleGraphics()
|
void Graphics::initializeBattleGraphics()
|
||||||
@ -158,13 +151,6 @@ Graphics::Graphics()
|
|||||||
tasks += GET_DEF_ESS(spellscr,"SPELLSCR.DEF");
|
tasks += GET_DEF_ESS(spellscr,"SPELLSCR.DEF");
|
||||||
tasks += GET_DEF_ESS(heroMoveArrows,"ADAG.DEF");
|
tasks += GET_DEF_ESS(heroMoveArrows,"ADAG.DEF");
|
||||||
|
|
||||||
const JsonNode config(ResourceID("config/creature_backgrounds.json"));
|
|
||||||
BOOST_FOREACH(const JsonNode &b, config["backgrounds"].Vector()) {
|
|
||||||
const int id = b["id"].Float();
|
|
||||||
tasks += GET_SURFACE(backgrounds[id], b["bg130"].String());
|
|
||||||
tasks += GET_SURFACE(backgroundsm[id], b["bg120"].String());
|
|
||||||
}
|
|
||||||
|
|
||||||
CThreadHelper th(&tasks,std::max((ui32)1,boost::thread::hardware_concurrency()));
|
CThreadHelper th(&tasks,std::max((ui32)1,boost::thread::hardware_concurrency()));
|
||||||
th.run();
|
th.run();
|
||||||
|
|
||||||
|
@ -64,12 +64,7 @@ public:
|
|||||||
//creatures
|
//creatures
|
||||||
std::map<int,SDL_Surface*> smallImgs; //creature ID -> small 32x32 img of creature; //ID=-2 is for blank (black) img; -1 for the border
|
std::map<int,SDL_Surface*> smallImgs; //creature ID -> small 32x32 img of creature; //ID=-2 is for blank (black) img; -1 for the border
|
||||||
std::map<int,SDL_Surface*> bigImgs; //creature ID -> big 58x64 img of creature; //ID=-2 is for blank (black) img; -1 for the border
|
std::map<int,SDL_Surface*> bigImgs; //creature ID -> big 58x64 img of creature; //ID=-2 is for blank (black) img; -1 for the border
|
||||||
std::map<int,SDL_Surface*> backgrounds; //castle ID -> 100x130 background creature image // -1 is for neutral
|
|
||||||
std::map<int,SDL_Surface*> backgroundsm; //castle ID -> 100x120 background creature image // -1 is for neutral
|
|
||||||
//towns
|
//towns
|
||||||
std::vector< std::string > buildingPics;//filenames of def with building images (used rarely, too big to keep them loaded)
|
|
||||||
std::vector< std::string > townBgs;//backgrounds of town
|
|
||||||
std::vector< std::string > guildBgs;// name of bitmaps with imgs for mage guild screen
|
|
||||||
std::map<int, std::string> ERMUtoPicture[GameConstants::F_NUMBER]; //maps building ID to it's picture's name for each town type
|
std::map<int, std::string> ERMUtoPicture[GameConstants::F_NUMBER]; //maps building ID to it's picture's name for each town type
|
||||||
//for battles
|
//for battles
|
||||||
std::vector< std::vector< std::string > > battleBacks; //battleBacks[terType] - vector of possible names for certain terrain type
|
std::vector< std::vector< std::string > > battleBacks; //battleBacks[terType] - vector of possible names for certain terrain type
|
||||||
|
@ -401,11 +401,11 @@ void NewStructures::applyCl( CClient *cl )
|
|||||||
CGTownInstance *town = GS(cl)->getTown(tid);
|
CGTownInstance *town = GS(cl)->getTown(tid);
|
||||||
BOOST_FOREACH(si32 id, bid)
|
BOOST_FOREACH(si32 id, bid)
|
||||||
{
|
{
|
||||||
if(id==13) //fort or capitol
|
if(id== EBuilding::CAPITOL) //fort or capitol
|
||||||
{
|
{
|
||||||
town->defInfo = GS(cl)->capitols[town->subID];
|
town->defInfo = GS(cl)->capitols[town->subID];
|
||||||
}
|
}
|
||||||
if(id ==7)
|
if(id == EBuilding::FORT)
|
||||||
{
|
{
|
||||||
town->defInfo = GS(cl)->forts[town->subID];
|
town->defInfo = GS(cl)->forts[town->subID];
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,19 +0,0 @@
|
|||||||
{
|
|
||||||
// Backgrounds for creatures.
|
|
||||||
// id: town ID (0 to 8, -1 is neutral)
|
|
||||||
// bg120: 100x120 background creature image
|
|
||||||
// bg130: 100x130 background creature image
|
|
||||||
|
|
||||||
"backgrounds": [
|
|
||||||
{ "id": -1, "bg120": "TPCASNEU.bmp", "bg130": "CRBKGNEU.bmp" },
|
|
||||||
{ "id": 0, "bg120": "TPCASCAS.bmp", "bg130": "CRBKGCAS.bmp" },
|
|
||||||
{ "id": 1, "bg120": "TPCASRAM.bmp", "bg130": "CRBKGRAM.bmp" },
|
|
||||||
{ "id": 2, "bg120": "TPCASTOW.bmp", "bg130": "CRBKGTOW.bmp" },
|
|
||||||
{ "id": 3, "bg120": "TPCASINF.bmp", "bg130": "CRBKGINF.bmp" },
|
|
||||||
{ "id": 4, "bg120": "TPCASNEC.bmp", "bg130": "CRBKGNEC.bmp" },
|
|
||||||
{ "id": 5, "bg120": "TPCASDUN.bmp", "bg130": "CRBKGDUN.bmp" },
|
|
||||||
{ "id": 6, "bg120": "TPCASSTR.bmp", "bg130": "CRBKGSTR.bmp" },
|
|
||||||
{ "id": 7, "bg120": "TPCASFOR.bmp", "bg130": "CRBKGFOR.bmp" },
|
|
||||||
{ "id": 8, "bg120": "TPCASELE.bmp", "bg130": "CRBKGELE.bmp" }
|
|
||||||
]
|
|
||||||
}
|
|
@ -1225,7 +1225,7 @@
|
|||||||
"id": 116,
|
"id": 116,
|
||||||
"level": 4,
|
"level": 4,
|
||||||
"name": [ "GoldGolem" ],
|
"name": [ "GoldGolem" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"ability_add": [ [ "SPELL_DAMAGE_REDUCTION", 85, -1, 0 ], //gold golems reduce dmg from spells
|
"ability_add": [ [ "SPELL_DAMAGE_REDUCTION", 85, -1, 0 ], //gold golems reduce dmg from spells
|
||||||
[ "NON_LIVING", 0, 0, 0 ] ], //diamond golems are non-living
|
[ "NON_LIVING", 0, 0, 0 ] ], //diamond golems are non-living
|
||||||
"defname": "CGGOLE.DEF"
|
"defname": "CGGOLE.DEF"
|
||||||
@ -1235,7 +1235,7 @@
|
|||||||
"id": 117,
|
"id": 117,
|
||||||
"level": 5,
|
"level": 5,
|
||||||
"name": [ "DiamondGolem" ],
|
"name": [ "DiamondGolem" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"ability_add": [ [ "SPELL_DAMAGE_REDUCTION", 95, -1, 0 ], //diamond golems reduce dmg from spells
|
"ability_add": [ [ "SPELL_DAMAGE_REDUCTION", 95, -1, 0 ], //diamond golems reduce dmg from spells
|
||||||
[ "NON_LIVING", 0, 0, 0 ] ], //psychic elementals shouldn't get morale
|
[ "NON_LIVING", 0, 0, 0 ] ], //psychic elementals shouldn't get morale
|
||||||
"defname": "CDGOLE.DEF"
|
"defname": "CDGOLE.DEF"
|
||||||
@ -1357,7 +1357,7 @@
|
|||||||
"id": 132,
|
"id": 132,
|
||||||
"level": 10,
|
"level": 10,
|
||||||
"name": [ "AzureDragon" ],
|
"name": [ "AzureDragon" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"ability_add": [ [ "DRAGON_NATURE", 0, 0, 0 ],
|
"ability_add": [ [ "DRAGON_NATURE", 0, 0, 0 ],
|
||||||
[ "TWO_HEX_ATTACK_BREATH", 0, 0, 0 ], //azure dragon's breath
|
[ "TWO_HEX_ATTACK_BREATH", 0, 0, 0 ], //azure dragon's breath
|
||||||
[ "FEARLESS", 0, 0, 0 ], //azure dragon is immune to fear
|
[ "FEARLESS", 0, 0, 0 ], //azure dragon is immune to fear
|
||||||
@ -1370,7 +1370,7 @@
|
|||||||
"id": 133,
|
"id": 133,
|
||||||
"level": 10,
|
"level": 10,
|
||||||
"name": [ "CrystalDragon" ],
|
"name": [ "CrystalDragon" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"ability_add": [ [ "DRAGON_NATURE", 0, 0, 0 ] ], //crystal dragon is a dragon
|
"ability_add": [ [ "DRAGON_NATURE", 0, 0, 0 ] ], //crystal dragon is a dragon
|
||||||
"ability_remove": [ "FLYING" ],
|
"ability_remove": [ "FLYING" ],
|
||||||
"defname": "CCDRGN.DEF"
|
"defname": "CCDRGN.DEF"
|
||||||
@ -1380,7 +1380,7 @@
|
|||||||
"id": 134,
|
"id": 134,
|
||||||
"level": 8,
|
"level": 8,
|
||||||
"name": [ "FairieDragon" ],
|
"name": [ "FairieDragon" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"ability_add": [ [ "DRAGON_NATURE", 0, 0, 0 ], //faerie dragon is a dragon
|
"ability_add": [ [ "DRAGON_NATURE", 0, 0, 0 ], //faerie dragon is a dragon
|
||||||
[ "CASTS", 5, 0, 0 ],
|
[ "CASTS", 5, 0, 0 ],
|
||||||
[ "CREATURE_SPELL_POWER", 500, 0, 0], //5 spell power per dragon
|
[ "CREATURE_SPELL_POWER", 500, 0, 0], //5 spell power per dragon
|
||||||
@ -1399,7 +1399,7 @@
|
|||||||
"id": 135,
|
"id": 135,
|
||||||
"level": 10,
|
"level": 10,
|
||||||
"name": [ "RustDragon" ],
|
"name": [ "RustDragon" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"ability_add": [ [ "SPELL_AFTER_ATTACK", 100, 80, 0 ], //always reduce defense
|
"ability_add": [ [ "SPELL_AFTER_ATTACK", 100, 80, 0 ], //always reduce defense
|
||||||
[ "ACID_BREATH", 25, 0, 20 ], //20% chance to do 25 damage
|
[ "ACID_BREATH", 25, 0, 20 ], //20% chance to do 25 damage
|
||||||
[ "DRAGON_NATURE", 0, 0, 0 ] ], //rust dragon is a dragon
|
[ "DRAGON_NATURE", 0, 0, 0 ] ], //rust dragon is a dragon
|
||||||
@ -1410,7 +1410,7 @@
|
|||||||
"id": 136,
|
"id": 136,
|
||||||
"level": 6,
|
"level": 6,
|
||||||
"name": [ "Enchanter" ],
|
"name": [ "Enchanter" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"ability_add": [ [ "NO_WALL_PENALTY", 0, 0, 0 ],
|
"ability_add": [ [ "NO_WALL_PENALTY", 0, 0, 0 ],
|
||||||
[ "ENCHANTER", 3, 28, 3], //air shield
|
[ "ENCHANTER", 3, 28, 3], //air shield
|
||||||
[ "ENCHANTER", 3, 41, 3], //bless
|
[ "ENCHANTER", 3, 41, 3], //bless
|
||||||
@ -1428,7 +1428,7 @@
|
|||||||
"id": 137,
|
"id": 137,
|
||||||
"level": 4,
|
"level": 4,
|
||||||
"name": [ "Sharpshooter" ],
|
"name": [ "Sharpshooter" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"ability_add": [ [ "NO_WALL_PENALTY", 0, 0, 0 ],
|
"ability_add": [ [ "NO_WALL_PENALTY", 0, 0, 0 ],
|
||||||
[ "NO_DISTANCE_PENALTY", 0, 0, 0 ] ], //Sharpshooter
|
[ "NO_DISTANCE_PENALTY", 0, 0, 0 ] ], //Sharpshooter
|
||||||
"defname": "CSHARP.DEF",
|
"defname": "CSHARP.DEF",
|
||||||
@ -1440,7 +1440,7 @@
|
|||||||
"id": 138,
|
"id": 138,
|
||||||
"level": 1,
|
"level": 1,
|
||||||
"name": [ "Halfling" ],
|
"name": [ "Halfling" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "CHALF.DEF",
|
"defname": "CHALF.DEF",
|
||||||
"projectile_defname": "PHALF.DEF",
|
"projectile_defname": "PHALF.DEF",
|
||||||
"projectile_spin": true
|
"projectile_spin": true
|
||||||
@ -1450,7 +1450,7 @@
|
|||||||
"id": 139,
|
"id": 139,
|
||||||
"level": 1,
|
"level": 1,
|
||||||
"name": [ "Peasant" ],
|
"name": [ "Peasant" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "CPEAS.DEF"
|
"defname": "CPEAS.DEF"
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1458,7 +1458,7 @@
|
|||||||
"id": 140,
|
"id": 140,
|
||||||
"level": 2,
|
"level": 2,
|
||||||
"name": [ "Boar" ],
|
"name": [ "Boar" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"ability_add": [ [ "DOUBLE_WIDE", 0, 0, 0 ] ], //boar should be treated as double-wide
|
"ability_add": [ [ "DOUBLE_WIDE", 0, 0, 0 ] ], //boar should be treated as double-wide
|
||||||
"defname": "CBOAR.DEF"
|
"defname": "CBOAR.DEF"
|
||||||
},
|
},
|
||||||
@ -1467,7 +1467,7 @@
|
|||||||
"id": 141,
|
"id": 141,
|
||||||
"level": 3,
|
"level": 3,
|
||||||
"name": [ "Mummy" ],
|
"name": [ "Mummy" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"ability_add": [ [ "UNDEAD", 0, 0, 0 ] ],
|
"ability_add": [ [ "UNDEAD", 0, 0, 0 ] ],
|
||||||
"defname": "CMUMMY.DEF"
|
"defname": "CMUMMY.DEF"
|
||||||
},
|
},
|
||||||
@ -1476,7 +1476,7 @@
|
|||||||
"id": 142,
|
"id": 142,
|
||||||
"level": 3,
|
"level": 3,
|
||||||
"name": [ "warrior" ],
|
"name": [ "warrior" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"ability_add": [ [ "DOUBLE_WIDE", 0, 0, 0 ] ], //nomads should be treated as double-wide
|
"ability_add": [ [ "DOUBLE_WIDE", 0, 0, 0 ] ], //nomads should be treated as double-wide
|
||||||
"defname": "CNOMAD.DEF"
|
"defname": "CNOMAD.DEF"
|
||||||
},
|
},
|
||||||
@ -1485,7 +1485,7 @@
|
|||||||
"id": 143,
|
"id": 143,
|
||||||
"level": 2,
|
"level": 2,
|
||||||
"name": [ "Rogue" ],
|
"name": [ "Rogue" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "CROGUE.DEF"
|
"defname": "CROGUE.DEF"
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1493,7 +1493,7 @@
|
|||||||
"id": 144,
|
"id": 144,
|
||||||
"level": 5,
|
"level": 5,
|
||||||
"name": [ "OgreShaman" ],
|
"name": [ "OgreShaman" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"ability_add": [ [ "FULL_HP_REGENERATION", 0, 0, 0 ] ], //troll
|
"ability_add": [ [ "FULL_HP_REGENERATION", 0, 0, 0 ] ], //troll
|
||||||
"defname": "CTROLL.DEF"
|
"defname": "CTROLL.DEF"
|
||||||
},
|
},
|
||||||
@ -1502,7 +1502,7 @@
|
|||||||
"id": 145,
|
"id": 145,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "Catapult" ],
|
"name": [ "Catapult" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "SMCATA.DEF",
|
"defname": "SMCATA.DEF",
|
||||||
"projectile_defname": "SMCATX.DEF",
|
"projectile_defname": "SMCATX.DEF",
|
||||||
"projectile_spin": true
|
"projectile_spin": true
|
||||||
@ -1512,7 +1512,7 @@
|
|||||||
"id": 146,
|
"id": 146,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "Ballista" ],
|
"name": [ "Ballista" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "SMBAL.DEF",
|
"defname": "SMBAL.DEF",
|
||||||
"projectile_defname": "SMBALX.DEF",
|
"projectile_defname": "SMBALX.DEF",
|
||||||
"projectile_spin": false
|
"projectile_spin": false
|
||||||
@ -1522,7 +1522,7 @@
|
|||||||
"id": 147,
|
"id": 147,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "FirstAidTent" ],
|
"name": [ "FirstAidTent" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"ability_add": [ [ "HEALER", 0, 0, 0 ] ], //Gorynyches fly
|
"ability_add": [ [ "HEALER", 0, 0, 0 ] ], //Gorynyches fly
|
||||||
"defname": "SMTENT.DEF"
|
"defname": "SMTENT.DEF"
|
||||||
},
|
},
|
||||||
@ -1531,7 +1531,7 @@
|
|||||||
"id": 148,
|
"id": 148,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "AmmoCart" ],
|
"name": [ "AmmoCart" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"ability_add": [ [ "NOT_ACTIVE", 0, 0, 0 ] ], //hell hound doesn't fly
|
"ability_add": [ [ "NOT_ACTIVE", 0, 0, 0 ] ], //hell hound doesn't fly
|
||||||
"defname": "SMCART.DEF"
|
"defname": "SMCART.DEF"
|
||||||
},
|
},
|
||||||
@ -1540,7 +1540,7 @@
|
|||||||
"id": 149,
|
"id": 149,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "ArrowTower" ],
|
"name": [ "ArrowTower" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"ability_add": [ [ "SHOOTER", 0, 0, 0 ] ], //cerberus doesn't fly
|
"ability_add": [ [ "SHOOTER", 0, 0, 0 ] ], //cerberus doesn't fly
|
||||||
"defname": "x"
|
"defname": "x"
|
||||||
},
|
},
|
||||||
@ -1627,7 +1627,7 @@
|
|||||||
"id": 159,
|
"id": 159,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "Ghost" ],
|
"name": [ "Ghost" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "ZM159G.DEF"
|
"defname": "ZM159G.DEF"
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1635,7 +1635,7 @@
|
|||||||
"id": 160,
|
"id": 160,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "God1War" ],
|
"name": [ "God1War" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "ZM160G.DEF"
|
"defname": "ZM160G.DEF"
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1643,7 +1643,7 @@
|
|||||||
"id": 161,
|
"id": 161,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "God2Peace" ],
|
"name": [ "God2Peace" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "ZM161G.DEF"
|
"defname": "ZM161G.DEF"
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1651,7 +1651,7 @@
|
|||||||
"id": 162,
|
"id": 162,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "God3Mana" ],
|
"name": [ "God3Mana" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "ZM162G.DEF"
|
"defname": "ZM162G.DEF"
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1659,7 +1659,7 @@
|
|||||||
"id": 163,
|
"id": 163,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "God4Lore" ],
|
"name": [ "God4Lore" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "ZM163G.DEF"
|
"defname": "ZM163G.DEF"
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1667,7 +1667,7 @@
|
|||||||
"id": 164,
|
"id": 164,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "MinotaurKing" ],
|
"name": [ "MinotaurKing" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "ZM164GD.DEF"
|
"defname": "ZM164GD.DEF"
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1675,7 +1675,7 @@
|
|||||||
"id": 165,
|
"id": 165,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "MineralElemental" ],
|
"name": [ "MineralElemental" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "ZM165GD.DEF"
|
"defname": "ZM165GD.DEF"
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1683,7 +1683,7 @@
|
|||||||
"id": 166,
|
"id": 166,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "ElectricityElemental" ],
|
"name": [ "ElectricityElemental" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "ZM166GD.DEF"
|
"defname": "ZM166GD.DEF"
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1691,7 +1691,7 @@
|
|||||||
"id": 167,
|
"id": 167,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "AncientBasilisk" ],
|
"name": [ "AncientBasilisk" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "ZM167GD.DEF"
|
"defname": "ZM167GD.DEF"
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1699,7 +1699,7 @@
|
|||||||
"id": 168,
|
"id": 168,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "Gorynych" ],
|
"name": [ "Gorynych" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"ability_add": [ [ "FLYING", 0, 0, 0 ] ],
|
"ability_add": [ [ "FLYING", 0, 0, 0 ] ],
|
||||||
"defname": "ZM168DG.DEF"
|
"defname": "ZM168DG.DEF"
|
||||||
},
|
},
|
||||||
@ -1708,7 +1708,7 @@
|
|||||||
"id": 169,
|
"id": 169,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "WarZealot" ],
|
"name": [ "WarZealot" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "ZM169ZL.DEF",
|
"defname": "ZM169ZL.DEF",
|
||||||
"projectile_defname": "CPRZEAX.DEF",
|
"projectile_defname": "CPRZEAX.DEF",
|
||||||
"projectile_spin": false
|
"projectile_spin": false
|
||||||
@ -1718,7 +1718,7 @@
|
|||||||
"id": 170,
|
"id": 170,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "Myriad" ],
|
"name": [ "Myriad" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "ZM170SW.DEF",
|
"defname": "ZM170SW.DEF",
|
||||||
"projectile_defname": "PLCBOWX.DEF",
|
"projectile_defname": "PLCBOWX.DEF",
|
||||||
"projectile_spin": false
|
"projectile_spin": false
|
||||||
@ -1728,7 +1728,7 @@
|
|||||||
"id": 171,
|
"id": 171,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "MedusaMatriarch" ],
|
"name": [ "MedusaMatriarch" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "ZM171SR.DEF",
|
"defname": "ZM171SR.DEF",
|
||||||
"projectile_defname": "PLCBOWX.DEF",
|
"projectile_defname": "PLCBOWX.DEF",
|
||||||
"projectile_spin": false
|
"projectile_spin": false
|
||||||
@ -1738,7 +1738,7 @@
|
|||||||
"id": 172,
|
"id": 172,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "Nightmare" ],
|
"name": [ "Nightmare" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "ZM172N.DEF"
|
"defname": "ZM172N.DEF"
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1746,7 +1746,7 @@
|
|||||||
"id": 173,
|
"id": 173,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "SantaGremlin" ],
|
"name": [ "SantaGremlin" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "ZM173M.DEF",
|
"defname": "ZM173M.DEF",
|
||||||
"projectile_defname": "CPRGRE.DEF",
|
"projectile_defname": "CPRGRE.DEF",
|
||||||
"projectile_spin": true
|
"projectile_spin": true
|
||||||
@ -1756,7 +1756,7 @@
|
|||||||
"id": 174,
|
"id": 174,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "Paladin1" ],
|
"name": [ "Paladin1" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"ability_add": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ],
|
"ability_add": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ],
|
||||||
[ "CASTS", 1, 0, 0 ] ,
|
[ "CASTS", 1, 0, 0 ] ,
|
||||||
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
|
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
|
||||||
@ -1769,7 +1769,7 @@
|
|||||||
"id": 175,
|
"id": 175,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "Hierophant1" ],
|
"name": [ "Hierophant1" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"ability_add": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ],
|
"ability_add": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ],
|
||||||
[ "CASTS", 1, 0, 0 ] ,
|
[ "CASTS", 1, 0, 0 ] ,
|
||||||
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
|
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
|
||||||
@ -1782,7 +1782,7 @@
|
|||||||
"id": 176,
|
"id": 176,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "TempleGuardian1" ],
|
"name": [ "TempleGuardian1" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"ability_add": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ],
|
"ability_add": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ],
|
||||||
[ "CASTS", 1, 0, 0 ] ,
|
[ "CASTS", 1, 0, 0 ] ,
|
||||||
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
|
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
|
||||||
@ -1795,7 +1795,7 @@
|
|||||||
"id": 177,
|
"id": 177,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "Succubus1" ],
|
"name": [ "Succubus1" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"ability_add": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ],
|
"ability_add": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ],
|
||||||
[ "CASTS", 1, 0, 0 ] ,
|
[ "CASTS", 1, 0, 0 ] ,
|
||||||
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
|
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
|
||||||
@ -1808,7 +1808,7 @@
|
|||||||
"id": 178,
|
"id": 178,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "SoulEater1" ],
|
"name": [ "SoulEater1" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"ability_add": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ],
|
"ability_add": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ],
|
||||||
[ "CASTS", 1, 0, 0 ] ,
|
[ "CASTS", 1, 0, 0 ] ,
|
||||||
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
|
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
|
||||||
@ -1821,7 +1821,7 @@
|
|||||||
"id": 179,
|
"id": 179,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "Brute1" ],
|
"name": [ "Brute1" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"ability_add": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ],
|
"ability_add": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ],
|
||||||
[ "CASTS", 1, 0, 0 ] ,
|
[ "CASTS", 1, 0, 0 ] ,
|
||||||
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
|
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
|
||||||
@ -1834,7 +1834,7 @@
|
|||||||
"id": 180,
|
"id": 180,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "OgreLeader1" ],
|
"name": [ "OgreLeader1" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"ability_add": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ],
|
"ability_add": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ],
|
||||||
[ "CASTS", 1, 0, 0 ] ,
|
[ "CASTS", 1, 0, 0 ] ,
|
||||||
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
|
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
|
||||||
@ -1847,7 +1847,7 @@
|
|||||||
"id": 181,
|
"id": 181,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "Shaman1" ],
|
"name": [ "Shaman1" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"ability_add": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ],
|
"ability_add": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ],
|
||||||
[ "CASTS", 1, 0, 0 ] ,
|
[ "CASTS", 1, 0, 0 ] ,
|
||||||
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
|
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
|
||||||
@ -1860,7 +1860,7 @@
|
|||||||
"id": 182,
|
"id": 182,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "AstralSpirit1" ],
|
"name": [ "AstralSpirit1" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"ability_add": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ],
|
"ability_add": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ],
|
||||||
[ "CASTS", 1, 0, 0 ] ,
|
[ "CASTS", 1, 0, 0 ] ,
|
||||||
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
|
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
|
||||||
@ -1873,7 +1873,7 @@
|
|||||||
"id": 183,
|
"id": 183,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "Paladin2" ],
|
"name": [ "Paladin2" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "ZM174NPC.DEF"
|
"defname": "ZM174NPC.DEF"
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1881,7 +1881,7 @@
|
|||||||
"id": 184,
|
"id": 184,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "Hierophant2" ],
|
"name": [ "Hierophant2" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "ZM175NPC.DEF"
|
"defname": "ZM175NPC.DEF"
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1889,7 +1889,7 @@
|
|||||||
"id": 185,
|
"id": 185,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "TempleGuardian2" ],
|
"name": [ "TempleGuardian2" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "ZM176NPC.DEF"
|
"defname": "ZM176NPC.DEF"
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1897,7 +1897,7 @@
|
|||||||
"id": 186,
|
"id": 186,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "Succubus2" ],
|
"name": [ "Succubus2" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "ZM177NPC.DEF"
|
"defname": "ZM177NPC.DEF"
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1905,7 +1905,7 @@
|
|||||||
"id": 187,
|
"id": 187,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "SoulEater2" ],
|
"name": [ "SoulEater2" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "ZM178NPC.DEF"
|
"defname": "ZM178NPC.DEF"
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1913,7 +1913,7 @@
|
|||||||
"id": 188,
|
"id": 188,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "Brute2" ],
|
"name": [ "Brute2" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "ZM179NPC.DEF"
|
"defname": "ZM179NPC.DEF"
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1921,7 +1921,7 @@
|
|||||||
"id": 189,
|
"id": 189,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "OgreLeader2" ],
|
"name": [ "OgreLeader2" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "ZM180NPC.DEF"
|
"defname": "ZM180NPC.DEF"
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1929,7 +1929,7 @@
|
|||||||
"id": 190,
|
"id": 190,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "Shaman2" ],
|
"name": [ "Shaman2" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "ZM181NPC.DEF"
|
"defname": "ZM181NPC.DEF"
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1937,7 +1937,7 @@
|
|||||||
"id": 191,
|
"id": 191,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "AstralSpirit2" ],
|
"name": [ "AstralSpirit2" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "ZM182NPC.DEF"
|
"defname": "ZM182NPC.DEF"
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1945,7 +1945,7 @@
|
|||||||
"id": 192,
|
"id": 192,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "SylvanCentaur" ],
|
"name": [ "SylvanCentaur" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "ZM192Z.DEF",
|
"defname": "ZM192Z.DEF",
|
||||||
"projectile_defname": "PELFX.DEF",
|
"projectile_defname": "PELFX.DEF",
|
||||||
"projectile_spin": false
|
"projectile_spin": false
|
||||||
@ -1955,7 +1955,7 @@
|
|||||||
"id": 193,
|
"id": 193,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "Sorceress" ],
|
"name": [ "Sorceress" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "ZM193Z.DEF",
|
"defname": "ZM193Z.DEF",
|
||||||
"projectile_defname": "CPRZEAX.DEF",
|
"projectile_defname": "CPRZEAX.DEF",
|
||||||
"projectile_spin": false
|
"projectile_spin": false
|
||||||
@ -1965,7 +1965,7 @@
|
|||||||
"id": 194,
|
"id": 194,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "Werewolf" ],
|
"name": [ "Werewolf" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "ZM194Z.DEF"
|
"defname": "ZM194Z.DEF"
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1973,7 +1973,7 @@
|
|||||||
"id": 195,
|
"id": 195,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "HellSteed" ],
|
"name": [ "HellSteed" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "ZM195Z.DEF"
|
"defname": "ZM195Z.DEF"
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1981,7 +1981,7 @@
|
|||||||
"id": 196,
|
"id": 196,
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"name": [ "Dracolich" ],
|
"name": [ "Dracolich" ],
|
||||||
"faction": -1,
|
"faction": 9,
|
||||||
"defname": "ZM196Z.DEF",
|
"defname": "ZM196Z.DEF",
|
||||||
"projectile_defname": "SMBALX.DEF",
|
"projectile_defname": "SMBALX.DEF",
|
||||||
"projectile_spin": false
|
"projectile_spin": false
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
"CREEP_SIZE": 4000,
|
"CREEP_SIZE": 4000,
|
||||||
"WEEKLY_GROWTH_PERCENT" : 10,
|
"WEEKLY_GROWTH_PERCENT" : 10,
|
||||||
"NEUTRAL_STACK_EXP_DAILY" : 500,
|
"NEUTRAL_STACK_EXP_DAILY" : 500,
|
||||||
|
"MAX_BUILDING_PER_TURN" : 1,
|
||||||
"DWELLINGS_ACCUMULATE_CREATURES" : true,
|
"DWELLINGS_ACCUMULATE_CREATURES" : true,
|
||||||
"ALL_CREATURES_GET_DOUBLE_MONTHS" : false
|
"ALL_CREATURES_GET_DOUBLE_MONTHS" : false
|
||||||
},
|
},
|
||||||
|
@ -1,52 +1,13 @@
|
|||||||
{
|
{
|
||||||
// Terrains properties related to heroes - ordered by faction (0 to 8)
|
// Movement costs on different terrains
|
||||||
// cost: ??
|
"dirt" : 100,
|
||||||
// native: native terrain for the faction
|
"sand" : 150,
|
||||||
|
"grass" : 100,
|
||||||
"terrains": [
|
"snow" : 150,
|
||||||
{
|
"swamp" : 175,
|
||||||
"costs": [ 100, 150, 100, 150, 175, 125, 100, 100, 100, -1 ],
|
"rough" : 125,
|
||||||
"native": 2
|
"subterra" : 100,
|
||||||
},
|
"lava" : 100,
|
||||||
|
"water" : 100,
|
||||||
{
|
"rock" : -1,
|
||||||
"costs": [ 100, 150, 100, 150, 175, 125, 100, 100, 100, -1 ],
|
|
||||||
"native": 2
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"costs": [ 100, 150, 100, 100, 175, 125, 100, 100, 100, -1 ],
|
|
||||||
"native": 3
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"costs": [ 100, 150, 100, 150, 175, 125, 100, 100, 100, -1 ],
|
|
||||||
"native": 7
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"costs": [ 100, 150, 100, 150, 175, 125, 100, 100, 100, -1 ],
|
|
||||||
"native": 0
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"costs": [ 100, 150, 100, 150, 175, 125, 100, 100, 100, -1 ],
|
|
||||||
"native": 6
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"costs": [ 100, 150, 100, 150, 175, 100, 100, 100, 100, -1 ],
|
|
||||||
"native": 5
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"costs": [ 100, 150, 100, 150, 100, 125, 100, 100, 100, -1 ],
|
|
||||||
"native": 4
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"costs": [ 100, 150, 100, 150, 175, 125, 100, 100, 100, -1 ],
|
|
||||||
"native": 2
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
// Some town pictures, ordered by the town number (0 to 8)
|
|
||||||
// town_background: background inside the town
|
|
||||||
// guild_background: background inside the mage guild
|
|
||||||
// building_picture: picture inside the city hall
|
|
||||||
"town_pictures": [
|
|
||||||
{ "town_background": "TBCSBACK.bmp", "guild_background": "TPMAGECS.bmp", "building_picture": "HALLCSTL.DEF" },
|
|
||||||
{ "town_background": "TBRMBACK.bmp", "guild_background": "TPMAGERM.bmp", "building_picture": "HALLRAMP.DEF" },
|
|
||||||
{ "town_background": "TBTWBACK.bmp", "guild_background": "TPMAGETW.bmp", "building_picture": "HALLTOWR.DEF" },
|
|
||||||
{ "town_background": "TBINBACK.bmp", "guild_background": "TPMAGEIN.bmp", "building_picture": "HALLINFR.DEF" },
|
|
||||||
{ "town_background": "TBNCBACK.bmp", "guild_background": "TPMAGENC.bmp", "building_picture": "HALLNECR.DEF" },
|
|
||||||
{ "town_background": "TBDNBACK.bmp", "guild_background": "TPMAGEDN.bmp", "building_picture": "HALLDUNG.DEF" },
|
|
||||||
{ "town_background": "TBSTBACK.bmp", "guild_background": "TPMAGEST.bmp", "building_picture": "HALLSTRN.DEF" },
|
|
||||||
{ "town_background": "TBFRBACK.bmp", "guild_background": "TPMAGEFR.bmp", "building_picture": "HALLFORT.DEF" },
|
|
||||||
{ "town_background": "TBELBACK.bmp", "guild_background": "TPMAGEEL.bmp", "building_picture": "HALLELEM.DEF" }
|
|
||||||
]
|
|
||||||
}
|
|
@ -596,7 +596,7 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, int terrain, int battlefieldTyp
|
|||||||
{
|
{
|
||||||
curB->town = town;
|
curB->town = town;
|
||||||
curB->siege = town->fortLevel();
|
curB->siege = town->fortLevel();
|
||||||
curB->terrainType = VLC->heroh->nativeTerrains[town->town->typeID];
|
curB->terrainType = VLC->townh->factions[town->town->typeID].nativeTerrain;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -321,7 +321,7 @@ bool CBattleInfoEssentials::battleCanFlee(int player) const
|
|||||||
if(mySide == BattleSide::DEFENDER && battleGetSiegeLevel())
|
if(mySide == BattleSide::DEFENDER && battleGetSiegeLevel())
|
||||||
{
|
{
|
||||||
auto town = battleGetDefendedTown();
|
auto town = battleGetDefendedTown();
|
||||||
if(!(town->subID == 6 && town->hasBuilt(EBuilding::SPECIAL_1))) //not a stronghold with escape tunnel
|
if(!town->hasBuilt(EBuilding::ESCAPE_TUNNEL, ETownType::STRONGHOLD))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#include "Filesystem/CResourceLoader.h"
|
#include "Filesystem/CResourceLoader.h"
|
||||||
#include "VCMI_Lib.h"
|
#include "VCMI_Lib.h"
|
||||||
#include "CGameState.h"
|
#include "CGameState.h"
|
||||||
#include "CHeroHandler.h"
|
#include "CTownHandler.h"
|
||||||
#include "CModHandler.h"
|
#include "CModHandler.h"
|
||||||
|
|
||||||
using namespace boost::assign;
|
using namespace boost::assign;
|
||||||
@ -148,11 +148,9 @@ std::string CCreature::nodeName() const
|
|||||||
|
|
||||||
bool CCreature::isItNativeTerrain(int terrain) const
|
bool CCreature::isItNativeTerrain(int terrain) const
|
||||||
{
|
{
|
||||||
if(!vstd::iswithin(faction, 0, 9))
|
assert(vstd::contains(VLC->townh->factions, faction));
|
||||||
return false;
|
|
||||||
|
|
||||||
//not good handler dependency
|
//not good handler dependency
|
||||||
return VLC->heroh->nativeTerrains[faction] == terrain;
|
return VLC->townh->factions[faction].nativeTerrain == terrain;
|
||||||
}
|
}
|
||||||
|
|
||||||
int readNumber(int & befi, int & i, int andame, std::string & buf) //helper function for void CCreatureHandler::loadCreatures() and loadUnitAnimInfo()
|
int readNumber(int & befi, int & i, int andame, std::string & buf) //helper function for void CCreatureHandler::loadCreatures() and loadUnitAnimInfo()
|
||||||
|
@ -528,7 +528,12 @@ std::pair<int,int> CGameState::pickObject (CGObjectInstance *obj)
|
|||||||
{
|
{
|
||||||
f = scenarioOps->getIthPlayersSettings(align).castle;
|
f = scenarioOps->getIthPlayersSettings(align).castle;
|
||||||
}
|
}
|
||||||
if(f<0) f = ran()%VLC->townh->towns.size();
|
if(f<0)
|
||||||
|
{
|
||||||
|
auto iter = VLC->townh->towns.begin();
|
||||||
|
std::advance(iter, ran()%VLC->townh->towns.size());
|
||||||
|
f = iter->first;
|
||||||
|
}
|
||||||
return std::pair<int,int>(GameConstants::TOWNI_TYPE,f);
|
return std::pair<int,int>(GameConstants::TOWNI_TYPE,f);
|
||||||
}
|
}
|
||||||
case 162: //random monster lvl5
|
case 162: //random monster lvl5
|
||||||
@ -1290,15 +1295,15 @@ void CGameState::init(StartInfo * si)
|
|||||||
if(vti->builtBuildings.find(-50)!=vti->builtBuildings.end()) //give standard set of buildings
|
if(vti->builtBuildings.find(-50)!=vti->builtBuildings.end()) //give standard set of buildings
|
||||||
{
|
{
|
||||||
vti->builtBuildings.erase(-50);
|
vti->builtBuildings.erase(-50);
|
||||||
vti->builtBuildings.insert(10);
|
vti->builtBuildings.insert(EBuilding::VILLAGE_HALL);
|
||||||
vti->builtBuildings.insert(5);
|
vti->builtBuildings.insert(EBuilding::TAVERN);
|
||||||
vti->builtBuildings.insert(30);
|
vti->builtBuildings.insert(EBuilding::DWELL_FIRST);
|
||||||
if(ran()%2)
|
if(ran()%2)
|
||||||
vti->builtBuildings.insert(31);
|
vti->builtBuildings.insert(EBuilding::DWELL_FIRST+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vstd::contains(vti->builtBuildings,(6)) && vti->state()==2)
|
if (vstd::contains(vti->builtBuildings, EBuilding::SHIPYARD) && vti->state()==2)
|
||||||
vti->builtBuildings.erase(6);//if we have harbor without water - erase it (this is H3 behaviour)
|
vti->builtBuildings.erase(EBuilding::SHIPYARD);//if we have harbor without water - erase it (this is H3 behaviour)
|
||||||
|
|
||||||
//init hordes
|
//init hordes
|
||||||
for (int i = 0; i<GameConstants::CREATURES_PER_TOWN; i++)
|
for (int i = 0; i<GameConstants::CREATURES_PER_TOWN; i++)
|
||||||
@ -1307,15 +1312,15 @@ void CGameState::init(StartInfo * si)
|
|||||||
vti->builtBuildings.erase(-31-i);//remove old ID
|
vti->builtBuildings.erase(-31-i);//remove old ID
|
||||||
if (vti->town->hordeLvl[0] == i)//if town first horde is this one
|
if (vti->town->hordeLvl[0] == i)//if town first horde is this one
|
||||||
{
|
{
|
||||||
vti->builtBuildings.insert(18);//add it
|
vti->builtBuildings.insert(EBuilding::HORDE_1);//add it
|
||||||
if (vstd::contains(vti->builtBuildings,(37+i)))//if we have upgraded dwelling as well
|
if (vstd::contains(vti->builtBuildings,(EBuilding::DWELL_UP_FIRST+i)))//if we have upgraded dwelling as well
|
||||||
vti->builtBuildings.insert(19);//add it as well
|
vti->builtBuildings.insert(EBuilding::HORDE_1_UPGR);//add it as well
|
||||||
}
|
}
|
||||||
if (vti->town->hordeLvl[1] == i)//if town second horde is this one
|
if (vti->town->hordeLvl[1] == i)//if town second horde is this one
|
||||||
{
|
{
|
||||||
vti->builtBuildings.insert(24);
|
vti->builtBuildings.insert(EBuilding::HORDE_2);
|
||||||
if (vstd::contains(vti->builtBuildings,(37+i)))
|
if (vstd::contains(vti->builtBuildings,(EBuilding::DWELL_UP_FIRST+i)))
|
||||||
vti->builtBuildings.insert(25);
|
vti->builtBuildings.insert(EBuilding::HORDE_2_UPGR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1327,9 +1332,9 @@ void CGameState::init(StartInfo * si)
|
|||||||
{
|
{
|
||||||
ev->buildings.erase(-31-i);
|
ev->buildings.erase(-31-i);
|
||||||
if (vti->town->hordeLvl[0] == i)
|
if (vti->town->hordeLvl[0] == i)
|
||||||
ev->buildings.insert(18);
|
ev->buildings.insert(EBuilding::HORDE_1);
|
||||||
if (vti->town->hordeLvl[1] == i)
|
if (vti->town->hordeLvl[1] == i)
|
||||||
ev->buildings.insert(24);
|
ev->buildings.insert(EBuilding::HORDE_2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//init spells
|
//init spells
|
||||||
@ -2058,7 +2063,7 @@ int CGameState::victoryCheck( ui8 player ) const
|
|||||||
BOOST_FOREACH(const CGTownInstance *t, map->towns)
|
BOOST_FOREACH(const CGTownInstance *t, map->towns)
|
||||||
if((t == map->victoryCondition.obj || !map->victoryCondition.obj)
|
if((t == map->victoryCondition.obj || !map->victoryCondition.obj)
|
||||||
&& t->tempOwner == player
|
&& t->tempOwner == player
|
||||||
&& vstd::contains(t->builtBuildings, EBuilding::GRAIL))
|
&& t->hasBuilt(EBuilding::GRAIL))
|
||||||
return 1;
|
return 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -2687,7 +2692,7 @@ void InfoAboutTown::initFromTown(const CGTownInstance *t, bool detailed)
|
|||||||
//include details about hero
|
//include details about hero
|
||||||
details = new Details;
|
details = new Details;
|
||||||
details->goldIncome = t->dailyIncome();
|
details->goldIncome = t->dailyIncome();
|
||||||
details->customRes = vstd::contains(t->builtBuildings, 15);
|
details->customRes = t->hasBuilt(EBuilding::RESOURCE_SILO);
|
||||||
details->hallLevel = t->hallLevel();
|
details->hallLevel = t->hallLevel();
|
||||||
details->garrisonedHero = t->garrisonHero;
|
details->garrisonedHero = t->garrisonHero;
|
||||||
}
|
}
|
||||||
|
@ -356,26 +356,11 @@ ui64 CHeroHandler::reqExp (ui32 level) const
|
|||||||
|
|
||||||
void CHeroHandler::loadTerrains()
|
void CHeroHandler::loadTerrains()
|
||||||
{
|
{
|
||||||
int faction = 0;
|
|
||||||
const JsonNode config(ResourceID("config/terrains.json"));
|
const JsonNode config(ResourceID("config/terrains.json"));
|
||||||
|
|
||||||
nativeTerrains.resize(GameConstants::F_NUMBER);
|
terrCosts.reserve(GameConstants::TERRAIN_TYPES);
|
||||||
|
BOOST_FOREACH(const std::string & name, GameConstants::TERRAIN_NAMES)
|
||||||
BOOST_FOREACH(const JsonNode &terrain, config["terrains"].Vector()) {
|
terrCosts.push_back(config[name].Float());
|
||||||
|
|
||||||
BOOST_FOREACH(const JsonNode &cost, terrain["costs"].Vector()) {
|
|
||||||
int curCost = cost.Float();
|
|
||||||
|
|
||||||
heroClasses[2*faction]->terrCosts.push_back(curCost);
|
|
||||||
heroClasses[2*faction+1]->terrCosts.push_back(curCost);
|
|
||||||
}
|
|
||||||
|
|
||||||
nativeTerrains[faction] = terrain["native"].Float();
|
|
||||||
|
|
||||||
faction ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(faction == GameConstants::F_NUMBER);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CHero::CHero()
|
CHero::CHero()
|
||||||
|
@ -69,7 +69,6 @@ public:
|
|||||||
std::vector<std::pair<int,int> > primChance;//primChance[PRIMARY_SKILL_ID] - first is for levels 2 - 9, second for 10+;;; probability (%) of getting point of primary skill when getting new level
|
std::vector<std::pair<int,int> > primChance;//primChance[PRIMARY_SKILL_ID] - first is for levels 2 - 9, second for 10+;;; probability (%) of getting point of primary skill when getting new level
|
||||||
std::vector<int> proSec; //probabilities of gaining secondary skills (out of 112), in id order
|
std::vector<int> proSec; //probabilities of gaining secondary skills (out of 112), in id order
|
||||||
int selectionProbability[9]; //probability of selection in towns
|
int selectionProbability[9]; //probability of selection in towns
|
||||||
std::vector<int> terrCosts; //default costs of going through terrains: dirt, sand, grass, snow, swamp, rough, subterranean, lava, water, rock; -1 means terrain is imapassable
|
|
||||||
|
|
||||||
int chooseSecSkill(const std::set<int> & possibles) const; //picks secondary skill out from given possibilities
|
int chooseSecSkill(const std::set<int> & possibles) const; //picks secondary skill out from given possibilities
|
||||||
CHeroClass(); //c-tor
|
CHeroClass(); //c-tor
|
||||||
@ -78,7 +77,7 @@ public:
|
|||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & skillLimit & name & aggression & initialAttack & initialDefence & initialPower & initialKnowledge & primChance
|
h & skillLimit & name & aggression & initialAttack & initialDefence & initialPower & initialKnowledge & primChance
|
||||||
& proSec & selectionProbability & terrCosts & alignment;
|
& proSec & selectionProbability & alignment;
|
||||||
}
|
}
|
||||||
EAlignment::EAlignment getAlignment();
|
EAlignment::EAlignment getAlignment();
|
||||||
};
|
};
|
||||||
@ -126,6 +125,9 @@ public:
|
|||||||
std::vector<CHeroClass *> heroClasses;
|
std::vector<CHeroClass *> heroClasses;
|
||||||
std::vector<ui64> expPerLevel; //expPerLEvel[i] is amount of exp needed to reach level i; if it is not in this vector, multiplicate last value by 1,2 to get next value
|
std::vector<ui64> expPerLevel; //expPerLEvel[i] is amount of exp needed to reach level i; if it is not in this vector, multiplicate last value by 1,2 to get next value
|
||||||
|
|
||||||
|
//default costs of going through terrains: dirt, sand, grass, snow, swamp, rough, subterranean, lava, water, rock; -1 means terrain is imapassable
|
||||||
|
std::vector<int> terrCosts;
|
||||||
|
|
||||||
struct SBallisticsLevelInfo
|
struct SBallisticsLevelInfo
|
||||||
{
|
{
|
||||||
ui8 keep, tower, gate, wall; //chance to hit in percent (eg. 87 is 87%)
|
ui8 keep, tower, gate, wall; //chance to hit in percent (eg. 87 is 87%)
|
||||||
@ -142,8 +144,6 @@ public:
|
|||||||
std::map<int, CObstacleInfo> obstacles; //info about obstacles that may be placed on battlefield
|
std::map<int, CObstacleInfo> obstacles; //info about obstacles that may be placed on battlefield
|
||||||
std::map<int, CObstacleInfo> absoluteObstacles; //info about obstacles that may be placed on battlefield
|
std::map<int, CObstacleInfo> absoluteObstacles; //info about obstacles that may be placed on battlefield
|
||||||
|
|
||||||
std::vector<int> nativeTerrains; //info about native terrains of different factions
|
|
||||||
|
|
||||||
void loadObstacles(); //loads info about obstacles
|
void loadObstacles(); //loads info about obstacles
|
||||||
|
|
||||||
std::vector<SPuzzleInfo> puzzleInfo[GameConstants::F_NUMBER]; //descriptions of puzzles
|
std::vector<SPuzzleInfo> puzzleInfo[GameConstants::F_NUMBER]; //descriptions of puzzles
|
||||||
@ -161,7 +161,7 @@ public:
|
|||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & heroClasses & heroes & expPerLevel & ballistics & nativeTerrains & puzzleInfo;
|
h & heroClasses & heroes & expPerLevel & ballistics & terrCosts & puzzleInfo;
|
||||||
h & obstacles & absoluteObstacles;
|
h & obstacles & absoluteObstacles;
|
||||||
if(!h.saving)
|
if(!h.saving)
|
||||||
{
|
{
|
||||||
|
@ -53,6 +53,7 @@ void CModHandler::loadConfigFromFile (std::string name)
|
|||||||
settings.CREEP_SIZE = hardcodedFeatures["CREEP_SIZE"].Float();
|
settings.CREEP_SIZE = hardcodedFeatures["CREEP_SIZE"].Float();
|
||||||
settings.WEEKLY_GROWTH = hardcodedFeatures["WEEKLY_GROWTH_PERCENT"].Float();
|
settings.WEEKLY_GROWTH = hardcodedFeatures["WEEKLY_GROWTH_PERCENT"].Float();
|
||||||
settings.NEUTRAL_STACK_EXP = hardcodedFeatures["NEUTRAL_STACK_EXP_DAILY"].Float();
|
settings.NEUTRAL_STACK_EXP = hardcodedFeatures["NEUTRAL_STACK_EXP_DAILY"].Float();
|
||||||
|
settings.MAX_BUILDING_PER_TURN = hardcodedFeatures["MAX_BUILDING_PER_TURN"].Float();
|
||||||
settings.DWELLINGS_ACCUMULATE_CREATURES = hardcodedFeatures["DWELLINGS_ACCUMULATE_CREATURES"].Bool();
|
settings.DWELLINGS_ACCUMULATE_CREATURES = hardcodedFeatures["DWELLINGS_ACCUMULATE_CREATURES"].Bool();
|
||||||
settings.ALL_CREATURES_GET_DOUBLE_MONTHS = hardcodedFeatures["ALL_CREATURES_GET_DOUBLE_MONTHS"].Bool();
|
settings.ALL_CREATURES_GET_DOUBLE_MONTHS = hardcodedFeatures["ALL_CREATURES_GET_DOUBLE_MONTHS"].Bool();
|
||||||
|
|
||||||
@ -125,11 +126,7 @@ CCreature * CModHandler::loadCreature (const JsonNode &node)
|
|||||||
if (!value->isNull())
|
if (!value->isNull())
|
||||||
cre->addBonus(value->Float(), Bonus::CASTS);
|
cre->addBonus(value->Float(), Bonus::CASTS);
|
||||||
|
|
||||||
value = &node["doubleWide"];
|
|
||||||
if (!value->isNull())
|
|
||||||
cre->doubleWide = value->Bool();
|
cre->doubleWide = value->Bool();
|
||||||
else
|
|
||||||
cre->doubleWide = false;
|
|
||||||
|
|
||||||
value = &node["abilities"];
|
value = &node["abilities"];
|
||||||
if (!value->isNull())
|
if (!value->isNull())
|
||||||
|
@ -83,6 +83,7 @@ public:
|
|||||||
int CREEP_SIZE; // neutral stacks won't grow beyond this number
|
int CREEP_SIZE; // neutral stacks won't grow beyond this number
|
||||||
int WEEKLY_GROWTH; //percent
|
int WEEKLY_GROWTH; //percent
|
||||||
int NEUTRAL_STACK_EXP;
|
int NEUTRAL_STACK_EXP;
|
||||||
|
int MAX_BUILDING_PER_TURN;
|
||||||
bool DWELLINGS_ACCUMULATE_CREATURES;
|
bool DWELLINGS_ACCUMULATE_CREATURES;
|
||||||
bool ALL_CREATURES_GET_DOUBLE_MONTHS;
|
bool ALL_CREATURES_GET_DOUBLE_MONTHS;
|
||||||
|
|
||||||
|
@ -553,7 +553,10 @@ ui32 CGHeroInstance::getTileCost(const TerrainTile &dest, const TerrainTile &fro
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ret = type->heroClass->terrCosts[from.tertype];
|
assert(vstd::contains(VLC->townh->factions, type->heroType / 2));
|
||||||
|
if (VLC->townh->factions[type->heroType / 2].nativeTerrain != from.tertype) //non-native terrain
|
||||||
|
ret = VLC->heroh->terrCosts[from.tertype];
|
||||||
|
|
||||||
ret = std::max(ret - 25*unsigned(getSecSkillLevel(CGHeroInstance::PATHFINDING)), 100u); //reduce 25% of terrain penalty for each pathfinding level
|
ret = std::max(ret - 25*unsigned(getSecSkillLevel(CGHeroInstance::PATHFINDING)), 100u); //reduce 25% of terrain penalty for each pathfinding level
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@ -1820,11 +1823,11 @@ void CGDwelling::fightOver(const CGHeroInstance *h, BattleResult *result) const
|
|||||||
|
|
||||||
int CGTownInstance::getSightRadious() const //returns sight distance
|
int CGTownInstance::getSightRadious() const //returns sight distance
|
||||||
{
|
{
|
||||||
if (subID == 2) //tower
|
if (subID == ETownType::TOWER)
|
||||||
{
|
{
|
||||||
if ((builtBuildings.find(26)) != builtBuildings.end()) //skyship
|
if (hasBuilt(EBuilding::GRAIL)) //skyship
|
||||||
return -1; //entire map
|
return -1; //entire map
|
||||||
else if ((builtBuildings.find(21)) != builtBuildings.end()) //lookout tower
|
else if (hasBuilt(EBuilding::LOOKOUT_TOWER)) //lookout tower
|
||||||
return 20;
|
return 20;
|
||||||
}
|
}
|
||||||
return 5;
|
return 5;
|
||||||
@ -1854,38 +1857,38 @@ void CGTownInstance::setPropertyDer(ui8 what, ui32 val)
|
|||||||
}
|
}
|
||||||
CGTownInstance::EFortLevel CGTownInstance::fortLevel() const //0 - none, 1 - fort, 2 - citadel, 3 - castle
|
CGTownInstance::EFortLevel CGTownInstance::fortLevel() const //0 - none, 1 - fort, 2 - citadel, 3 - castle
|
||||||
{
|
{
|
||||||
if((builtBuildings.find(9))!=builtBuildings.end())
|
if (hasBuilt(EBuilding::CASTLE))
|
||||||
return CASTLE;
|
return CASTLE;
|
||||||
if((builtBuildings.find(8))!=builtBuildings.end())
|
if (hasBuilt(EBuilding::CITADEL))
|
||||||
return CITADEL;
|
return CITADEL;
|
||||||
if((builtBuildings.find(7))!=builtBuildings.end())
|
if (hasBuilt(EBuilding::FORT))
|
||||||
return FORT;
|
return FORT;
|
||||||
return NONE;
|
return NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CGTownInstance::hallLevel() const // -1 - none, 0 - village, 1 - town, 2 - city, 3 - capitol
|
int CGTownInstance::hallLevel() const // -1 - none, 0 - village, 1 - town, 2 - city, 3 - capitol
|
||||||
{
|
{
|
||||||
if ((builtBuildings.find(13))!=builtBuildings.end())
|
if (hasBuilt(EBuilding::CAPITOL))
|
||||||
return 3;
|
return 3;
|
||||||
if ((builtBuildings.find(12))!=builtBuildings.end())
|
if (hasBuilt(EBuilding::CITY_HALL))
|
||||||
return 2;
|
return 2;
|
||||||
if ((builtBuildings.find(11))!=builtBuildings.end())
|
if (hasBuilt(EBuilding::TOWN_HALL))
|
||||||
return 1;
|
return 1;
|
||||||
if ((builtBuildings.find(10))!=builtBuildings.end())
|
if (hasBuilt(EBuilding::VILLAGE_HALL))
|
||||||
return 0;
|
return 0;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
int CGTownInstance::mageGuildLevel() const
|
int CGTownInstance::mageGuildLevel() const
|
||||||
{
|
{
|
||||||
if ((builtBuildings.find(4))!=builtBuildings.end())
|
if (hasBuilt(EBuilding::MAGES_GUILD_5))
|
||||||
return 5;
|
return 5;
|
||||||
if ((builtBuildings.find(3))!=builtBuildings.end())
|
if (hasBuilt(EBuilding::MAGES_GUILD_4))
|
||||||
return 4;
|
return 4;
|
||||||
if ((builtBuildings.find(2))!=builtBuildings.end())
|
if (hasBuilt(EBuilding::MAGES_GUILD_3))
|
||||||
return 3;
|
return 3;
|
||||||
if ((builtBuildings.find(1))!=builtBuildings.end())
|
if (hasBuilt(EBuilding::MAGES_GUILD_2))
|
||||||
return 2;
|
return 2;
|
||||||
if ((builtBuildings.find(0))!=builtBuildings.end())
|
if (hasBuilt(EBuilding::MAGES_GUILD_1))
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1896,7 +1899,7 @@ int CGTownInstance::creatureDwellingLevel(int dwelling) const
|
|||||||
return -1;
|
return -1;
|
||||||
for (int i=0; ; i++)
|
for (int i=0; ; i++)
|
||||||
{
|
{
|
||||||
if (!vstd::contains(builtBuildings, 30+dwelling+i*GameConstants::CREATURES_PER_TOWN))
|
if (!hasBuilt(EBuilding::DWELL_FIRST+dwelling+i*GameConstants::CREATURES_PER_TOWN))
|
||||||
return i-1;
|
return i-1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1915,7 +1918,7 @@ GrowthInfo CGTownInstance::getGrowthInfo(int level) const
|
|||||||
|
|
||||||
if (level<0 || level >=GameConstants::CREATURES_PER_TOWN)
|
if (level<0 || level >=GameConstants::CREATURES_PER_TOWN)
|
||||||
return ret;
|
return ret;
|
||||||
if (!vstd::contains(builtBuildings, EBuilding::DWELL_FIRST+level))
|
if (!hasBuilt(EBuilding::DWELL_FIRST+level))
|
||||||
return ret; //no dwelling
|
return ret; //no dwelling
|
||||||
|
|
||||||
const CCreature *creature = VLC->creh->creatures[creatures[level].second.back()];
|
const CCreature *creature = VLC->creh->creatures[creatures[level].second.back()];
|
||||||
@ -1924,17 +1927,17 @@ GrowthInfo CGTownInstance::getGrowthInfo(int level) const
|
|||||||
|
|
||||||
ret.entries.push_back(GrowthInfo::Entry(VLC->generaltexth->allTexts[590], base));// \n\nBasic growth %d"
|
ret.entries.push_back(GrowthInfo::Entry(VLC->generaltexth->allTexts[590], base));// \n\nBasic growth %d"
|
||||||
|
|
||||||
if ( vstd::contains(builtBuildings, EBuilding::CASTLE))
|
if (hasBuilt(EBuilding::CASTLE))
|
||||||
ret.entries.push_back(GrowthInfo::Entry(subID, EBuilding::CASTLE, castleBonus = base));
|
ret.entries.push_back(GrowthInfo::Entry(subID, EBuilding::CASTLE, castleBonus = base));
|
||||||
else if ( vstd::contains(builtBuildings, EBuilding::CITADEL))
|
else if (hasBuilt(EBuilding::CITADEL))
|
||||||
ret.entries.push_back(GrowthInfo::Entry(subID, EBuilding::CITADEL, castleBonus = base / 2));
|
ret.entries.push_back(GrowthInfo::Entry(subID, EBuilding::CITADEL, castleBonus = base / 2));
|
||||||
|
|
||||||
if(town->hordeLvl[0] == level)//horde 1
|
if(town->hordeLvl[0] == level)//horde 1
|
||||||
if( vstd::contains(builtBuildings, EBuilding::HORDE_1) || vstd::contains(builtBuildings, EBuilding::HORDE_1_UPGR))
|
if(hasBuilt(EBuilding::HORDE_1))
|
||||||
ret.entries.push_back(GrowthInfo::Entry(subID, EBuilding::HORDE_1, creature->hordeGrowth));
|
ret.entries.push_back(GrowthInfo::Entry(subID, EBuilding::HORDE_1, creature->hordeGrowth));
|
||||||
|
|
||||||
if(town->hordeLvl[1] == level)//horde 2
|
if(town->hordeLvl[1] == level)//horde 2
|
||||||
if(vstd::contains(builtBuildings, EBuilding::HORDE_2) || vstd::contains(builtBuildings, EBuilding::HORDE_2_UPGR))
|
if(hasBuilt(EBuilding::HORDE_2))
|
||||||
ret.entries.push_back(GrowthInfo::Entry(subID, EBuilding::HORDE_2, creature->hordeGrowth));
|
ret.entries.push_back(GrowthInfo::Entry(subID, EBuilding::HORDE_2, creature->hordeGrowth));
|
||||||
|
|
||||||
int dwellingBonus = 0;
|
int dwellingBonus = 0;
|
||||||
@ -1958,7 +1961,7 @@ GrowthInfo CGTownInstance::getGrowthInfo(int level) const
|
|||||||
BOOST_FOREACH(const Bonus *b, *bonuses2)
|
BOOST_FOREACH(const Bonus *b, *bonuses2)
|
||||||
ret.entries.push_back(GrowthInfo::Entry(b->Description() + " %+d", b->val * (base + castleBonus) / 100));
|
ret.entries.push_back(GrowthInfo::Entry(b->Description() + " %+d", b->val * (base + castleBonus) / 100));
|
||||||
|
|
||||||
if(vstd::contains(builtBuildings, EBuilding::GRAIL)) //grail - +50% to ALL (so far added) growth
|
if(hasBuilt(EBuilding::GRAIL)) //grail - +50% to ALL (so far added) growth
|
||||||
ret.entries.push_back(GrowthInfo::Entry(subID, EBuilding::GRAIL, ret.totalGrowth() / 2));
|
ret.entries.push_back(GrowthInfo::Entry(subID, EBuilding::GRAIL, ret.totalGrowth() / 2));
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -1967,25 +1970,26 @@ GrowthInfo CGTownInstance::getGrowthInfo(int level) const
|
|||||||
int CGTownInstance::dailyIncome() const
|
int CGTownInstance::dailyIncome() const
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
if ((builtBuildings.find(26))!=builtBuildings.end())
|
if (hasBuilt(EBuilding::GRAIL))
|
||||||
ret+=5000;
|
ret+=5000;
|
||||||
if ((builtBuildings.find(13))!=builtBuildings.end())
|
|
||||||
|
if (hasBuilt(EBuilding::CAPITOL))
|
||||||
ret+=4000;
|
ret+=4000;
|
||||||
else if ((builtBuildings.find(12))!=builtBuildings.end())
|
else if (hasBuilt(EBuilding::CITY_HALL))
|
||||||
ret+=2000;
|
ret+=2000;
|
||||||
else if ((builtBuildings.find(11))!=builtBuildings.end())
|
else if (hasBuilt(EBuilding::TOWN_HALL))
|
||||||
ret+=1000;
|
ret+=1000;
|
||||||
else if ((builtBuildings.find(10))!=builtBuildings.end())
|
else if (hasBuilt(EBuilding::VILLAGE_HALL))
|
||||||
ret+=500;
|
ret+=500;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
bool CGTownInstance::hasFort() const
|
bool CGTownInstance::hasFort() const
|
||||||
{
|
{
|
||||||
return (builtBuildings.find(7))!=builtBuildings.end();
|
return hasBuilt(EBuilding::FORT);
|
||||||
}
|
}
|
||||||
bool CGTownInstance::hasCapitol() const
|
bool CGTownInstance::hasCapitol() const
|
||||||
{
|
{
|
||||||
return (builtBuildings.find(13))!=builtBuildings.end();
|
return hasBuilt(EBuilding::CAPITOL);
|
||||||
}
|
}
|
||||||
CGTownInstance::CGTownInstance()
|
CGTownInstance::CGTownInstance()
|
||||||
:IShipyard(this), IMarket(this)
|
:IShipyard(this), IMarket(this)
|
||||||
@ -2006,8 +2010,10 @@ int CGTownInstance::spellsAtLevel(int level, bool checkGuild) const
|
|||||||
if(checkGuild && mageGuildLevel() < level)
|
if(checkGuild && mageGuildLevel() < level)
|
||||||
return 0;
|
return 0;
|
||||||
int ret = 6 - level; //how many spells are available at this level
|
int ret = 6 - level; //how many spells are available at this level
|
||||||
if(subID == 2 && vstd::contains(builtBuildings,22)) //magic library in Tower
|
|
||||||
|
if (hasBuilt(EBuilding::LIBRARY, ETownType::TOWER))
|
||||||
ret++;
|
ret++;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2074,7 +2080,7 @@ void CGTownInstance::initObj()
|
|||||||
blockVisit = true;
|
blockVisit = true;
|
||||||
hoverName = name + ", " + town->Name();
|
hoverName = name + ", " + town->Name();
|
||||||
|
|
||||||
if (subID == 5)
|
if (subID == ETownType::DUNGEON)
|
||||||
creatures.resize(GameConstants::CREATURES_PER_TOWN+1);//extra dwelling for Dungeon
|
creatures.resize(GameConstants::CREATURES_PER_TOWN+1);//extra dwelling for Dungeon
|
||||||
else
|
else
|
||||||
creatures.resize(GameConstants::CREATURES_PER_TOWN);
|
creatures.resize(GameConstants::CREATURES_PER_TOWN);
|
||||||
@ -2109,7 +2115,9 @@ void CGTownInstance::newTurn() const
|
|||||||
{
|
{
|
||||||
if (cb->getDate(1) == 1) //reset on new week
|
if (cb->getDate(1) == 1) //reset on new week
|
||||||
{
|
{
|
||||||
if (vstd::contains(builtBuildings,17) && subID == 1 && cb->getDate(0) != 1 && (tempOwner < GameConstants::PLAYER_LIMIT) )//give resources for Rampart, Mystic Pond
|
//give resources for Rampart, Mystic Pond
|
||||||
|
if (hasBuilt(EBuilding::MYSTIC_POND, ETownType::RAMPART)
|
||||||
|
&& cb->getDate(0) != 1 && (tempOwner < GameConstants::PLAYER_LIMIT))
|
||||||
{
|
{
|
||||||
int resID = rand()%4+2;//bonus to random rare resource
|
int resID = rand()%4+2;//bonus to random rare resource
|
||||||
resID = (resID==2)?1:resID;
|
resID = (resID==2)?1:resID;
|
||||||
@ -2119,10 +2127,10 @@ void CGTownInstance::newTurn() const
|
|||||||
cb->setObjProperty (id, 15, resVal);
|
cb->setObjProperty (id, 15, resVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( subID == 5 )
|
if ( subID == ETownType::DUNGEON )
|
||||||
for (std::vector<CGTownBuilding*>::const_iterator i = bonusingBuildings.begin(); i!=bonusingBuildings.end(); i++)
|
for (std::vector<CGTownBuilding*>::const_iterator i = bonusingBuildings.begin(); i!=bonusingBuildings.end(); i++)
|
||||||
{
|
{
|
||||||
if ((*i)->ID == 21)
|
if ((*i)->ID == EBuilding::MANA_VORTEX)
|
||||||
cb->setObjProperty (id, 12, (*i)->id); //reset visitors for Mana Vortex
|
cb->setObjProperty (id, 12, (*i)->id); //reset visitors for Mana Vortex
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2249,7 +2257,7 @@ int CGTownInstance::getBoatType() const
|
|||||||
|
|
||||||
int CGTownInstance::getMarketEfficiency() const
|
int CGTownInstance::getMarketEfficiency() const
|
||||||
{
|
{
|
||||||
if(!vstd::contains(builtBuildings, 14))
|
if (!hasBuilt(EBuilding::MARKETPLACE))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
const PlayerState *p = cb->getPlayer(tempOwner);
|
const PlayerState *p = cb->getPlayer(tempOwner);
|
||||||
@ -2257,7 +2265,7 @@ int CGTownInstance::getMarketEfficiency() const
|
|||||||
|
|
||||||
int marketCount = 0;
|
int marketCount = 0;
|
||||||
BOOST_FOREACH(const CGTownInstance *t, p->towns)
|
BOOST_FOREACH(const CGTownInstance *t, p->towns)
|
||||||
if(vstd::contains(t->builtBuildings, 14))
|
if(t->hasBuilt(EBuilding::MARKETPLACE))
|
||||||
marketCount++;
|
marketCount++;
|
||||||
|
|
||||||
return marketCount;
|
return marketCount;
|
||||||
@ -2269,16 +2277,22 @@ bool CGTownInstance::allowsTrade(EMarketMode::EMarketMode mode) const
|
|||||||
{
|
{
|
||||||
case EMarketMode::RESOURCE_RESOURCE:
|
case EMarketMode::RESOURCE_RESOURCE:
|
||||||
case EMarketMode::RESOURCE_PLAYER:
|
case EMarketMode::RESOURCE_PLAYER:
|
||||||
return vstd::contains(builtBuildings, 14); // marketplace
|
return hasBuilt(EBuilding::MARKETPLACE);
|
||||||
|
|
||||||
case EMarketMode::ARTIFACT_RESOURCE:
|
case EMarketMode::ARTIFACT_RESOURCE:
|
||||||
case EMarketMode::RESOURCE_ARTIFACT:
|
case EMarketMode::RESOURCE_ARTIFACT:
|
||||||
return (subID == 2 || subID == 5 || subID == 8) && vstd::contains(builtBuildings, 17);//artifact merchants
|
return hasBuilt(EBuilding::ARTIFACT_MERCHANT, ETownType::TOWER)
|
||||||
|
|| hasBuilt(EBuilding::ARTIFACT_MERCHANT, ETownType::DUNGEON)
|
||||||
|
|| hasBuilt(EBuilding::ARTIFACT_MERCHANT, ETownType::CONFLUX);
|
||||||
|
|
||||||
case EMarketMode::CREATURE_RESOURCE:
|
case EMarketMode::CREATURE_RESOURCE:
|
||||||
return subID == 6 && vstd::contains(builtBuildings, 21); //Freelancer's guild
|
return hasBuilt(EBuilding::FREELANCERS_GUILD, ETownType::STRONGHOLD);
|
||||||
|
|
||||||
case EMarketMode::CREATURE_UNDEAD:
|
case EMarketMode::CREATURE_UNDEAD:
|
||||||
return subID == 4 && vstd::contains(builtBuildings, 22);//Skeleton transformer
|
return hasBuilt(EBuilding::SKELETON_TRANSFORMER, ETownType::NECROPOLIS);
|
||||||
|
|
||||||
case EMarketMode::RESOURCE_SKILL:
|
case EMarketMode::RESOURCE_SKILL:
|
||||||
return subID == 8 && vstd::contains(builtBuildings, 21);//Magic University
|
return hasBuilt(EBuilding::MAGIC_UNIVERSITY, ETownType::CONFLUX);
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
return false;
|
return false;
|
||||||
@ -2326,50 +2340,50 @@ void CGTownInstance::recreateBuildingsBonuses()
|
|||||||
BOOST_FOREACH(Bonus *b, bl)
|
BOOST_FOREACH(Bonus *b, bl)
|
||||||
removeBonus(b);
|
removeBonus(b);
|
||||||
|
|
||||||
|
//tricky! -> checks tavern only if no bratherhood of sword or not a castle
|
||||||
|
if(subID != ETownType::CASTLE || !addBonusIfBuilt(EBuilding::BROTHERHOOD, Bonus::MORALE, +2))
|
||||||
|
addBonusIfBuilt(EBuilding::TAVERN, Bonus::MORALE, +1);
|
||||||
|
|
||||||
if(subID != 0 || !addBonusIfBuilt(22, Bonus::MORALE, +2)) //tricky! -> checks tavern only if no bratherhood of sword or not a castle
|
if(subID == ETownType::CASTLE) //castle
|
||||||
addBonusIfBuilt(5, Bonus::MORALE, +1);
|
|
||||||
|
|
||||||
if(subID == 0) //castle
|
|
||||||
{
|
{
|
||||||
addBonusIfBuilt(17, Bonus::SEA_MOVEMENT, +500, make_shared<CPropagatorNodeType>(PLAYER)); //lighthouses
|
addBonusIfBuilt(EBuilding::LIGHTHOUSE, Bonus::SEA_MOVEMENT, +500, make_shared<CPropagatorNodeType>(PLAYER));
|
||||||
addBonusIfBuilt(26, Bonus::MORALE, +2, make_shared<CPropagatorNodeType>(PLAYER)); //colossus
|
addBonusIfBuilt(EBuilding::GRAIL, Bonus::MORALE, +2, make_shared<CPropagatorNodeType>(PLAYER)); //colossus
|
||||||
}
|
}
|
||||||
else if(subID == 1) //rampart
|
else if(subID == ETownType::RAMPART) //rampart
|
||||||
{
|
{
|
||||||
addBonusIfBuilt(21, Bonus::LUCK, +2); //fountain of fortune
|
addBonusIfBuilt(EBuilding::FOUNTAIN_OF_FORTUNE, Bonus::LUCK, +2); //fountain of fortune
|
||||||
addBonusIfBuilt(21, Bonus::LUCK, +2, make_shared<CPropagatorNodeType>(PLAYER)); //guardian spirit
|
addBonusIfBuilt(EBuilding::GRAIL, Bonus::LUCK, +2, make_shared<CPropagatorNodeType>(PLAYER)); //guardian spirit
|
||||||
}
|
}
|
||||||
else if(subID == 2) //tower
|
else if(subID == ETownType::RAMPART) //tower
|
||||||
{
|
{
|
||||||
addBonusIfBuilt(26, Bonus::PRIMARY_SKILL, +15, PrimarySkill::KNOWLEDGE); //grail
|
addBonusIfBuilt(EBuilding::GRAIL, Bonus::PRIMARY_SKILL, +15, PrimarySkill::KNOWLEDGE); //grail
|
||||||
}
|
}
|
||||||
else if(subID == 3) //Inferno
|
else if(subID == ETownType::TOWER) //Inferno
|
||||||
{
|
{
|
||||||
addBonusIfBuilt(21, Bonus::PRIMARY_SKILL, +2, PrimarySkill::SPELL_POWER); //Brimstone Clouds
|
addBonusIfBuilt(EBuilding::STORMCLOUDS, Bonus::PRIMARY_SKILL, +2, PrimarySkill::SPELL_POWER); //Brimstone Clouds
|
||||||
}
|
}
|
||||||
else if(subID == 4) //necropolis
|
else if(subID == ETownType::NECROPOLIS) //necropolis
|
||||||
{
|
{
|
||||||
addBonusIfBuilt(17, Bonus::DARKNESS, +20);
|
addBonusIfBuilt(EBuilding::COVER_OF_DARKNESS, Bonus::DARKNESS, +20);
|
||||||
addBonusIfBuilt(21, Bonus::SECONDARY_SKILL_PREMY, +10, make_shared<CPropagatorNodeType>(PLAYER), CGHeroInstance::NECROMANCY); //necromancy amplifier
|
addBonusIfBuilt(EBuilding::NECROMANCY_AMPLIFIER, Bonus::SECONDARY_SKILL_PREMY, +10, make_shared<CPropagatorNodeType>(PLAYER), CGHeroInstance::NECROMANCY); //necromancy amplifier
|
||||||
addBonusIfBuilt(26, Bonus::SECONDARY_SKILL_PREMY, +20, make_shared<CPropagatorNodeType>(PLAYER), CGHeroInstance::NECROMANCY); //Soul prison
|
addBonusIfBuilt(EBuilding::GRAIL, Bonus::SECONDARY_SKILL_PREMY, +20, make_shared<CPropagatorNodeType>(PLAYER), CGHeroInstance::NECROMANCY); //Soul prison
|
||||||
}
|
}
|
||||||
else if(subID == 5) //Dungeon
|
else if(subID == ETownType::DUNGEON) //Dungeon
|
||||||
{
|
{
|
||||||
addBonusIfBuilt(26, Bonus::PRIMARY_SKILL, +12, PrimarySkill::SPELL_POWER); //grail
|
addBonusIfBuilt(EBuilding::GRAIL, Bonus::PRIMARY_SKILL, +12, PrimarySkill::SPELL_POWER); //grail
|
||||||
}
|
}
|
||||||
else if(subID == 6) //Stronghold
|
else if(subID == ETownType::STRONGHOLD) //Stronghold
|
||||||
{
|
{
|
||||||
addBonusIfBuilt(26, Bonus::PRIMARY_SKILL, +20, PrimarySkill::ATTACK); //grail
|
addBonusIfBuilt(EBuilding::GRAIL, Bonus::PRIMARY_SKILL, +20, PrimarySkill::ATTACK); //grail
|
||||||
}
|
}
|
||||||
else if(subID == 7) //Fortress
|
else if(subID == ETownType::FORTRESS) //Fortress
|
||||||
{
|
{
|
||||||
addBonusIfBuilt(21, Bonus::PRIMARY_SKILL, +2, PrimarySkill::DEFENSE); //Glyphs of Fear
|
addBonusIfBuilt(EBuilding::GLYPHS_OF_FEAR, Bonus::PRIMARY_SKILL, +2, PrimarySkill::DEFENSE); //Glyphs of Fear
|
||||||
addBonusIfBuilt(22, Bonus::PRIMARY_SKILL, +2, PrimarySkill::ATTACK); //Blood Obelisk
|
addBonusIfBuilt(EBuilding::BLOOD_OBELISK, Bonus::PRIMARY_SKILL, +2, PrimarySkill::ATTACK); //Blood Obelisk
|
||||||
addBonusIfBuilt(26, Bonus::PRIMARY_SKILL, +10, PrimarySkill::ATTACK); //grail
|
addBonusIfBuilt(EBuilding::GRAIL, Bonus::PRIMARY_SKILL, +10, PrimarySkill::ATTACK); //grail
|
||||||
addBonusIfBuilt(26, Bonus::PRIMARY_SKILL, +10, PrimarySkill::DEFENSE); //grail
|
addBonusIfBuilt(EBuilding::GRAIL, Bonus::PRIMARY_SKILL, +10, PrimarySkill::DEFENSE); //grail
|
||||||
}
|
}
|
||||||
else if(subID == 8)
|
else if(subID == ETownType::CONFLUX)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -2382,7 +2396,7 @@ bool CGTownInstance::addBonusIfBuilt(int building, int type, int val, int subtyp
|
|||||||
|
|
||||||
bool CGTownInstance::addBonusIfBuilt(int building, int type, int val, TPropagatorPtr prop, int subtype /*= -1*/)
|
bool CGTownInstance::addBonusIfBuilt(int building, int type, int val, TPropagatorPtr prop, int subtype /*= -1*/)
|
||||||
{
|
{
|
||||||
if(vstd::contains(builtBuildings, building))
|
if(hasBuilt(building))
|
||||||
{
|
{
|
||||||
std::ostringstream descr;
|
std::ostringstream descr;
|
||||||
descr << VLC->generaltexth->buildings[subID][building].first << " ";
|
descr << VLC->generaltexth->buildings[subID][building].first << " ";
|
||||||
@ -2466,11 +2480,19 @@ const CArmedInstance * CGTownInstance::getUpperArmy() const
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CGTownInstance::hasBuilt(int buildingID, int townID) const
|
||||||
|
{
|
||||||
|
if (townID == town->typeID || townID == ETownType::ANY)
|
||||||
|
return hasBuilt(buildingID);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool CGTownInstance::hasBuilt(int buildingID) const
|
bool CGTownInstance::hasBuilt(int buildingID) const
|
||||||
{
|
{
|
||||||
return vstd::contains(builtBuildings, buildingID);
|
return vstd::contains(builtBuildings, buildingID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool CGVisitableOPH::wasVisited (const CGHeroInstance * h) const
|
bool CGVisitableOPH::wasVisited (const CGHeroInstance * h) const
|
||||||
{
|
{
|
||||||
return vstd::contains(visitors, h->id);
|
return vstd::contains(visitors, h->id);
|
||||||
@ -2828,13 +2850,13 @@ void COPWBonus::setProperty(ui8 what, ui32 val)
|
|||||||
void COPWBonus::onHeroVisit (const CGHeroInstance * h) const
|
void COPWBonus::onHeroVisit (const CGHeroInstance * h) const
|
||||||
{
|
{
|
||||||
int heroID = h->id;
|
int heroID = h->id;
|
||||||
if (town->builtBuildings.find(ID) != town->builtBuildings.end())
|
if (town->hasBuilt(ID))
|
||||||
{
|
{
|
||||||
InfoWindow iw;
|
InfoWindow iw;
|
||||||
iw.player = h->tempOwner;
|
iw.player = h->tempOwner;
|
||||||
switch (town->subID)
|
switch (town->subID)
|
||||||
{
|
{
|
||||||
case 0: //Stables
|
case ETownType::CASTLE: //Stables
|
||||||
if (!h->hasBonusFrom(Bonus::OBJECT, 94)) //does not stack with advMap Stables
|
if (!h->hasBonusFrom(Bonus::OBJECT, 94)) //does not stack with advMap Stables
|
||||||
{
|
{
|
||||||
GiveBonus gb;
|
GiveBonus gb;
|
||||||
@ -2845,7 +2867,7 @@ void COPWBonus::onHeroVisit (const CGHeroInstance * h) const
|
|||||||
cb->showInfoDialog(&iw);
|
cb->showInfoDialog(&iw);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 5: //Mana Vortex
|
case ETownType::DUNGEON: //Mana Vortex
|
||||||
if (visitors.empty() && h->mana <= h->manaLimit() * 2)
|
if (visitors.empty() && h->mana <= h->manaLimit() * 2)
|
||||||
{
|
{
|
||||||
cb->setManaPoints (heroID, 2 * h->manaLimit());
|
cb->setManaPoints (heroID, 2 * h->manaLimit());
|
||||||
@ -2872,34 +2894,34 @@ void CTownBonus::setProperty (ui8 what, ui32 val)
|
|||||||
void CTownBonus::onHeroVisit (const CGHeroInstance * h) const
|
void CTownBonus::onHeroVisit (const CGHeroInstance * h) const
|
||||||
{
|
{
|
||||||
int heroID = h->id;
|
int heroID = h->id;
|
||||||
if ((town->builtBuildings.find(ID) != town->builtBuildings.end()) && (visitors.find(heroID) == visitors.end()))
|
if (town->hasBuilt(ID) && visitors.find(heroID) == visitors.end())
|
||||||
{
|
{
|
||||||
InfoWindow iw;
|
InfoWindow iw;
|
||||||
int what=0, val=0, mid=0;
|
int what=0, val=0, mid=0;
|
||||||
switch (ID)
|
switch (ID)
|
||||||
{
|
{
|
||||||
case 23:
|
case EBuilding::SPECIAL_4:
|
||||||
switch(town->subID)
|
switch(town->subID)
|
||||||
{
|
{
|
||||||
case 2: //wall
|
case ETownType::TOWER: //wall
|
||||||
what = 3;
|
what = 3;
|
||||||
val = 1;
|
val = 1;
|
||||||
mid = 581;
|
mid = 581;
|
||||||
iw.components.push_back (Component(Component::PRIM_SKILL, 3, 1, 0));
|
iw.components.push_back (Component(Component::PRIM_SKILL, 3, 1, 0));
|
||||||
break;
|
break;
|
||||||
case 3: //order of fire
|
case ETownType::INFERNO: //order of fire
|
||||||
what = 2;
|
what = 2;
|
||||||
val = 1;
|
val = 1;
|
||||||
mid = 582;
|
mid = 582;
|
||||||
iw.components.push_back (Component(Component::PRIM_SKILL, 2, 1, 0));
|
iw.components.push_back (Component(Component::PRIM_SKILL, 2, 1, 0));
|
||||||
break;
|
break;
|
||||||
case 6://hall of valhalla
|
case ETownType::STRONGHOLD://hall of valhalla
|
||||||
what = 0;
|
what = 0;
|
||||||
val = 1;
|
val = 1;
|
||||||
mid = 584;
|
mid = 584;
|
||||||
iw.components.push_back (Component(Component::PRIM_SKILL, 0, 1, 0));
|
iw.components.push_back (Component(Component::PRIM_SKILL, 0, 1, 0));
|
||||||
break;
|
break;
|
||||||
case 5://academy of battle scholars
|
case ETownType::DUNGEON://academy of battle scholars
|
||||||
what = 4;
|
what = 4;
|
||||||
val = 1000*(100+h->getSecSkillLevel(CGHeroInstance::LEARNING)*5)/100.0;
|
val = 1000*(100+h->getSecSkillLevel(CGHeroInstance::LEARNING)*5)/100.0;
|
||||||
mid = 583;
|
mid = 583;
|
||||||
@ -2907,10 +2929,10 @@ void CTownBonus::onHeroVisit (const CGHeroInstance * h) const
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 17:
|
case EBuilding::SPECIAL_1:
|
||||||
switch(town->subID)
|
switch(town->subID)
|
||||||
{
|
{
|
||||||
case 7: //cage of warlords
|
case ETownType::FORTRESS: //cage of warlords
|
||||||
what = 1;
|
what = 1;
|
||||||
val = 1;
|
val = 1;
|
||||||
mid = 585;
|
mid = 585;
|
||||||
@ -6919,7 +6941,7 @@ void CArmedInstance::updateMoraleBonusFromArmy()
|
|||||||
//-1 modifier for any Necropolis unit in army
|
//-1 modifier for any Necropolis unit in army
|
||||||
const ui8 UNDEAD_MODIFIER_ID = -2;
|
const ui8 UNDEAD_MODIFIER_ID = -2;
|
||||||
Bonus *undeadModifier = getBonusList().getFirst(Selector::source(Bonus::ARMY, UNDEAD_MODIFIER_ID));
|
Bonus *undeadModifier = getBonusList().getFirst(Selector::source(Bonus::ARMY, UNDEAD_MODIFIER_ID));
|
||||||
if(vstd::contains(factions,4))
|
if(vstd::contains(factions, ETownType::NECROPOLIS))
|
||||||
{
|
{
|
||||||
if(!undeadModifier)
|
if(!undeadModifier)
|
||||||
addNewBonus(new Bonus(Bonus::PERMANENT, Bonus::MORALE, Bonus::ARMY, -1, UNDEAD_MODIFIER_ID, VLC->generaltexth->arraytxt[116]));
|
addNewBonus(new Bonus(Bonus::PERMANENT, Bonus::MORALE, Bonus::ARMY, -1, UNDEAD_MODIFIER_ID, VLC->generaltexth->arraytxt[116]));
|
||||||
|
@ -1,11 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
|
||||||
#include "CHeroHandler.h"
|
|
||||||
#include "CTownHandler.h"
|
|
||||||
#include "../lib/VCMI_Lib.h"
|
|
||||||
#endif
|
|
||||||
#include "../lib/CCreatureSet.h"
|
#include "../lib/CCreatureSet.h"
|
||||||
#include "CArtHandler.h"
|
#include "CArtHandler.h"
|
||||||
#include "../lib/ConstTransitivePtr.h"
|
#include "../lib/ConstTransitivePtr.h"
|
||||||
@ -636,7 +630,9 @@ public:
|
|||||||
GrowthInfo getGrowthInfo(int level) const;
|
GrowthInfo getGrowthInfo(int level) const;
|
||||||
bool hasFort() const;
|
bool hasFort() const;
|
||||||
bool hasCapitol() const;
|
bool hasCapitol() const;
|
||||||
|
//checks if building is constructed and town has same subID
|
||||||
bool hasBuilt(int buildingID) const;
|
bool hasBuilt(int buildingID) const;
|
||||||
|
bool hasBuilt(int buildingID, int townID) const;
|
||||||
int dailyIncome() const; //calculates daily income of this town
|
int dailyIncome() const; //calculates daily income of this town
|
||||||
int spellsAtLevel(int level, bool checkGuild) const; //levels are counted from 1 (1 - 5)
|
int spellsAtLevel(int level, bool checkGuild) const; //levels are counted from 1 (1 - 5)
|
||||||
void removeCapitols (ui8 owner) const;
|
void removeCapitols (ui8 owner) const;
|
||||||
|
@ -17,8 +17,6 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static std::string emptyStr = "";
|
|
||||||
|
|
||||||
const std::string & CBuilding::Name() const
|
const std::string & CBuilding::Name() const
|
||||||
{
|
{
|
||||||
if(name.length())
|
if(name.length())
|
||||||
@ -26,7 +24,7 @@ const std::string & CBuilding::Name() const
|
|||||||
else if(vstd::contains(VLC->generaltexth->buildings,tid) && vstd::contains(VLC->generaltexth->buildings[tid],bid))
|
else if(vstd::contains(VLC->generaltexth->buildings,tid) && vstd::contains(VLC->generaltexth->buildings[tid],bid))
|
||||||
return VLC->generaltexth->buildings[tid][bid].first;
|
return VLC->generaltexth->buildings[tid][bid].first;
|
||||||
tlog2 << "Warning: Cannot find name text for building " << bid << "for " << tid << "town.\n";
|
tlog2 << "Warning: Cannot find name text for building " << bid << "for " << tid << "town.\n";
|
||||||
return emptyStr;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string & CBuilding::Description() const
|
const std::string & CBuilding::Description() const
|
||||||
@ -36,7 +34,30 @@ const std::string & CBuilding::Description() const
|
|||||||
else if(vstd::contains(VLC->generaltexth->buildings,tid) && vstd::contains(VLC->generaltexth->buildings[tid],bid))
|
else if(vstd::contains(VLC->generaltexth->buildings,tid) && vstd::contains(VLC->generaltexth->buildings[tid],bid))
|
||||||
return VLC->generaltexth->buildings[tid][bid].second;
|
return VLC->generaltexth->buildings[tid][bid].second;
|
||||||
tlog2 << "Warning: Cannot find description text for building " << bid << "for " << tid << "town.\n";
|
tlog2 << "Warning: Cannot find description text for building " << bid << "for " << tid << "town.\n";
|
||||||
return emptyStr;
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
CBuilding::BuildingType CBuilding::getBase() const
|
||||||
|
{
|
||||||
|
const CBuilding * build = this;
|
||||||
|
while (build->upgrade >= 0)
|
||||||
|
build = VLC->townh->towns[build->tid].buildings[build->upgrade];
|
||||||
|
|
||||||
|
return build->bid;
|
||||||
|
}
|
||||||
|
|
||||||
|
si32 CBuilding::getDistance(CBuilding::BuildingType buildID) const
|
||||||
|
{
|
||||||
|
const CBuilding * build = VLC->townh->towns[tid].buildings[buildID];
|
||||||
|
int distance = 0;
|
||||||
|
while (build->upgrade >= 0 && build != this)
|
||||||
|
{
|
||||||
|
build = VLC->townh->towns[build->tid].buildings[build->upgrade];
|
||||||
|
distance++;
|
||||||
|
}
|
||||||
|
if (build == this)
|
||||||
|
return distance;
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string & CTown::Name() const
|
const std::string & CTown::Name() const
|
||||||
@ -65,9 +86,8 @@ JsonNode readBuilding(CLegacyConfigParser & parser)
|
|||||||
JsonNode ret;
|
JsonNode ret;
|
||||||
JsonNode & cost = ret["cost"];
|
JsonNode & cost = ret["cost"];
|
||||||
|
|
||||||
const std::string resources [] = {"wood", "mercury", "ore", "sulfur", "crystal", "gems", "gold"};
|
//note: this code will try to parse mithril as well but wil always return 0 for it
|
||||||
|
BOOST_FOREACH(const std::string & resID, GameConstants::RESOURCE_NAMES)
|
||||||
BOOST_FOREACH(const std::string & resID, resources)
|
|
||||||
cost[resID].Float() = parser.readNumber();
|
cost[resID].Float() = parser.readNumber();
|
||||||
|
|
||||||
parser.endLine();
|
parser.endLine();
|
||||||
@ -139,17 +159,27 @@ void CTownHandler::loadBuilding(CTown &town, const JsonNode & source)
|
|||||||
{
|
{
|
||||||
CBuilding * ret = new CBuilding;
|
CBuilding * ret = new CBuilding;
|
||||||
|
|
||||||
ret->name = source["name"].String();
|
static const std::string modes [] = {"normal", "auto", "special", "grail"};
|
||||||
ret->description = source["description"].String();
|
|
||||||
|
ret->mode = boost::find(modes, source["mode"].String()) - modes;
|
||||||
|
|
||||||
ret->tid = town.typeID;
|
ret->tid = town.typeID;
|
||||||
ret->bid = source["id"].Float();
|
ret->bid = source["id"].Float();
|
||||||
|
ret->name = source["name"].String();
|
||||||
|
ret->description = source["description"].String();
|
||||||
ret->resources = TResources(source["cost"]);
|
ret->resources = TResources(source["cost"]);
|
||||||
|
|
||||||
BOOST_FOREACH(const JsonNode &building, source["requires"].Vector())
|
BOOST_FOREACH(const JsonNode &building, source["requires"].Vector())
|
||||||
ret->requirements.insert(building.Float());
|
ret->requirements.insert(building.Float());
|
||||||
|
|
||||||
|
if (!source["upgrades"].isNull())
|
||||||
|
{
|
||||||
|
ret->requirements.insert(source["upgrades"].Float());
|
||||||
|
ret->upgrade = source["upgrades"].Float();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret->upgrade = -1;
|
||||||
|
|
||||||
town.buildings[ret->bid] = ret;
|
town.buildings[ret->bid] = ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,57 +195,39 @@ void CTownHandler::loadStructure(CTown &town, const JsonNode & source)
|
|||||||
{
|
{
|
||||||
CStructure * ret = new CStructure;
|
CStructure * ret = new CStructure;
|
||||||
|
|
||||||
ret->ID = source["id"].Float();
|
if (source["id"].isNull())
|
||||||
|
{
|
||||||
|
ret->building = nullptr;
|
||||||
|
ret->buildable = nullptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret->building = town.buildings[source["id"].Float()];
|
||||||
|
|
||||||
|
if (source["builds"].isNull())
|
||||||
|
ret->buildable = ret->building;
|
||||||
|
else
|
||||||
|
ret->buildable = town.buildings[source["builds"].Float()];
|
||||||
|
}
|
||||||
|
|
||||||
ret->pos.x = source["x"].Float();
|
ret->pos.x = source["x"].Float();
|
||||||
ret->pos.y = source["y"].Float();
|
ret->pos.y = source["y"].Float();
|
||||||
ret->pos.z = 0;
|
ret->pos.z = source["z"].Float();
|
||||||
|
|
||||||
ret->defName = source["defname"].String();
|
ret->hiddenUpgrade = source["hidden"].Bool();
|
||||||
|
ret->defName = source["animation"].String();
|
||||||
ret->borderName = source["border"].String();
|
ret->borderName = source["border"].String();
|
||||||
ret->areaName = source["area"].String();
|
ret->areaName = source["area"].String();
|
||||||
|
|
||||||
ret->group = -1;
|
town.clientInfo.structures.push_back(ret);
|
||||||
ret->townID = town.typeID;
|
|
||||||
|
|
||||||
town.clientInfo.structures[ret->ID] = ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CTownHandler::loadStructures(CTown &town, const JsonNode & source)
|
void CTownHandler::loadStructures(CTown &town, const JsonNode & source)
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(const JsonNode &node, source["structures"].Vector())
|
BOOST_FOREACH(const JsonNode &node, source.Vector())
|
||||||
{
|
{
|
||||||
loadStructure(town, node);
|
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)
|
void CTownHandler::loadTownHall(CTown &town, const JsonNode & source)
|
||||||
@ -238,23 +250,27 @@ void CTownHandler::loadTownHall(CTown &town, const JsonNode & source)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CTownHandler::loadTown(std::vector<CTown> &towns, const JsonNode & source)
|
void CTownHandler::loadClientData(CTown &town, const JsonNode & source)
|
||||||
{
|
{
|
||||||
towns.push_back(CTown());
|
town.clientInfo.hallBackground = source["hallBackground"].String();
|
||||||
CTown & town = towns.back();
|
town.clientInfo.musicTheme = source["musicTheme"].String();
|
||||||
|
town.clientInfo.townBackground = source["townBackground"].String();
|
||||||
|
town.clientInfo.guildWindow = source["guildWindow"].String();
|
||||||
|
town.clientInfo.buildingsIcons = source["buildingsIcons"].String();
|
||||||
|
|
||||||
//TODO: allow loading name and names vector from json and from h3 txt's
|
loadTownHall(town, source["hallSlots"]);
|
||||||
|
loadStructures(town, source["structures"]);
|
||||||
town.typeID = towns.size() - 1;
|
}
|
||||||
|
|
||||||
|
void CTownHandler::loadTown(CTown &town, const JsonNode & source)
|
||||||
|
{
|
||||||
town.bonus = town.typeID;
|
town.bonus = town.typeID;
|
||||||
if (town.bonus==8)
|
if (town.bonus==8)
|
||||||
town.bonus=3;
|
town.bonus=3;
|
||||||
|
|
||||||
town.clientInfo.hallBackground = source["hallBackground"].String();
|
town.mageLevel = source["mageGuild"].Float();
|
||||||
town.mageLevel = source["mage_guild"].Float();
|
town.primaryRes = source["primaryResource"].Float();
|
||||||
town.primaryRes = source["primary_resource"].Float();
|
town.warMachine = source["warMachine"].Float();
|
||||||
town.warMachine = source["war_machine"].Float();
|
|
||||||
|
|
||||||
// Horde building creature level
|
// Horde building creature level
|
||||||
BOOST_FOREACH(const JsonNode &node, source["horde"].Vector())
|
BOOST_FOREACH(const JsonNode &node, source["horde"].Vector())
|
||||||
@ -272,20 +288,37 @@ void CTownHandler::loadTown(std::vector<CTown> &towns, const JsonNode & source)
|
|||||||
town.creatures.push_back(level);
|
town.creatures.push_back(level);
|
||||||
}
|
}
|
||||||
|
|
||||||
loadTownHall(town, source["hallSlots"]);
|
|
||||||
loadBuildings(town, source["buildings"]);
|
loadBuildings(town, source["buildings"]);
|
||||||
loadStructures(town, source);
|
loadClientData(town,source);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CTownHandler::loadTowns(std::vector<CTown> &towns, const JsonNode & source)
|
void CTownHandler::loadFactions(const JsonNode &source)
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(const JsonNode & node, source.Vector())
|
BOOST_FOREACH(auto & node, source.Struct())
|
||||||
{
|
{
|
||||||
loadTown(towns, node);
|
int id = node.second["index"].Float();
|
||||||
}
|
CFaction & faction = factions[id];
|
||||||
|
|
||||||
// ensure that correct number of town have been loaded. Safe to remove
|
faction.factionID = id;
|
||||||
assert(towns.size() == GameConstants::F_NUMBER);
|
faction.name = node.first;
|
||||||
|
|
||||||
|
faction.creatureBg120 = node.second["creatureBackground"]["120px"].String();
|
||||||
|
faction.creatureBg130 = node.second["creatureBackground"]["130px"].String();
|
||||||
|
|
||||||
|
if (!node.second["nativeTerrain"].isNull())
|
||||||
|
{
|
||||||
|
//get terrain as string and converto to numeric ID
|
||||||
|
faction.nativeTerrain = boost::find(GameConstants::TERRAIN_NAMES, node.second["nativeTerrain"].String()) - GameConstants::TERRAIN_NAMES;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
faction.nativeTerrain = -1;
|
||||||
|
|
||||||
|
if (!node.second["town"].isNull())
|
||||||
|
{
|
||||||
|
towns[id].typeID = id;
|
||||||
|
loadTown(towns[id], node.second["town"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CTownHandler::load()
|
void CTownHandler::load()
|
||||||
@ -295,23 +328,33 @@ void CTownHandler::load()
|
|||||||
JsonNode legacyConfig;
|
JsonNode legacyConfig;
|
||||||
loadLegacyData(legacyConfig);
|
loadLegacyData(legacyConfig);
|
||||||
|
|
||||||
|
//hardocoded list of H3 factions. Should be only used to convert H3 configs
|
||||||
|
static const std::string factionName [GameConstants::F_NUMBER] =
|
||||||
|
{
|
||||||
|
"castle", "rampart", "tower",
|
||||||
|
"inferno", "necropolis", "dungeon",
|
||||||
|
"stronghold", "fortress", "conflux"
|
||||||
|
};
|
||||||
|
|
||||||
// semi-manually merge legacy config with towns json
|
// semi-manually merge legacy config with towns json
|
||||||
// legacy config have only one item: town buildings stored in 2d vector
|
// 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++)
|
for (size_t i=0; i< legacyConfig.Vector().size(); i++)
|
||||||
{
|
{
|
||||||
JsonNode & buildings = buildingsConf["towns"].Vector()[i]["buildings"];
|
JsonNode & buildings = buildingsConf[factionName[i]]["town"]["buildings"];
|
||||||
BOOST_FOREACH(JsonNode & building, buildings.Vector())
|
BOOST_FOREACH(JsonNode & building, buildings.Vector())
|
||||||
{
|
{
|
||||||
|
JsonNode & legacyFaction = legacyConfig.Vector()[i];
|
||||||
if (vstd::contains(building.Struct(), "id"))
|
if (vstd::contains(building.Struct(), "id"))
|
||||||
{
|
{
|
||||||
JsonNode & legacyBuilding = legacyConfig.Vector()[i].Vector()[building["id"].Float()];
|
//find same buildings in legacy and json configs
|
||||||
|
JsonNode & legacyBuilding = legacyFaction.Vector()[building["id"].Float()];
|
||||||
|
|
||||||
if (!legacyBuilding.isNull())
|
if (!legacyBuilding.isNull()) //merge if h3 config was found for this building
|
||||||
JsonNode::merge(building, legacyBuilding);
|
JsonNode::merge(building, legacyBuilding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loadTowns(towns, buildingsConf["towns"]);
|
loadFactions(buildingsConf);
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "ConstTransitivePtr.h"
|
#include "ConstTransitivePtr.h"
|
||||||
#include "ResourceSet.h"
|
#include "ResourceSet.h"
|
||||||
#include "int3.h"
|
#include "int3.h"
|
||||||
|
//#include "GameConstants.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CTownHandler.h, part of VCMI engine
|
* CTownHandler.h, part of VCMI engine
|
||||||
@ -22,20 +23,39 @@ class JsonNode;
|
|||||||
/// contains all mechanics-related data about town structures
|
/// contains all mechanics-related data about town structures
|
||||||
class DLL_LINKAGE CBuilding
|
class DLL_LINKAGE CBuilding
|
||||||
{
|
{
|
||||||
|
typedef si32 BuildingType;//TODO: replace int with pointer?
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string description;
|
std::string description;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
si32 tid, bid; //town ID and structure ID
|
si32 tid, bid; //town ID and structure ID
|
||||||
TResources resources;
|
TResources resources;
|
||||||
std::set<int> requirements; //set of required buildings
|
|
||||||
|
std::set<BuildingType> requirements; /// set of required buildings, includes upgradeOf;
|
||||||
|
BuildingType upgrade; /// indicates that building "upgrade" can be improved by this, -1 = empty
|
||||||
|
|
||||||
|
enum EBuildMode
|
||||||
|
{
|
||||||
|
BUILD_NORMAL, // 0 - normal, default
|
||||||
|
BUILD_AUTO, // 1 - auto - building appears when all requirements are built
|
||||||
|
BUILD_SPECIAL, // 2 - special - building can not be built normally
|
||||||
|
BUILD_GRAIL // 3 - grail - building reqires grail to be built
|
||||||
|
};
|
||||||
|
ui32 mode;
|
||||||
|
|
||||||
const std::string &Name() const;
|
const std::string &Name() const;
|
||||||
const std::string &Description() const;
|
const std::string &Description() const;
|
||||||
|
|
||||||
|
//return base of upgrade(s) or this
|
||||||
|
BuildingType getBase() const;
|
||||||
|
|
||||||
|
// returns how many times build has to be upgraded to become build
|
||||||
|
si32 getDistance(BuildingType build) const;
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & tid & bid & resources & name & description & requirements;
|
h & tid & bid & resources & name & description & requirements & upgrade & mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
friend class CTownHandler;
|
friend class CTownHandler;
|
||||||
@ -43,38 +63,35 @@ public:
|
|||||||
|
|
||||||
/// This is structure used only by client
|
/// This is structure used only by client
|
||||||
/// Consists of all gui-related data about town structures
|
/// Consists of all gui-related data about town structures
|
||||||
/// Should be mode from lib to client
|
/// Should be moved from lib to client
|
||||||
struct DLL_LINKAGE CStructure
|
struct DLL_LINKAGE CStructure
|
||||||
{
|
{
|
||||||
int ID;
|
CBuilding * building; // base building. If null - this structure will be always present on screen
|
||||||
|
CBuilding * buildable; // building that will be used to determine built building and visible cost. Usually same as "building"
|
||||||
|
|
||||||
|
bool hiddenUpgrade; // used only if "building" is upgrade, if true - structure on town screen will behave exactly like parent (mouse clicks, hover texts, etc)
|
||||||
|
|
||||||
int3 pos;
|
int3 pos;
|
||||||
std::string defName, borderName, areaName;
|
std::string defName, borderName, areaName;
|
||||||
int townID, group;
|
|
||||||
|
|
||||||
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)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & ID & pos & defName & borderName & areaName & townID & group;
|
h & pos & defName & borderName & areaName & building & buildable;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class DLL_LINKAGE CTown
|
class DLL_LINKAGE CTown
|
||||||
{
|
{
|
||||||
std::string name; //name of type
|
std::string name;
|
||||||
|
std::string description;
|
||||||
|
|
||||||
std::vector<std::string> names; //names of the town instances
|
std::vector<std::string> names; //names of the town instances
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ui32 typeID;
|
ui32 typeID;//also works as factionID
|
||||||
|
|
||||||
/// level -> list of creatures on this tier
|
/// level -> list of creatures on this tier
|
||||||
/// TODO: replace with pointers to CCreature?
|
// TODO: replace with pointers to CCreature
|
||||||
std::vector<std::vector<si32> > creatures;
|
std::vector<std::vector<si32> > creatures;
|
||||||
|
|
||||||
bmap<int, ConstTransitivePtr<CBuilding> > buildings;
|
bmap<int, ConstTransitivePtr<CBuilding> > buildings;
|
||||||
@ -88,13 +105,21 @@ public:
|
|||||||
// Client-only data. Should be moved away from lib
|
// Client-only data. Should be moved away from lib
|
||||||
struct ClientInfo
|
struct ClientInfo
|
||||||
{
|
{
|
||||||
|
std::string musicTheme;
|
||||||
|
std::string townBackground;
|
||||||
|
std::string guildWindow;
|
||||||
|
std::string buildingsIcons;
|
||||||
std::string hallBackground;
|
std::string hallBackground;
|
||||||
std::vector< std::vector< std::vector<int> > > hallSlots; /// vector[row][column] = list of buildings in this slot
|
/// vector[row][column] = list of buildings in this slot
|
||||||
bmap<int, ConstTransitivePtr<CStructure> > structures;
|
std::vector< std::vector< std::vector<int> > > hallSlots;
|
||||||
|
|
||||||
|
/// list of town screen structures.
|
||||||
|
/// NOTE: index in vector is meaningless. Vector used instead of list for a bit faster access
|
||||||
|
std::vector<ConstTransitivePtr<CStructure> > structures;
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & hallBackground & hallSlots & structures;
|
h & musicTheme & townBackground & guildWindow & buildingsIcons & hallBackground & hallSlots & structures;
|
||||||
}
|
}
|
||||||
} clientInfo;
|
} clientInfo;
|
||||||
|
|
||||||
@ -110,6 +135,23 @@ public:
|
|||||||
friend class CTownHandler;
|
friend class CTownHandler;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CFaction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::string name; //reference name, usually lower case
|
||||||
|
ui32 factionID;
|
||||||
|
|
||||||
|
ui32 nativeTerrain;
|
||||||
|
|
||||||
|
std::string creatureBg120;
|
||||||
|
std::string creatureBg130;
|
||||||
|
|
||||||
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
|
{
|
||||||
|
h & name & factionID & nativeTerrain & creatureBg120 & creatureBg130;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class DLL_LINKAGE CTownHandler
|
class DLL_LINKAGE CTownHandler
|
||||||
{
|
{
|
||||||
/// loads CBuilding's into town
|
/// loads CBuilding's into town
|
||||||
@ -123,28 +165,32 @@ class DLL_LINKAGE CTownHandler
|
|||||||
/// loads town hall vector (hallSlots)
|
/// loads town hall vector (hallSlots)
|
||||||
void loadTownHall(CTown &town, const JsonNode & source);
|
void loadTownHall(CTown &town, const JsonNode & source);
|
||||||
|
|
||||||
/// load town and insert it into towns vector
|
void loadClientData(CTown &town, const JsonNode & source);
|
||||||
void loadTown(std::vector<CTown> &towns, const JsonNode & source);
|
|
||||||
|
void loadTown(CTown &town, const JsonNode & source);
|
||||||
|
|
||||||
/// main loading function, accepts merged JSON source and add all entries from it into game
|
/// 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
|
/// all entries in JSON should be checked for validness before using this function
|
||||||
void loadTowns(std::vector<CTown> &towns, const JsonNode & source);
|
void loadFactions(const JsonNode & source);
|
||||||
|
|
||||||
/// load all available data from h3 txt(s) into json structure using format similar to vcmi configs
|
/// load all available data from h3 txt(s) into json structure using format similar to vcmi configs
|
||||||
/// returns 2d array [townID] [buildID] of buildings
|
/// returns 2d array [townID] [buildID] of buildings
|
||||||
void loadLegacyData(JsonNode & dest);
|
void loadLegacyData(JsonNode & dest);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::vector<CTown> towns;
|
std::map<ui32, CTown> towns;
|
||||||
|
std::map<ui32, CFaction> factions;
|
||||||
|
|
||||||
CTownHandler(); //c-tor, set pointer in VLC to this
|
CTownHandler(); //c-tor, set pointer in VLC to this
|
||||||
|
|
||||||
/// "entry point" for towns loading.
|
/// "entry point" for towns loading.
|
||||||
/// reads legacy txt's from H3 + vcmi json, merges them
|
/// reads legacy txt's from H3 + vcmi json, merges them
|
||||||
/// and loads resulting structure to game using loadTowns method
|
/// and loads resulting structure to game using loadTowns method
|
||||||
|
/// in future may require loaded Creature Handler
|
||||||
void load();
|
void load();
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & towns;
|
h & towns & factions;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -72,19 +72,26 @@ namespace GameConstants
|
|||||||
const int ARTIFACTS_QUANTITY=171;
|
const int ARTIFACTS_QUANTITY=171;
|
||||||
const int HEROES_QUANTITY=156;
|
const int HEROES_QUANTITY=156;
|
||||||
const int SPELLS_QUANTITY=70;
|
const int SPELLS_QUANTITY=70;
|
||||||
const int RESOURCE_QUANTITY=8;
|
|
||||||
const int TERRAIN_TYPES=10;
|
|
||||||
const int PRIMARY_SKILLS=4;
|
const int PRIMARY_SKILLS=4;
|
||||||
const int NEUTRAL_PLAYER=255;
|
const int NEUTRAL_PLAYER=255;
|
||||||
const int NAMES_PER_TOWN=16;
|
const int NAMES_PER_TOWN=16;
|
||||||
const int CREATURES_PER_TOWN = 7; //without upgrades
|
const int CREATURES_PER_TOWN = 7; //without upgrades
|
||||||
const int MAX_BUILDING_PER_TURN = 1;
|
|
||||||
const int SPELL_LEVELS = 5;
|
const int SPELL_LEVELS = 5;
|
||||||
const int AVAILABLE_HEROES_PER_PLAYER = 2;
|
const int AVAILABLE_HEROES_PER_PLAYER = 2;
|
||||||
const int SPELLBOOK_GOLD_COST = 500;
|
const int SPELLBOOK_GOLD_COST = 500;
|
||||||
|
|
||||||
const ui16 BACKPACK_START = 19;
|
const ui16 BACKPACK_START = 19;
|
||||||
const int ID_CATAPULT = 3, ID_LOCK = 145;
|
const int ID_CATAPULT = 3, ID_LOCK = 145;
|
||||||
|
|
||||||
|
const int TERRAIN_TYPES=10;
|
||||||
|
const std::string TERRAIN_NAMES [TERRAIN_TYPES] = {
|
||||||
|
"dirt", "sand", "grass", "snow", "swamp", "rough", "subterra", "lava", "water", "rock"
|
||||||
|
};
|
||||||
|
|
||||||
|
const int RESOURCE_QUANTITY=8;
|
||||||
|
const std::string RESOURCE_NAMES [RESOURCE_QUANTITY] = {
|
||||||
|
"wood", "mercury", "ore", "sulfur", "crystal", "gems", "gold", "mithril"
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enum declarations
|
// Enum declarations
|
||||||
@ -109,9 +116,19 @@ namespace EAlignment
|
|||||||
enum EAlignment { GOOD, EVIL, NEUTRAL };
|
enum EAlignment { GOOD, EVIL, NEUTRAL };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace ETownType
|
||||||
|
{
|
||||||
|
enum ETownType
|
||||||
|
{
|
||||||
|
ANY = -1,
|
||||||
|
CASTLE, RAMPART, TOWER, INFERNO, NECROPOLIS, DUNGEON, STRONGHOLD, FORTRESS, CONFLUX
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
namespace EBuilding
|
namespace EBuilding
|
||||||
{
|
{
|
||||||
//Quite useful as long as most of building mechanics hardcoded
|
//Quite useful as long as most of building mechanics hardcoded
|
||||||
|
// NOTE: all building with completely configurable mechanics will be removed from list
|
||||||
enum EBuilding
|
enum EBuilding
|
||||||
{
|
{
|
||||||
MAGES_GUILD_1, MAGES_GUILD_2, MAGES_GUILD_3, MAGES_GUILD_4, MAGES_GUILD_5,
|
MAGES_GUILD_1, MAGES_GUILD_2, MAGES_GUILD_3, MAGES_GUILD_4, MAGES_GUILD_5,
|
||||||
@ -119,8 +136,47 @@ namespace EBuilding
|
|||||||
VILLAGE_HALL, TOWN_HALL, CITY_HALL, CAPITOL, MARKETPLACE,
|
VILLAGE_HALL, TOWN_HALL, CITY_HALL, CAPITOL, MARKETPLACE,
|
||||||
RESOURCE_SILO, BLACKSMITH, SPECIAL_1, HORDE_1, HORDE_1_UPGR,
|
RESOURCE_SILO, BLACKSMITH, SPECIAL_1, HORDE_1, HORDE_1_UPGR,
|
||||||
SHIP, SPECIAL_2, SPECIAL_3, SPECIAL_4, HORDE_2,
|
SHIP, SPECIAL_2, SPECIAL_3, SPECIAL_4, HORDE_2,
|
||||||
HORDE_2_UPGR, GRAIL, EXTRA_CITY_HALL, EXTRA_TOWN_HALL, EXTRA_CAPITOL,
|
HORDE_2_UPGR, GRAIL, EXTRA_TOWN_HALL, EXTRA_CITY_HALL, EXTRA_CAPITOL,
|
||||||
DWELL_FIRST=30, DWELL_LAST=36, DWELL_UP_FIRST=37, DWELL_UP_LAST=43
|
DWELL_FIRST=30, DWELL_LAST=36, DWELL_UP_FIRST=37, DWELL_UP_LAST=43,
|
||||||
|
|
||||||
|
//Special buildings for towns.
|
||||||
|
LIGHTHOUSE = SPECIAL_1,
|
||||||
|
STABLES = SPECIAL_2, //Castle
|
||||||
|
BROTHERHOOD = SPECIAL_3,
|
||||||
|
|
||||||
|
MYSTIC_POND = SPECIAL_1,
|
||||||
|
FOUNTAIN_OF_FORTUNE = SPECIAL_3, //Rampart
|
||||||
|
TREASURY = SPECIAL_4,
|
||||||
|
|
||||||
|
ARTIFACT_MERCHANT = SPECIAL_1,
|
||||||
|
LOOKOUT_TOWER = SPECIAL_2, //Tower
|
||||||
|
LIBRARY = SPECIAL_3,
|
||||||
|
WALL_OF_KNOWLEDGE = SPECIAL_4,
|
||||||
|
|
||||||
|
STORMCLOUDS = SPECIAL_2,
|
||||||
|
CASTLE_GATE = SPECIAL_3, //Inferno
|
||||||
|
ORDER_OF_FIRE = SPECIAL_4,
|
||||||
|
|
||||||
|
COVER_OF_DARKNESS = SPECIAL_1,
|
||||||
|
NECROMANCY_AMPLIFIER = SPECIAL_2, //Necropolis
|
||||||
|
SKELETON_TRANSFORMER = SPECIAL_3,
|
||||||
|
|
||||||
|
//ARTIFACT_MERCHANT - same ID as in tower
|
||||||
|
MANA_VORTEX = SPECIAL_2,
|
||||||
|
PORTAL_OF_SUMMON = SPECIAL_3, //Dungeon
|
||||||
|
BATTLE_ACADEMY = SPECIAL_4,
|
||||||
|
|
||||||
|
ESCAPE_TUNNEL = SPECIAL_1,
|
||||||
|
FREELANCERS_GUILD = SPECIAL_2, //Stronghold
|
||||||
|
BALLISTA_YARD = SPECIAL_3,
|
||||||
|
HALL_OF_VALHALLA = SPECIAL_4,
|
||||||
|
|
||||||
|
CAGE_OF_WARLORDS = SPECIAL_1,
|
||||||
|
GLYPHS_OF_FEAR = SPECIAL_2, // Fortress
|
||||||
|
BLOOD_OBELISK = SPECIAL_3,
|
||||||
|
|
||||||
|
//ARTIFACT_MERCHANT - same ID as in tower
|
||||||
|
MAGIC_UNIVERSITY = SPECIAL_2, // Conflux
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,20 +1,22 @@
|
|||||||
#include "StdInc.h"
|
#include "StdInc.h"
|
||||||
#include "IGameCallback.h"
|
#include "IGameCallback.h"
|
||||||
|
|
||||||
#include "../lib/CGameState.h"
|
#include <boost/random/linear_congruential.hpp>
|
||||||
#include "../lib/map.h"
|
|
||||||
|
#include "CGameState.h"
|
||||||
|
#include "map.h"
|
||||||
#include "CObjectHandler.h"
|
#include "CObjectHandler.h"
|
||||||
#include "CHeroHandler.h"
|
#include "CHeroHandler.h"
|
||||||
#include "StartInfo.h"
|
#include "StartInfo.h"
|
||||||
#include "CArtHandler.h"
|
#include "CArtHandler.h"
|
||||||
#include "CSpellHandler.h"
|
#include "CSpellHandler.h"
|
||||||
#include "../lib/VCMI_Lib.h"
|
#include "VCMI_Lib.h"
|
||||||
#include <boost/random/linear_congruential.hpp>
|
|
||||||
#include "CTownHandler.h"
|
#include "CTownHandler.h"
|
||||||
#include "BattleState.h"
|
#include "BattleState.h"
|
||||||
#include "NetPacks.h"
|
#include "NetPacks.h"
|
||||||
#include "CBuildingHandler.h"
|
#include "CBuildingHandler.h"
|
||||||
#include "GameConstants.h"
|
#include "GameConstants.h"
|
||||||
|
#include "CModHandler.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IGameCallback.cpp, part of VCMI engine
|
* IGameCallback.cpp, part of VCMI engine
|
||||||
@ -544,7 +546,7 @@ int CGameInfoCallback::canBuildStructure( const CGTownInstance *t, int ID )
|
|||||||
ERROR_RET_VAL_IF(!canGetFullInfo(t), "Town is not owned!", -1);
|
ERROR_RET_VAL_IF(!canGetFullInfo(t), "Town is not owned!", -1);
|
||||||
|
|
||||||
int ret = EBuildingState::ALLOWED;
|
int ret = EBuildingState::ALLOWED;
|
||||||
if(t->builded >= GameConstants::MAX_BUILDING_PER_TURN)
|
if(t->builded >= VLC->modh->settings.MAX_BUILDING_PER_TURN)
|
||||||
ret = EBuildingState::CANT_BUILD_TODAY; //building limit
|
ret = EBuildingState::CANT_BUILD_TODAY; //building limit
|
||||||
|
|
||||||
CBuilding * pom = t->town->buildings[ID];
|
CBuilding * pom = t->town->buildings[ID];
|
||||||
@ -561,7 +563,7 @@ int CGameInfoCallback::canBuildStructure( const CGTownInstance *t, int ID )
|
|||||||
|
|
||||||
for( std::set<int>::iterator ri = reqs.begin(); ri != reqs.end(); ri++ )
|
for( std::set<int>::iterator ri = reqs.begin(); ri != reqs.end(); ri++ )
|
||||||
{
|
{
|
||||||
if(t->builtBuildings.find(*ri)==t->builtBuildings.end())
|
if(!t->hasBuilt(*ri))
|
||||||
ret = EBuildingState::PREREQUIRES; //lack of requirements - cannot build
|
ret = EBuildingState::PREREQUIRES; //lack of requirements - cannot build
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -576,7 +578,7 @@ int CGameInfoCallback::canBuildStructure( const CGTownInstance *t, int ID )
|
|||||||
{
|
{
|
||||||
BOOST_FOREACH(const CGTownInstance *t, ps->towns)
|
BOOST_FOREACH(const CGTownInstance *t, ps->towns)
|
||||||
{
|
{
|
||||||
if(vstd::contains(t->builtBuildings, 13))
|
if(t->hasBuilt(EBuilding::CAPITOL))
|
||||||
{
|
{
|
||||||
ret = EBuildingState::HAVE_CAPITAL; //no more than one capitol
|
ret = EBuildingState::HAVE_CAPITAL; //no more than one capitol
|
||||||
break;
|
break;
|
||||||
@ -592,7 +594,7 @@ int CGameInfoCallback::canBuildStructure( const CGTownInstance *t, int ID )
|
|||||||
ret = EBuildingState::NO_WATER; //lack of water
|
ret = EBuildingState::NO_WATER; //lack of water
|
||||||
}
|
}
|
||||||
|
|
||||||
if(t->builtBuildings.find(ID)!=t->builtBuildings.end()) //already built
|
if(t->hasBuilt(ID)) //already built
|
||||||
ret = EBuildingState::ALREADY_PRESENT;
|
ret = EBuildingState::ALREADY_PRESENT;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -603,32 +605,27 @@ std::set<int> CGameInfoCallback::getBuildingRequiments( const CGTownInstance *t,
|
|||||||
|
|
||||||
std::set<int> used;
|
std::set<int> used;
|
||||||
used.insert(ID);
|
used.insert(ID);
|
||||||
std::set<int> reqs = t->town->buildings[ID]->requirements;
|
auto reqs = t->town->buildings[ID]->requirements;
|
||||||
|
|
||||||
while(true)
|
bool found;
|
||||||
|
do
|
||||||
{
|
{
|
||||||
size_t noloop=0;
|
found = false;
|
||||||
for(std::set<int>::iterator i=reqs.begin();i!=reqs.end();i++)
|
for(auto i=reqs.begin();i!=reqs.end();i++)
|
||||||
{
|
{
|
||||||
if(used.find(*i)==used.end()) //we haven't added requirements for this building
|
if(used.find(*i)==used.end()) //we haven't added requirements for this building
|
||||||
{
|
{
|
||||||
|
found = true;
|
||||||
|
auto & requires = t->town->buildings[*i]->requirements;
|
||||||
|
|
||||||
used.insert(*i);
|
used.insert(*i);
|
||||||
for(
|
for(auto j = requires.begin(); j!= requires.end(); j++)
|
||||||
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
|
reqs.insert(*j);//creating full list of requirements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
noloop++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(noloop==reqs.size())
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
while (found);
|
||||||
|
|
||||||
return reqs;
|
return reqs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -501,7 +501,7 @@ bool JsonParser::extractString(std::string &str)
|
|||||||
str.append( &input[first], pos-first);
|
str.append( &input[first], pos-first);
|
||||||
return error("Closing quote not found!", true);
|
return error("Closing quote not found!", true);
|
||||||
}
|
}
|
||||||
if (input[pos] < ' ') // control character
|
if ((unsigned char)(input[pos]) < ' ') // control character
|
||||||
{
|
{
|
||||||
str.append( &input[first], pos-first);
|
str.append( &input[first], pos-first);
|
||||||
first = pos+1;
|
first = pos+1;
|
||||||
|
@ -10,15 +10,9 @@ Res::ResourceSet::ResourceSet()
|
|||||||
|
|
||||||
Res::ResourceSet::ResourceSet(const JsonNode & node)
|
Res::ResourceSet::ResourceSet(const JsonNode & node)
|
||||||
{
|
{
|
||||||
resize(GameConstants::RESOURCE_QUANTITY, 0);
|
reserve(GameConstants::RESOURCE_QUANTITY);
|
||||||
at(0) = node["wood"].Float();
|
BOOST_FOREACH(std::string name, GameConstants::RESOURCE_NAMES)
|
||||||
at(1) = node["mercury"].Float();
|
push_back(node[name].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
|
bool Res::ResourceSet::nonZero() const
|
||||||
|
20
lib/map.cpp
20
lib/map.cpp
@ -57,18 +57,14 @@ static std::set<si32> convertBuildings(const std::set<si32> h3m, int castleID, b
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(addAuxiliary)
|
if(addAuxiliary)
|
||||||
{
|
ret.insert(EBuilding::VILLAGE_HALL); //village hall is always present
|
||||||
ret.insert(10); //village hall is always present
|
|
||||||
ret.insert(-1); //houses near v.hall / eyecandies
|
|
||||||
ret.insert(-2); //terrain eyecandy, if -1 is used
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ret.find(11)!=ret.end())
|
if(ret.find(EBuilding::CITY_HALL)!=ret.end())
|
||||||
ret.insert(27);
|
ret.insert(EBuilding::EXTRA_CITY_HALL);
|
||||||
if(ret.find(12)!=ret.end())
|
if(ret.find(EBuilding::TOWN_HALL)!=ret.end())
|
||||||
ret.insert(28);
|
ret.insert(EBuilding::EXTRA_TOWN_HALL);
|
||||||
if(ret.find(13)!=ret.end())
|
if(ret.find(EBuilding::CAPITOL)!=ret.end())
|
||||||
ret.insert(29);
|
ret.insert(EBuilding::EXTRA_CAPITOL);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -711,7 +707,7 @@ void Mapa::loadTown( CGObjectInstance * &nobj, const ui8 * bufor, int &i, int su
|
|||||||
else //standard buildings
|
else //standard buildings
|
||||||
{
|
{
|
||||||
if(readChar(bufor,i)) //has fort
|
if(readChar(bufor,i)) //has fort
|
||||||
nt->builtBuildings.insert(7);
|
nt->builtBuildings.insert(EBuilding::FORT);
|
||||||
nt->builtBuildings.insert(-50); //means that set of standard building should be included
|
nt->builtBuildings.insert(-50); //means that set of standard building should be included
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1138,7 +1138,7 @@ void CGameHandler::newTurn()
|
|||||||
bool deityOfFireBuilt = false;
|
bool deityOfFireBuilt = false;
|
||||||
BOOST_FOREACH(const CGTownInstance *t, gs->map->towns)
|
BOOST_FOREACH(const CGTownInstance *t, gs->map->towns)
|
||||||
{
|
{
|
||||||
if(t->subID == 3 && vstd::contains(t->builtBuildings, EBuilding::GRAIL))
|
if(t->hasBuilt(EBuilding::GRAIL, ETownType::INFERNO))
|
||||||
{
|
{
|
||||||
deityOfFireBuilt = true;
|
deityOfFireBuilt = true;
|
||||||
break;
|
break;
|
||||||
@ -1231,7 +1231,7 @@ void CGameHandler::newTurn()
|
|||||||
hth.id = h->id;
|
hth.id = h->id;
|
||||||
hth.move = h->maxMovePoints(gs->map->getTile(h->getPosition(false)).tertype != TerrainTile::water);
|
hth.move = h->maxMovePoints(gs->map->getTile(h->getPosition(false)).tertype != TerrainTile::water);
|
||||||
|
|
||||||
if(h->visitedTown && vstd::contains(h->visitedTown->builtBuildings,0)) //if hero starts turn in town with mage guild
|
if(h->visitedTown && h->visitedTown->hasBuilt(EBuilding::MAGES_GUILD_1)) //if hero starts turn in town with mage guild
|
||||||
hth.mana = std::max(h->mana, h->manaLimit()); //restore all mana
|
hth.mana = std::max(h->mana, h->manaLimit()); //restore all mana
|
||||||
else
|
else
|
||||||
hth.mana = std::max((si32)(0), std::max(h->mana, std::min((si32)(h->mana + h->manaRegain()), h->manaLimit())));
|
hth.mana = std::max((si32)(0), std::max(h->mana, std::min((si32)(h->mana + h->manaRegain()), h->manaLimit())));
|
||||||
@ -1258,11 +1258,11 @@ void CGameHandler::newTurn()
|
|||||||
handleTownEvents(t, n, newCreas);
|
handleTownEvents(t, n, newCreas);
|
||||||
if(newWeek) //first day of week
|
if(newWeek) //first day of week
|
||||||
{
|
{
|
||||||
if(t->subID == 5 && vstd::contains(t->builtBuildings, EBuilding::SPECIAL_3))
|
if(t->hasBuilt(EBuilding::PORTAL_OF_SUMMON, ETownType::DUNGEON))
|
||||||
setPortalDwelling(t, true, (n.specialWeek == NewTurn::PLAGUE ? true : false)); //set creatures for Portal of Summoning
|
setPortalDwelling(t, true, (n.specialWeek == NewTurn::PLAGUE ? true : false)); //set creatures for Portal of Summoning
|
||||||
|
|
||||||
if(!firstTurn)
|
if(!firstTurn)
|
||||||
if (t->subID == 1 && player < GameConstants::PLAYER_LIMIT && vstd::contains(t->builtBuildings, EBuilding::SPECIAL_3))//dwarven treasury
|
if (t->hasBuilt(EBuilding::TREASURY, ETownType::RAMPART) && player < GameConstants::PLAYER_LIMIT)
|
||||||
n.res[player][Res::GOLD] += hadGold[player]/10; //give 10% of starting gold
|
n.res[player][Res::GOLD] += hadGold[player]/10; //give 10% of starting gold
|
||||||
|
|
||||||
SetAvailableCreatures sac;
|
SetAvailableCreatures sac;
|
||||||
@ -1307,7 +1307,7 @@ void CGameHandler::newTurn()
|
|||||||
}
|
}
|
||||||
if(!firstTurn && player < GameConstants::PLAYER_LIMIT)//not the first day and town not neutral
|
if(!firstTurn && player < GameConstants::PLAYER_LIMIT)//not the first day and town not neutral
|
||||||
{
|
{
|
||||||
if(vstd::contains(t->builtBuildings, EBuilding::RESOURCE_SILO)) //there is resource silo
|
if(t->hasBuilt(EBuilding::RESOURCE_SILO)) //there is resource silo
|
||||||
{
|
{
|
||||||
if(t->town->primaryRes == 127) //we'll give wood and ore
|
if(t->town->primaryRes == 127) //we'll give wood and ore
|
||||||
{
|
{
|
||||||
@ -1322,7 +1322,7 @@ void CGameHandler::newTurn()
|
|||||||
|
|
||||||
n.res[player][Res::GOLD] += t->dailyIncome();
|
n.res[player][Res::GOLD] += t->dailyIncome();
|
||||||
}
|
}
|
||||||
if(vstd::contains(t->builtBuildings, EBuilding::GRAIL) && t->subID == 2)
|
if(t->hasBuilt(EBuilding::GRAIL, ETownType::TOWER))
|
||||||
{
|
{
|
||||||
// Skyship, probably easier to handle same as Veil of darkness
|
// Skyship, probably easier to handle same as Veil of darkness
|
||||||
//do it every new day after veils apply
|
//do it every new day after veils apply
|
||||||
@ -1579,7 +1579,7 @@ void CGameHandler::giveSpells( const CGTownInstance *t, const CGHeroInstance *h
|
|||||||
cs.learn = true;
|
cs.learn = true;
|
||||||
for(int i=0; i<std::min(t->mageGuildLevel(),h->getSecSkillLevel(CGHeroInstance::WISDOM)+2);i++)
|
for(int i=0; i<std::min(t->mageGuildLevel(),h->getSecSkillLevel(CGHeroInstance::WISDOM)+2);i++)
|
||||||
{
|
{
|
||||||
if (t->subID == 8 && vstd::contains(t->builtBuildings, EBuilding::GRAIL)) //Aurora Borealis
|
if (t->hasBuilt(EBuilding::GRAIL, ETownType::CONFLUX)) //Aurora Borealis
|
||||||
{
|
{
|
||||||
std::vector<ui16> spells;
|
std::vector<ui16> spells;
|
||||||
getAllowedSpells(spells, i);
|
getAllowedSpells(spells, i);
|
||||||
@ -1795,9 +1795,9 @@ bool CGameHandler::teleportHero(si32 hid, si32 dstid, ui8 source, ui8 asker/* =
|
|||||||
const CGTownInstance *from = h->visitedTown;
|
const CGTownInstance *from = h->visitedTown;
|
||||||
if(((h->getOwner() != t->getOwner())
|
if(((h->getOwner() != t->getOwner())
|
||||||
&& complain("Cannot teleport hero to another player"))
|
&& complain("Cannot teleport hero to another player"))
|
||||||
|| ((!from || from->subID!=3 || !vstd::contains(from->builtBuildings, EBuilding::SPECIAL_3))
|
|| ((!from || from->hasBuilt(EBuilding::CASTLE_GATE, ETownType::INFERNO))
|
||||||
&& complain("Hero must be in town with Castle gate for teleporting"))
|
&& complain("Hero must be in town with Castle gate for teleporting"))
|
||||||
|| ((t->subID!=3 || !vstd::contains(t->builtBuildings, EBuilding::SPECIAL_3))
|
|| (t->hasBuilt(EBuilding::CASTLE_GATE, ETownType::INFERNO)
|
||||||
&& complain("Cannot teleport hero to town without Castle gate in it")))
|
&& complain("Cannot teleport hero to town without Castle gate in it")))
|
||||||
return false;
|
return false;
|
||||||
int3 pos = t->visitablePos();
|
int3 pos = t->visitablePos();
|
||||||
@ -1818,7 +1818,7 @@ void CGameHandler::setOwner(int objid, ui8 owner)
|
|||||||
if(owner < GameConstants::PLAYER_LIMIT && getTown(objid)) //town captured
|
if(owner < GameConstants::PLAYER_LIMIT && getTown(objid)) //town captured
|
||||||
{
|
{
|
||||||
const CGTownInstance * town = getTown(objid);
|
const CGTownInstance * town = getTown(objid);
|
||||||
if (town->subID == 5 && vstd::contains(town->builtBuildings, 22))
|
if (town->hasBuilt(EBuilding::PORTAL_OF_SUMMON, ETownType::DUNGEON))
|
||||||
setPortalDwelling(town, true, false);
|
setPortalDwelling(town, true, false);
|
||||||
|
|
||||||
if (!gs->getPlayer(owner)->towns.size())//player lost last town
|
if (!gs->getPlayer(owner)->towns.size())//player lost last town
|
||||||
@ -1837,7 +1837,7 @@ void CGameHandler::setOwner(int objid, ui8 owner)
|
|||||||
{
|
{
|
||||||
BOOST_FOREACH(const CGTownInstance *t, gs->getPlayer(owner)->towns)
|
BOOST_FOREACH(const CGTownInstance *t, gs->getPlayer(owner)->towns)
|
||||||
{
|
{
|
||||||
if (t->subID == 5 && vstd::contains(t->builtBuildings, 22))
|
if (t->hasBuilt(EBuilding::PORTAL_OF_SUMMON, ETownType::DUNGEON))
|
||||||
setPortalDwelling(t);//set initial creatures for all portals of summoning
|
setPortalDwelling(t);//set initial creatures for all portals of summoning
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2421,27 +2421,34 @@ bool CGameHandler::buildStructure( si32 tid, si32 bid, bool force /*=false*/ )
|
|||||||
|
|
||||||
if(!force)
|
if(!force)
|
||||||
{
|
{
|
||||||
if (gs->canBuildStructure(t,bid) != 7)
|
switch (b->mode)
|
||||||
|
{
|
||||||
|
case CBuilding::BUILD_NORMAL :
|
||||||
|
case CBuilding::BUILD_AUTO :
|
||||||
|
if (gs->canBuildStructure(t,bid) != EBuildingState::ALLOWED)
|
||||||
COMPLAIN_RET("Cannot build that building!");
|
COMPLAIN_RET("Cannot build that building!");
|
||||||
|
break;
|
||||||
|
|
||||||
if(bid == 26) //grail
|
case CBuilding::BUILD_SPECIAL:
|
||||||
|
COMPLAIN_RET("This building can not be constructed!");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CBuilding::BUILD_GRAIL :
|
||||||
|
if(b->mode == CBuilding::BUILD_GRAIL) //needs grail
|
||||||
{
|
{
|
||||||
if(!t->visitingHero || !t->visitingHero->hasArt(2))
|
if(!t->visitingHero || !t->visitingHero->hasArt(2))
|
||||||
COMPLAIN_RET("Cannot build grail - hero doesn't have it")
|
COMPLAIN_RET("Cannot build this without grail!")
|
||||||
else
|
else
|
||||||
removeArtifact(ArtifactLocation(t->visitingHero, t->visitingHero->getArtPos(2, false)));
|
removeArtifact(ArtifactLocation(t->visitingHero, t->visitingHero->getArtPos(2, false)));
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NewStructures ns;
|
NewStructures ns;
|
||||||
ns.tid = tid;
|
ns.tid = tid;
|
||||||
//we have upgr. dwelling, upgr. horde will be builded as well
|
|
||||||
if ( (bid == 18) && (vstd::contains(t->builtBuildings,(t->town->hordeLvl[0]+37))) )
|
|
||||||
ns.bid.insert(19);
|
|
||||||
else if ( (bid == 24) && (vstd::contains(t->builtBuildings,(t->town->hordeLvl[1]+37))) )
|
|
||||||
ns.bid.insert(25);
|
|
||||||
|
|
||||||
else if(bid >= EBuilding::DWELL_FIRST) //dwelling
|
if(bid >= EBuilding::DWELL_FIRST) //dwelling
|
||||||
{
|
{
|
||||||
int level = (bid - EBuilding::DWELL_FIRST) % GameConstants::CREATURES_PER_TOWN;
|
int level = (bid - EBuilding::DWELL_FIRST) % GameConstants::CREATURES_PER_TOWN;
|
||||||
int upgradeNumber = (bid - EBuilding::DWELL_FIRST) / GameConstants::CREATURES_PER_TOWN;
|
int upgradeNumber = (bid - EBuilding::DWELL_FIRST) / GameConstants::CREATURES_PER_TOWN;
|
||||||
@ -2451,14 +2458,6 @@ bool CGameHandler::buildStructure( si32 tid, si32 bid, bool force /*=false*/ )
|
|||||||
|
|
||||||
CCreature * crea = VLC->creh->creatures[t->town->creatures[level][upgradeNumber]];
|
CCreature * crea = VLC->creh->creatures[t->town->creatures[level][upgradeNumber]];
|
||||||
|
|
||||||
if (vstd::iswithin(bid, EBuilding::DWELL_UP_FIRST, EBuilding::DWELL_UP_LAST))
|
|
||||||
{
|
|
||||||
if ( (bid-37 == t->town->hordeLvl[0]) && (vstd::contains(t->builtBuildings,18)) )
|
|
||||||
ns.bid.insert(19);//we have horde, will be upgraded as well as dwelling
|
|
||||||
if ( (bid-37 == t->town->hordeLvl[1]) && (vstd::contains(t->builtBuildings,24)) )
|
|
||||||
ns.bid.insert(25);
|
|
||||||
}
|
|
||||||
|
|
||||||
SetAvailableCreatures ssi;
|
SetAvailableCreatures ssi;
|
||||||
ssi.tid = tid;
|
ssi.tid = tid;
|
||||||
ssi.creatures = t->creatures;
|
ssi.creatures = t->creatures;
|
||||||
@ -2467,19 +2466,34 @@ bool CGameHandler::buildStructure( si32 tid, si32 bid, bool force /*=false*/ )
|
|||||||
ssi.creatures[level].second.push_back(crea->idNumber);
|
ssi.creatures[level].second.push_back(crea->idNumber);
|
||||||
sendAndApply(&ssi);
|
sendAndApply(&ssi);
|
||||||
}
|
}
|
||||||
else if(bid == 11)
|
else if ( t->subID == ETownType::DUNGEON && bid == EBuilding::MANA_VORTEX )
|
||||||
ns.bid.insert(27);
|
|
||||||
else if(bid == 12)
|
|
||||||
ns.bid.insert(28);
|
|
||||||
else if(bid == 13)
|
|
||||||
ns.bid.insert(29);
|
|
||||||
else if ( t->subID == 5 && bid == 22 )
|
|
||||||
{
|
{
|
||||||
setPortalDwelling(t);
|
setPortalDwelling(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
ns.bid.insert(bid);
|
ns.bid.insert(bid);
|
||||||
ns.builded = force?t->builded:(t->builded+1);
|
ns.builded = force?t->builded:(t->builded+1);
|
||||||
|
|
||||||
|
BOOST_FOREACH(auto & build, t->town->buildings)
|
||||||
|
{
|
||||||
|
if (build.second->mode == CBuilding::BUILD_AUTO
|
||||||
|
&& !vstd::contains(t->builtBuildings, build.second->bid))
|
||||||
|
{
|
||||||
|
bool canBuild = true;
|
||||||
|
BOOST_FOREACH(int requires, build.second->requirements)
|
||||||
|
{
|
||||||
|
if (!vstd::contains(t->builtBuildings, requires)
|
||||||
|
&& !vstd::contains(ns.bid, requires))
|
||||||
|
{
|
||||||
|
canBuild = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (canBuild)
|
||||||
|
ns.bid.insert(build.second->bid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sendAndApply(&ns);
|
sendAndApply(&ns);
|
||||||
|
|
||||||
//reveal ground for lookout tower
|
//reveal ground for lookout tower
|
||||||
@ -2866,7 +2880,7 @@ bool CGameHandler::buyArtifact( ui32 hid, si32 aid )
|
|||||||
CGTownInstance *town = hero->visitedTown;
|
CGTownInstance *town = hero->visitedTown;
|
||||||
if(aid==0) //spellbook
|
if(aid==0) //spellbook
|
||||||
{
|
{
|
||||||
if((!vstd::contains(town->builtBuildings,si32(EBuilding::MAGES_GUILD_1)) && complain("Cannot buy a spellbook, no mage guild in the town!"))
|
if((!town->hasBuilt(EBuilding::MAGES_GUILD_1) && complain("Cannot buy a spellbook, no mage guild in the town!"))
|
||||||
|| (getResource(hero->getOwner(), Res::GOLD) < GameConstants::SPELLBOOK_GOLD_COST && complain("Cannot buy a spellbook, not enough gold!") )
|
|| (getResource(hero->getOwner(), Res::GOLD) < GameConstants::SPELLBOOK_GOLD_COST && complain("Cannot buy a spellbook, not enough gold!") )
|
||||||
|| (hero->getArt(ArtifactPosition::SPELLBOOK) && complain("Cannot buy a spellbook, hero already has a one!"))
|
|| (hero->getArt(ArtifactPosition::SPELLBOOK) && complain("Cannot buy a spellbook, hero already has a one!"))
|
||||||
)
|
)
|
||||||
@ -2881,19 +2895,22 @@ bool CGameHandler::buyArtifact( ui32 hid, si32 aid )
|
|||||||
else if(aid < 7 && aid > 3) //war machine
|
else if(aid < 7 && aid > 3) //war machine
|
||||||
{
|
{
|
||||||
int price = VLC->arth->artifacts[aid]->price;
|
int price = VLC->arth->artifacts[aid]->price;
|
||||||
|
|
||||||
if(( hero->getArt(9+aid) && complain("Hero already has this machine!"))
|
if(( hero->getArt(9+aid) && complain("Hero already has this machine!"))
|
||||||
|| (!vstd::contains(town->builtBuildings,si32(EBuilding::BLACKSMITH)) && complain("No blackismith!"))
|
|| (gs->getPlayer(hero->getOwner())->resources[Res::GOLD] < price && complain("Not enough gold!")))
|
||||||
|| (gs->getPlayer(hero->getOwner())->resources[Res::GOLD] < price && complain("Not enough gold!")) //no gold
|
|
||||||
|| ((!(town->subID == 6 && vstd::contains(town->builtBuildings,si32(EBuilding::SPECIAL_3) ) )
|
|
||||||
&& town->town->warMachine!= aid ) && complain("This machine is unavailable here!")))
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if ((town->hasBuilt(EBuilding::BLACKSMITH) && town->town->warMachine == aid )
|
||||||
|
|| ((town->hasBuilt(EBuilding::BALLISTA_YARD, ETownType::STRONGHOLD)) && aid == 4))
|
||||||
|
{
|
||||||
giveResource(hero->getOwner(),Res::GOLD,-price);
|
giveResource(hero->getOwner(),Res::GOLD,-price);
|
||||||
giveHeroNewArtifact(hero, VLC->arth->artifacts[aid], 9+aid);
|
giveHeroNewArtifact(hero, VLC->arth->artifacts[aid], 9+aid);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
COMPLAIN_RET("This machine is unavailable here!");
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3136,7 +3153,7 @@ bool CGameHandler::hireHero(const CGObjectInstance *obj, ui8 hid, ui8 player)
|
|||||||
|
|
||||||
if(t) //tavern in town
|
if(t) //tavern in town
|
||||||
{
|
{
|
||||||
if( (!vstd::contains(t->builtBuildings,EBuilding::TAVERN) && complain("No tavern!"))
|
if( (!t->hasBuilt(EBuilding::TAVERN) && complain("No tavern!"))
|
||||||
|| (t->visitingHero && complain("There is visiting hero - no place!")))
|
|| (t->visitingHero && complain("There is visiting hero - no place!")))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -3731,8 +3748,7 @@ void CGameHandler::playerMessage( ui8 player, const std::string &message )
|
|||||||
{
|
{
|
||||||
BOOST_FOREACH (auto & build, town->town->buildings)
|
BOOST_FOREACH (auto & build, town->town->buildings)
|
||||||
{
|
{
|
||||||
if (!vstd::contains(town->builtBuildings, build.first)
|
if (!town->hasBuilt(build.first) && !build.second->Name().empty())
|
||||||
&& !build.second->Name().empty())
|
|
||||||
{
|
{
|
||||||
buildStructure(town->id, build.first, true);
|
buildStructure(town->id, build.first, true);
|
||||||
}
|
}
|
||||||
@ -4739,7 +4755,7 @@ void CGameHandler::handleTownEvents(CGTownInstance * town, NewTurn &n, std::map<
|
|||||||
}
|
}
|
||||||
|
|
||||||
for(std::set<si32>::iterator i = ev->buildings.begin(); i!=ev->buildings.end();i++)
|
for(std::set<si32>::iterator i = ev->buildings.begin(); i!=ev->buildings.end();i++)
|
||||||
if ( !vstd::contains(town->builtBuildings, *i))
|
if ( town->hasBuilt(*i))
|
||||||
{
|
{
|
||||||
buildStructure(town->id, *i, true);
|
buildStructure(town->id, *i, true);
|
||||||
iw.components.push_back(Component(Component::BUILDING, town->subID, *i, 0));
|
iw.components.push_back(Component(Component::BUILDING, town->subID, *i, 0));
|
||||||
@ -4902,14 +4918,14 @@ bool CGameHandler::buildBoat( ui32 objid )
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if(obj->o->ID == GameConstants::TOWNI_TYPE
|
else if(obj->o->ID == GameConstants::TOWNI_TYPE
|
||||||
&& !vstd::contains((static_cast<const CGTownInstance*>(obj))->builtBuildings,6))
|
&& !static_cast<const CGTownInstance*>(obj)->hasBuilt(EBuilding::SHIPYARD))
|
||||||
{
|
{
|
||||||
complain("Cannot build boat in the town - no shipyard!");
|
complain("Cannot build boat in the town - no shipyard!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO use "real" cost via obj->getBoatCost
|
//TODO use "real" cost via obj->getBoatCost
|
||||||
if(getResource(obj->o->tempOwner, 6) < 1000 || getResource(obj->o->tempOwner, 0) < 10)
|
if(getResource(obj->o->tempOwner, Res::GOLD) < 1000 || getResource(obj->o->tempOwner, Res::WOOD) < 10)
|
||||||
{
|
{
|
||||||
complain("Not enough resources to build a boat!");
|
complain("Not enough resources to build a boat!");
|
||||||
return false;
|
return false;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user