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

#39 and #106 - fixed cosmetic buildings behaviour

#102 - fixed config + requirements system
#161 - extended clickable rectangle
and some minor fixes
This commit is contained in:
Ivan Savenko 2009-12-29 13:40:16 +00:00
parent eb6f7fffc9
commit def041a8c9
18 changed files with 184 additions and 167 deletions

View File

@ -815,6 +815,11 @@ int CCallback::canBuildStructure( const CGTownInstance *t, int ID )
return gs->canBuildStructure(t,ID);
}
std::set<int> CCallback::getBuildingRequiments( const CGTownInstance *t, int ID )
{
return gs->getBuildingRequiments(t,ID);
}
bool CCallback::getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath &ret)
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);

View File

@ -156,7 +156,7 @@ public:
virtual std::vector < const CGTownInstance *> getTownsInfo(bool onlyOur=true) const=0;
virtual std::vector<const CGHeroInstance *> getAvailableHeroes(const CGTownInstance * town) const =0; //heroes that can be recruited
virtual int canBuildStructure(const CGTownInstance *t, int ID) =0;//// 0 - no more than one capitol, 1 - lack of water, 2 - forbidden, 3 - Add another level to Mage Guild, 4 - already built, 5 - cannot build, 6 - cannot afford, 7 - build, 8 - lack of requirements
virtual std::set<int> getBuildingRequiments(const CGTownInstance *t, int ID) =0;
virtual void getMarketOffer(int t1, int t2, int &give, int &rec, int mode=0)const =0; //t1 - type of given resource, t2 - type of received resource; give is the amount of resource t1 that can be traded for amount rec of resource t2 (one of them is 1)
virtual bool getTownInfo(const CGObjectInstance *town, InfoAboutTown &dest) const = 0;
@ -273,6 +273,7 @@ public:
std::vector<const CGHeroInstance *> getAvailableHeroes(const CGTownInstance * town) const; //heroes that can be recruited
const TerrainTile * getTileInfo(int3 tile) const;
int canBuildStructure(const CGTownInstance *t, int ID);//// 0 - no more than one capitol, 1 - lack of water, 2 - forbidden, 3 - Add another level to Mage Guild, 4 - already built, 5 - cannot build, 6 - cannot afford, 7 - build, 8 - lack of requirements
std::set<int> getBuildingRequiments(const CGTownInstance *t, int ID);
bool getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath &ret);
const CGPathNode *getPathInfo(int3 tile);
bool getPath2(int3 dest, CGPath &ret);

View File

@ -157,9 +157,6 @@ void AdventureMapButton::clickRight(tribool down, bool previousState)
void AdventureMapButton::hover (bool on)
{
if(blocked)
return;
if(hoverable)
{
if(on)
@ -586,7 +583,10 @@ CSlider::CSlider(int x, int y, int totalw, boost::function<void(int)> Moved, int
if(style == 0)
{
imgs = CDefHandler::giveDefEss("IGPCRDIV.DEF");
if (horizontal)
imgs = CDefHandler::giveDefEss("IGPCRDIV.DEF");
else
imgs = CDefHandler::giveDefEss("OVBUTN2.DEF");
left->imgs.resize(1); right->imgs.resize(1); slider->imgs.resize(1);
left->imgs[0].push_back(imgs->ourImages[0].bitmap); left->imgs[0].push_back(imgs->ourImages[1].bitmap);
right->imgs[0].push_back(imgs->ourImages[2].bitmap); right->imgs[0].push_back(imgs->ourImages[3].bitmap);

View File

@ -159,47 +159,38 @@ SDL_Surface * BitmapHandler::loadBitmap(std::string fname, bool setKey)
}
if(e->offset<0)
{
fname.replace(fname.find_last_of('.'),fname.find_last_of('.')+4,".BMP");
fname = e->realName;
fname = DATA_DIR "/Data/" + fname;
FILE * f = fopen(fname.c_str(),"r");
if(f)
char sign[3];
f = fopen(fname.c_str(),"r");
if(!f)
{
tlog1 << "Cannot open " << fname << " - not present as bmp nor as pcx.\n";
return NULL;
}
fread(sign,1,3,f);
if(sign[0]=='B' && sign[1]=='M') //BMP named as PCX - people (eg. Kulex) sometimes use such files
{
fclose(f);
return SDL_LoadBMP(fname.c_str());
}
else //file .bmp not present, check .pcx
else //PCX - but we don't know which
{
char sign[3];
fname.replace(fname.find_last_of('.'),fname.find_last_of('.')+4,".PCX");
f = fopen(fname.c_str(),"r");
if(!f)
{
tlog1 << "Cannot open " << fname << " - not present as bmp nor as pcx.\n";
return NULL;
}
fread(sign,1,3,f);
if(sign[0]=='B' && sign[1]=='M') //BMP named as PCX - people (eg. Kulex) sometimes use such files
if((sign[0]==10) && (sign[1]<6) && (sign[2]==1)) //ZSoft PCX
{
fclose(f);
return SDL_LoadBMP(fname.c_str());
return IMG_Load(fname.c_str());
}
else //PCX - but we don't know which
else //H3-style PCX
{
if((sign[0]==10) && (sign[1]<6) && (sign[2]==1)) //ZSoft PCX
{
fclose(f);
return IMG_Load(fname.c_str());
}
else //H3-style PCX
{
CPCXConv cp;
pcx = new unsigned char[e->realSize];
memcpy(pcx,sign,3);
int res = fread((char*)pcx+3, 1, e->realSize-3, f); //TODO use me
fclose(f);
cp.openPCX((char*)pcx,e->realSize);
return cp.getSurface();
}
CPCXConv cp;
pcx = new unsigned char[e->realSize];
memcpy(pcx,sign,3);
int res = fread((char*)pcx+3, 1, e->realSize-3, f); //TODO use me
fclose(f);
cp.openPCX((char*)pcx,e->realSize);
return cp.getSurface();
}
}
}

View File

@ -442,7 +442,6 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, int listPos)
garr->splitButtons.push_back(split);
statusbar = new CStatusBar(pos.x+7,pos.y+555,"TSTATBAR.bmp",732);
resdatabar = new CResDataBar("ZRESBAR.bmp",pos.x+3,pos.y+575,32,2,85,85);
resdatabar->pos.x = pos.x+3; resdatabar->pos.y = pos.y+575;
townlist->fun = boost::bind(&CCastleInterface::townChange,this);
townlist->genList();
@ -622,11 +621,8 @@ void CCastleInterface::buildingClicked(int building)
GH.pushInt(cmw);
break;
}
case 15: //resource silo
{
LOCPLINT->showInfoDialog(CGI->buildh->buildings[town->subID][15]->Description(),std::vector<SComponent*>(), soundBase::sound_todo);
break;
}
//case 15: //resource silo - default handling should be enought
case 16: //blacksmith
{
const CGHeroInstance *hero = town->visitingHero;
@ -662,7 +658,7 @@ void CCastleInterface::buildingClicked(int building)
break;
default:
tlog4<<"This building isn't handled...\n";
defaultBuildingClicked(building);
break;
}
break;
@ -672,10 +668,20 @@ void CCastleInterface::buildingClicked(int building)
//TODO: case 25: //upg horde 2
//TODO: case 26: //grail
default:
tlog4<<"This building isn't handled...\n";
defaultBuildingClicked(building);
break;
}
}
}
void CCastleInterface::defaultBuildingClicked(int building)
{
std::vector<SComponent*> comps(1,
new CCustomImgComponent(SComponent::building,town->subID,building,bicons->ourImages[building].bitmap,false));
LOCPLINT->showInfoDialog(
CGI->buildh->buildings[town->subID][building]->Description(),
comps, soundBase::sound_todo);
}
void CCastleInterface::enterHall()
{
@ -1034,7 +1040,7 @@ void CCastleInterface::CCreaInfo::clickLeft(tribool down, bool previousState)
}
};
int AddToString(std::string from, std::string & to, int numb)
int CCastleInterface::CCreaInfo::AddToString(std::string from, std::string & to, int numb)
{
if (!numb)
return 0;//do not add string if 0
@ -1077,8 +1083,8 @@ void CCastleInterface::CCreaInfo::clickRight(tribool down, bool previousState)
CGI->creh->creatures[crid].hordeGrowth);
cnt = 0;
for (std::vector<CGDwelling*>::const_iterator it = CGI->state->players[0].dwellings.begin();
it !=CGI->state->players[0].dwellings.end(); ++it)
for (std::vector<CGDwelling*>::const_iterator it = CGI->state->players[ci->town->tempOwner].dwellings.begin();
it !=CGI->state->players[ci->town->tempOwner].dwellings.end(); ++it)
if (CGI->creh->creatures[crid].idNumber == (*it)->creatures[0].second[0])
cnt++;//external dwellings count to summ
summ+=AddToString(CGI->generaltexth->allTexts[591],descr,cnt);
@ -1362,7 +1368,7 @@ CHallInterface::CBuildingBox::CBuildingBox(int id)
:BID(id)
{
pos.w = 150;
pos.h = 70;
pos.h = 88;
}
CHallInterface::CBuildingBox::CBuildingBox(int id, int x, int y)
:BID(id)
@ -1370,7 +1376,7 @@ CHallInterface::CBuildingBox::CBuildingBox(int id, int x, int y)
pos.x = x;
pos.y = y;
pos.w = 150;
pos.h = 70;
pos.h = 88;
}
@ -1382,6 +1388,7 @@ CHallInterface::CHallInterface(CCastleInterface * owner)
resdatabar->pos.y += pos.y;
LOCPLINT->castleInt->statusbar->clear();
bg = BitmapHandler::loadBitmap(CGI->buildh->hall[owner->town->subID].first);
bid = owner->town->hallLevel()+10;
graphics->blueToPlayersAdv(bg,LOCPLINT->playerID);
exit = new AdventureMapButton
(CGI->generaltexth->hcommands[8],"",boost::bind(&CHallInterface::close,this),pos.x+748,pos.y+556,"TPMAGE1.DEF",SDLK_RETURN);
@ -1457,6 +1464,7 @@ void CHallInterface::show(SDL_Surface * to)
{
blitAt(bg,pos,to);
LOCPLINT->castleInt->statusbar->show(to);
printAtMiddle(CGI->buildh->buildings[LOCPLINT->castleInt->town->subID][bid]->Name(),400+pos.x,13+pos.y,GEORXX,zwykly,to);
resdatabar->show(to);
exit->show(to);
for(int i=0; i<5; i++)
@ -1553,53 +1561,19 @@ std::string CHallInterface::CBuildWindow::getTextForState(int state)
case 8:
{
ret = CGI->generaltexth->allTexts[52];
std::set<int> used;
used.insert(bid);
std::set<int> reqs;
std::set<int> reqs= LOCPLINT->cb->getBuildingRequiments(LOCPLINT->castleInt->town, bid);
for(std::set<int>::iterator i=CGI->townh->requirements[tid][bid].begin();
i!=CGI->townh->requirements[tid][bid].end();
i++
)
{
if (LOCPLINT->castleInt->town->builtBuildings.find(*i) == LOCPLINT->castleInt->town->builtBuildings.end())
reqs.insert(*i);
}
while(true)
{
size_t czystych=0;
for(std::set<int>::iterator i=reqs.begin();i!=reqs.end();i++)
{
if(used.find(*i)==used.end()) //we haven't added requirements for this building
{
used.insert(*i);
for(
std::set<int>::iterator j=CGI->townh->requirements[tid][*i].begin();
j!=CGI->townh->requirements[tid][*i].end();
j++
)
{
if(LOCPLINT->castleInt->town->builtBuildings.find(*j) == //this building is not built
LOCPLINT->castleInt->town->builtBuildings.end())
reqs.insert(*j);
}
}
else
{
czystych++;
}
}
if(czystych==reqs.size())
break;
}
bool first=true;
for(std::set<int>::iterator i=reqs.begin();i!=reqs.end();i++)
{
if (vstd::contains(LOCPLINT->castleInt->town->builtBuildings, *i))
continue;//skipping constructed buildings
ret+=(((first)?(" "):(", ")) + CGI->buildh->buildings[tid][*i]->Name());
first = false;
first = false;//TODO - currently can return "Mage guild lvl 1, MG lvl 2..." - extra check needed
}
}
}
return ret;
}

View File

@ -78,6 +78,7 @@ class CCastleInterface : public CWindowWithGarrison
int crid,bid;
CCreaInfo(int CRID, int BID); //c-tor
~CCreaInfo();//d-tor
int AddToString(std::string from, std::string & to, int numb);
void hover(bool on);
void clickLeft(tribool down, bool previousState);
void clickRight(tribool down, bool previousState);
@ -128,6 +129,7 @@ public:
void show(SDL_Surface * to);
void showAll(SDL_Surface * to);
void buildingClicked(int building);
void defaultBuildingClicked(int building);//for buildings with simple description + pic left-click messages
void enterTavern();
void enterMageGuild();
void splitClicked(); //for hero meeting (splitting stacks is handled by garrison int)
@ -189,7 +191,7 @@ public:
AdventureMapButton *exit;
SDL_Surface * bg; //background
int bid;//building ID
CHallInterface(CCastleInterface * owner); //c-tor
~CHallInterface(); //d-tor

View File

@ -16,6 +16,7 @@
#include "CCreatureAnimation.h"
#include "Graphics.h"
#include "../hch/CArtHandler.h"
#include "../hch/CBuildingHandler.h"
#include "../hch/CGeneralTextHandler.h"
#include "../hch/CHeroHandler.h"
#include "../hch/CLodHandler.h"
@ -814,6 +815,10 @@ void SComponent::init(Etype Type, int Subtype, int Val)
}
subtitle = oss.str();
break;
case building:
description = CGI->buildh->buildings[Subtype][Val]->Description();
subtitle = CGI->buildh->buildings[Subtype][Val]->Name();
break;
case secskill44: case secskill:
subtitle += CGI->generaltexth->levels[Val-1] + " " + CGI->generaltexth->skillName[Subtype];
description = CGI->generaltexth->skillInfoTexts[Subtype][Val-1];

View File

@ -130,7 +130,7 @@ class SComponent : public virtual CIntObject //common popup window component
public:
enum Etype
{
primskill, secskill, resource, creature, artifact, experience, secskill44, spell, morale, luck
primskill, secskill, resource, creature, artifact, experience, secskill44, spell, morale, luck, building
} type; //component type
int subtype; //TODO: comment me
int val; //TODO: comment me

View File

@ -292,6 +292,7 @@ Graphics::Graphics()
tasks += GET_DEF_ESS(bigTownPic,"ITPT.DEF");
tasks += GET_DEF_ESS(pskillsb,"PSKILL.DEF");
tasks += GET_DEF_ESS(pskillsm,"PSKIL42.DEF");
tasks += GET_DEF_ESS(pskillst,"PSKIL32.DEF");
tasks += GET_DEF_ESS(resources,"RESOUR82.DEF");
tasks += GET_DEF_ESS(un44,"UN44.DEF");
tasks += GET_DEF_ESS(smallIcons,"ITPA.DEF");

View File

@ -70,7 +70,8 @@ public:
std::vector<SDL_Surface *> portraitLarge; //58x64 px portraits of heroes
std::vector<CDefEssential *> flags1, flags2, flags3, flags4; //flags blitted on heroes when ,
CDefEssential * pskillsb, *resources; //82x93
CDefEssential * pskillsm; //42x42
CDefEssential * pskillsm; //42x42 primary skills
CDefEssential * pskillst; //32x32
CDefEssential * un44; //many things
CDefEssential * smallIcons, *resources32; //resources 32x32
CDefEssential * flags;

View File

@ -167,7 +167,7 @@
4 21 TBNCEXT0.def 307 61
4 22 TBNCEXT1.def 247 275
4 -1 TBNCEXT2.def 25 279
4 27 TBNCEXT3.def 307 246
4 27 TBNCEXT3.def 0 241
4 28 TBNCEXT4.def 321 255
4 29 TBNCEXT5.def 475 257
4 11 TBNCHAL2.def 482 56

View File

@ -49,8 +49,10 @@ CASTLE 1
11
12
13
17
21
22
23
-1
27
28

View File

@ -6,24 +6,23 @@
4 3
8 7
9 8
11 5
11 10 5
12 11 0 14 16
13 12 7 8 9
13 12 9
15 14
16 10
17 6
18 7 16 30 32 33
19 7 16 30 39 33
18 32
19 39
20 6
21 7 16 30 33
21 33
22 5
30 7
31 7 30
32 7 16 30 33
33 7 16 30
34 0 7 16 30 33
35 7 16 21 30 33
36 0 7 16 30 33 34
31 30
32 33
33 16 30
34 0 33
35 21
36 34
37 30
38 31
39 32
@ -39,11 +38,10 @@
4 3
8 7
9 8
11 5
11 10 5
12 11 0 14 16
13 12 7 8 9
13 12 9
15 14
16 10
18 31
19 38
21 17
@ -72,11 +70,10 @@
4 3
8 7
9 8
11 5
11 10 5
12 11 0 14 16
13 12 7 8 9
13 12 9
15 14
16 10
17 14
18 31
19 38
@ -105,11 +102,10 @@
4 3
8 7
9 8
11 5
11 10 5
12 11 0 14 16
13 12 7 8 9
13 12 9
15 14
16 10
18 30
19 37
21 7
@ -139,14 +135,13 @@
4 3
8 7
9 8
11 5
11 10 5
12 11 0 14 16
13 12 7 8 9
13 12 9
15 14
16 10
17 7
18 30
19 37
18 22 30
19 22 37
20 6
21 0
22 30
@ -172,17 +167,14 @@
4 3
8 7
9 8
11 5
11 10 5
12 11 0 14 16
13 12 7 8 9
13 12 9
15 14
16 10
17 14
18 30
19 37
21 0
22 10
23 10
30 7
31 30
32 30
@ -205,11 +197,10 @@
4 3
8 7
9 8
11 5
11 10 5
12 11 0 14 16
13 12 7 8 9
13 12 9
15 14
16 10
17 7
18 30
19 37
@ -238,11 +229,10 @@
4 3
8 7
9 8
11 5
11 10 5
12 11 0 14 16
13 12 7 8 9
13 12 9
15 14
16 10
17 11 21
18 30
19 37
@ -270,18 +260,17 @@
4 3
8 7
9 8
11 5
11 10 5
12 11 0 14 16
13 12 7 8 9
13 12 9
15 14
16 10
17 14
18 30
19 37
21 0
30 7
31 30
32 30
31 30 0
32 30 0
33 31
34 32
35 33 34
@ -289,8 +278,8 @@
37 30
38 31
39 32
40 33
40 33 31
41 34
42 35
42 35 1
43 36
-1

View File

@ -227,12 +227,14 @@ void CLodHandler::init(std::string lodFile, std::string dirName)
if(boost::filesystem::is_regular(dir->status()))
{
std::string name = dir->path().leaf();
std::string realname = name;
std::transform(name.begin(), name.end(), name.begin(), (int(*)(int))toupper);
boost::algorithm::replace_all(name,".BMP",".PCX");
Entry * e = entries.znajdz(name);
if(e) //file present in .lod - overwrite its entry
{
e->offset = -1;
e->realName = realname;
e->realSize = e->size = boost::filesystem::file_size(dir->path());
}
else //file not present in lod - add entry for it
@ -240,6 +242,7 @@ void CLodHandler::init(std::string lodFile, std::string dirName)
Entry e2;
e2.offset = -1;
e2.nameStr = name;
e2.realName = realname;
e2.realSize = e2.size = boost::filesystem::file_size(dir->path());
entries.push_back(e2);
}

View File

@ -40,7 +40,8 @@ struct LodEntry {
struct Entry
{
// Info extracted from LOD file
std::string nameStr;
std::string nameStr,
realName;
int offset, //from beginning
realSize, //size without compression
size; //and with

View File

@ -1797,9 +1797,46 @@ int CGameState::getMovementCost(const CGHeroInstance *h, const int3 &src, const
return ret;
}
std::set<int> CGameState::getBuildingRequiments(const CGTownInstance *t, int ID)
{
std::set<int> used;
used.insert(ID);
std::set<int> reqs = VLC->townh->requirements[t->subID][ID];
while(true)
{
size_t noloop=0;
for(std::set<int>::iterator i=reqs.begin();i!=reqs.end();i++)
{
if(used.find(*i)==used.end()) //we haven't added requirements for this building
{
used.insert(*i);
for(
std::set<int>::iterator j=VLC->townh->requirements[t->subID][*i].begin();
j!=VLC->townh->requirements[t->subID][*i].end();
j++)
{
reqs.insert(*j);//creating full list of requirements
}
}
else
{
noloop++;
}
}
if(noloop==reqs.size())
break;
}
return reqs;
}
int CGameState::canBuildStructure( const CGTownInstance *t, int ID )
{
int ret = 7; //allowed by default
if(t->builded >= MAX_BUILDING_PER_TURN)
ret = 5; //building limit
//checking resources
CBuilding * pom = VLC->buildh->buildings[t->subID][ID];
@ -1813,9 +1850,9 @@ int CGameState::canBuildStructure( const CGTownInstance *t, int ID )
}
//checking for requirements
for( std::set<int>::iterator ri = VLC->townh->requirements[t->subID][ID].begin();
ri != VLC->townh->requirements[t->subID][ID].end();
ri++ )
std::set<int> reqs = getBuildingRequiments(t, ID);//getting all requiments
for( std::set<int>::iterator ri = reqs.begin(); ri != reqs.end(); ri++ )
{
if(t->builtBuildings.find(*ri)==t->builtBuildings.end())
ret = 8; //lack of requirements - cannot build
@ -1824,8 +1861,6 @@ int CGameState::canBuildStructure( const CGTownInstance *t, int ID )
//can we build it?
if(t->forbiddenBuildings.find(ID)!=t->forbiddenBuildings.end())
ret = 2; //forbidden
else if(t->builded >= MAX_BUILDING_PER_TURN)
ret = 5; //building limit
if(ID == 13) //capitol
{

View File

@ -373,6 +373,7 @@ public:
bool battleCanShoot(int ID, int dest); //determines if stack with given ID shoot at the selected destination
UpgradeInfo getUpgradeInfo(const CArmedInstance *obj, int stackPos);
float getMarketEfficiency(int player, int mode=0);
std::set<int> getBuildingRequiments(const CGTownInstance *t, int ID);
int canBuildStructure(const CGTownInstance *t, int ID);// 0 - no more than one capitol, 1 - lack of water, 2 - forbidden, 3 - Add another level to Mage Guild, 4 - already built, 5 - cannot build, 6 - cannot afford, 7 - build, 8 - lack of requirements
bool checkForVisitableDir(const int3 & src, const int3 & dst) const; //check if src tile is visitable from dst tile
bool checkForVisitableDir(const int3 & src, const TerrainTile *pom, const int3 & dst) const; //check if src tile is visitable from dst tile

View File

@ -2041,6 +2041,12 @@ bool CGameHandler::buildStructure( si32 tid, si32 bid )
ssi.creatures[bid-30].second.push_back(crid);
sendAndApply(&ssi);
}
else if(bid == 11)
ns.bid.insert(27);
else if(bid == 12)
ns.bid.insert(28);
else if(bid == 13)
ns.bid.insert(29);
ns.bid.insert(bid);
ns.builded = t->builded + 1;