瀏覽代碼

Mostly working building and requirements

Michał W. Urbańczyk 17 年之前
父節點
當前提交
ac82c2fe5a
共有 6 個文件被更改,包括 201 次插入75 次删除
  1. 4 2
      CCallback.cpp
  2. 173 72
      CCastleInterface.cpp
  3. 6 1
      CCastleInterface.h
  4. 1 0
      CGameInterface.h
  5. 16 0
      CPlayerInterface.cpp
  6. 1 0
      CPlayerInterface.h

+ 4 - 2
CCallback.cpp

@@ -523,13 +523,15 @@ bool CCallback::buildBuilding(const CGTownInstance *town, int buildingID)
 {
 	CGTownInstance * t = const_cast<CGTownInstance *>(town);
 	CBuilding *b = CGI->buildh->buildings[t->subID][buildingID];
-	//TODO: check if we are allowed to build
+	
+	if(0/*not allowed*/)//TODO: check if we are allowed to build
+		return false;
 
 	t->builtBuildings.insert(buildingID);
 	for(int i=0;i<7;i++)
 		gs->players[player].resources[i]-=b->resources[i];
 	t->builded++;
-
+	CGI->playerint[CGI->state->players[player].serial]->buildChanged(town,buildingID,1);
 	return true;
 }
 

+ 173 - 72
CCastleInterface.cpp

@@ -13,7 +13,7 @@
 #include "hch/CGeneralTextHandler.h"
 extern TTF_Font * GEOR16;
 CBuildingRect::CBuildingRect(Structure *Str)
-:str(Str)
+:str(Str), moi(false)
 {	
 	def = CGI->spriteh->giveDef(Str->defName);
 	pos.x = str->pos.x;
@@ -48,12 +48,16 @@ void CBuildingRect::activate()
 	Hoverable::activate();
 	ClickableL::activate();
 	ClickableR::activate();
+
 }
 void CBuildingRect::deactivate()
 {
 	Hoverable::deactivate();
 	ClickableL::deactivate();
 	ClickableR::deactivate();
+	if(moi)
+		MotionInterested::deactivate();
+	moi=false;
 }
 bool CBuildingRect::operator<(const CBuildingRect & p2) const
 {
@@ -67,11 +71,15 @@ void CBuildingRect::hover(bool on)
 	Hoverable::hover(on);
 	if(on)
 	{
-		MotionInterested::activate();
+		if(!moi)
+			MotionInterested::activate();
+		moi = true;
 	}
 	else 
 	{
-		MotionInterested::deactivate();
+		if(moi)
+			MotionInterested::deactivate();
+		moi = false;
 		if(LOCPLINT->castleInt->hBuild == this)
 		{
 			LOCPLINT->castleInt->hBuild = NULL;
@@ -214,60 +222,10 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, bool Activate)
 
 	CSDL_Ext::blueToPlayersAdv(townInt,LOCPLINT->playerID);
 	exit->bitmapOffset = 4;
-	std::set< std::pair<int,int> > s; //group - id
 
 
 	//buildings
-	for (std::set<int>::const_iterator i=town->builtBuildings.begin();i!=town->builtBuildings.end();i++)
-	{
-		if(CGI->townh->structures.find(town->subID) != CGI->townh->structures.end()) //we have info about structures in this town
-		{
-			if(CGI->townh->structures[town->subID].find(*i)!=CGI->townh->structures[town->subID].end()) //we have info about that structure
-			{
-				Structure * st = CGI->townh->structures[town->subID][*i];
-				if(st->group<0) //no group - just add it
-				{
-					buildings.push_back(new CBuildingRect(st));
-				}
-				else
-				{
-					std::set< std::pair<int,int> >::iterator obecny=s.end();
-					for(std::set< std::pair<int,int> >::iterator seti = s.begin(); seti!=s.end(); seti++) //check if we have already building from same group
-					{
-						if(seti->first == st->group)
-						{
-							obecny = seti; 
-							break;
-						}
-					}
-					if(obecny != s.end())
-					{
-						if((*(CGI->townh->structures[town->subID][obecny->second])) < (*(CGI->townh->structures[town->subID][st->ID]))) //we have to replace old building with current one
-						{
-							for(int itpb = 0; itpb<buildings.size(); itpb++)
-							{
-								if(buildings[itpb]->str->ID == obecny->second)
-								{
-									delete buildings[itpb];
-									buildings.erase(buildings.begin() + itpb);
-									obecny->second = st->ID;
-									buildings.push_back(new CBuildingRect(st));
-								}
-							}
-						}
-					}
-					else
-					{
-						buildings.push_back(new CBuildingRect(st));
-						s.insert(std::pair<int,int>(st->group,st->ID));
-					}
-				}
-			}
-			else continue;
-		}
-		else
-			break;
-	}
+	recreateBuildings();
 
 
 	//garrison
@@ -511,6 +469,83 @@ void CCastleInterface::deactivate()
 		buildings[i]->deactivate();
 }
 
+void CCastleInterface::addBuilding(int bid)
+{
+	//TODO: lepiej by bylo tylko dodawac/usuwac co trzeba pamietajac o grupach
+	recreateBuildings();
+}
+
+void CCastleInterface::removeBuilding(int bid)
+{
+	//TODO: lepiej by bylo tylko dodawac/usuwac co trzeba pamietajac o grupach
+	recreateBuildings();
+}
+
+void CCastleInterface::recreateBuildings()
+{
+	for(int i=0;i<buildings.size();i++)
+	{
+		if(showing)
+			buildings[i]->deactivate();
+		delete buildings[i];
+	}
+	buildings.clear();
+	hBuild = NULL;
+
+	std::set< std::pair<int,int> > s; //group - id
+
+
+		for (std::set<int>::const_iterator i=town->builtBuildings.begin();i!=town->builtBuildings.end();i++)
+	{
+		if(CGI->townh->structures.find(town->subID) != CGI->townh->structures.end()) //we have info about structures in this town
+		{
+			if(CGI->townh->structures[town->subID].find(*i)!=CGI->townh->structures[town->subID].end()) //we have info about that structure
+			{
+				Structure * st = CGI->townh->structures[town->subID][*i];
+				if(st->group<0) //no group - just add it
+				{
+					buildings.push_back(new CBuildingRect(st));
+				}
+				else
+				{
+					std::set< std::pair<int,int> >::iterator obecny=s.end();
+					for(std::set< std::pair<int,int> >::iterator seti = s.begin(); seti!=s.end(); seti++) //check if we have already building from same group
+					{
+						if(seti->first == st->group)
+						{
+							obecny = seti; 
+							break;
+						}
+					}
+					if(obecny != s.end())
+					{
+						if((*(CGI->townh->structures[town->subID][obecny->second])) < (*(CGI->townh->structures[town->subID][st->ID]))) //we have to replace old building with current one
+						{
+							for(int itpb = 0; itpb<buildings.size(); itpb++)
+							{
+								if(buildings[itpb]->str->ID == obecny->second)
+								{
+									delete buildings[itpb];
+									buildings.erase(buildings.begin() + itpb);
+									obecny->second = st->ID;
+									buildings.push_back(new CBuildingRect(st));
+								}
+							}
+						}
+					}
+					else
+					{
+						buildings.push_back(new CBuildingRect(st));
+						s.insert(std::pair<int,int>(st->group,st->ID));
+					}
+				}
+			}
+			else continue;
+		}
+		else
+			break;
+	}
+}
 
 void CHallInterface::CResDataBar::show(SDL_Surface * to)
 {
@@ -600,7 +635,7 @@ void CHallInterface::CBuildingBox::show(SDL_Surface * to)
 		pom2 = 2;
 		pom = 2;
 		break;
-	case 0: case 5: 
+	case 0: case 5: case 8:
 		pom2 = 1;
 		pom = 2;
 		break;
@@ -682,7 +717,7 @@ CHallInterface::CHallInterface(CCastleInterface * owner)
 					if(owner->town->forbiddenBuildings.find(CGI->buildh->hall[owner->town->subID].second[i][j][k])!=owner->town->forbiddenBuildings.end())
 						boxes[i][boxes[i].size()-1]->state = 2; //forbidden
 					else if(owner->town->builded >= MAX_BUILDING_PER_TURN)
-						boxes[i][boxes[i].size()-1]->state = 5; //already built
+						boxes[i][boxes[i].size()-1]->state = 5; //building limit
 
 					//checking resources
 					CBuilding * pom = CGI->buildh->buildings[owner->town->subID][CGI->buildh->hall[owner->town->subID].second[i][j][k]];
@@ -698,7 +733,7 @@ CHallInterface::CHallInterface(CCastleInterface * owner)
 						 ri++ )
 					{
 						if(owner->town->builtBuildings.find(*ri)==owner->town->builtBuildings.end())
-							boxes[i][boxes[i].size()-1]->state = 5; //lack of requirements - cannot build
+							boxes[i][boxes[i].size()-1]->state = 8; //lack of requirements - cannot build
 					}
 
 					//TODO: check if capital is already built, check if there is water for shipyard
@@ -736,6 +771,7 @@ CHallInterface::~CHallInterface()
 void CHallInterface::close()
 {
 	deactivate();
+	delete this;
 	LOCPLINT->castleInt->activate();
 	LOCPLINT->castleInt->showAll();
 }
@@ -771,22 +807,31 @@ void CHallInterface::deactivate()
 
 void CHallInterface::CBuildWindow::activate()
 {
+	LOCPLINT->objsToBlit.push_back(this);
+	ClickableR::activate();
+	if(mode)
+		return;
 	buy->activate();
 	cancel->activate();
-	ClickableR::activate();
-	LOCPLINT->objsToBlit.push_back(this);
 }
 void CHallInterface::CBuildWindow::deactivate()
 {
+	LOCPLINT->objsToBlit.erase(std::find(LOCPLINT->objsToBlit.begin(),LOCPLINT->objsToBlit.end(),this));
+	ClickableR::deactivate();
+	if(mode)
+		return;
 	buy->deactivate();
 	cancel->deactivate();
-	ClickableR::deactivate();
-	LOCPLINT->objsToBlit.erase(std::find(LOCPLINT->objsToBlit.begin(),LOCPLINT->objsToBlit.end(),this));
 }
 void CHallInterface::CBuildWindow::Buy()
 {
 	LOCPLINT->cb->buildBuilding(LOCPLINT->castleInt->town,bid);
-	close();
+	deactivate();
+	delete this;
+	delete LOCPLINT->castleInt->hallInt;
+	LOCPLINT->castleInt->hallInt = NULL;
+	LOCPLINT->castleInt->activate();
+	LOCPLINT->castleInt->showAll();
 }
 void CHallInterface::CBuildWindow::close()
 {
@@ -805,20 +850,70 @@ void CHallInterface::CBuildWindow::show(SDL_Surface * to)
 	SDL_Rect pom = genRect(bitmap->h-1,bitmap->w-1,pos.x,pos.y);
 	SDL_Rect poms = pom; poms.x=0;poms.y=0;
 	SDL_BlitSurface(bitmap,&poms,to?to:ekran,&pom);
-	buy->show();
-	cancel->show();
+	if(!mode)
+	{
+		buy->show();
+		cancel->show();
+	}
 }
-std::string getTextForState(int state)
+std::string CHallInterface::CBuildWindow::getTextForState(int state)
 {
+	std::string ret;
 	if(state<7)
-		return CGI->townh->hcommands[state];
+		ret =  CGI->townh->hcommands[state];
 	switch (state)
 	{
+	case 4:
+		ret.replace(ret.find_first_of("%s"),2,CGI->buildh->buildings[tid][bid]->name);
+		break;
 	case 7:
 		return CGI->generaltexth->allTexts[219]; //all prereq. are met
-	default:
-		return "Error, wrong state!";
+	case 8:
+		{
+			ret = CGI->generaltexth->allTexts[52];
+			std::set<int> used;
+			used.insert(bid);
+			std::set<int> reqs;
+			
+			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)
+			{
+				int 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++)
+			{
+				ret+=(((first)?(" "):(", ")) + CGI->buildh->buildings[tid][*i]->name);
+				first = false;
+			}
+		}
 	}
+	return ret;
 }
 CHallInterface::CBuildWindow::CBuildWindow(int Tid, int Bid, int State, bool Mode)
 :tid(Tid),bid(Bid),mode(Mode), state(State)
@@ -859,13 +954,19 @@ CHallInterface::CBuildWindow::CBuildWindow(int Tid, int Bid, int State, bool Mod
 		if(it==4)
 			ah+=75;
 	}
-	buy = new AdventureMapButton<CBuildWindow>("","",&CBuildWindow::Buy,pos.x+45,pos.y+446,"IBUY30.DEF",this,true,NULL,false);
-	cancel = new AdventureMapButton<CBuildWindow>("","",&CBuildWindow::close,pos.x+290,pos.y+445,"ICANCEL.DEF",this,true,NULL,false);
+	if(!mode)
+	{
+		buy = new AdventureMapButton<CBuildWindow>("","",&CBuildWindow::Buy,pos.x+45,pos.y+446,"IBUY30.DEF",this,true,NULL,false);
+		cancel = new AdventureMapButton<CBuildWindow>("","",&CBuildWindow::close,pos.x+290,pos.y+445,"ICANCEL.DEF",this,true,NULL,false);
+	}
 	activate();
 }
 CHallInterface::CBuildWindow::~CBuildWindow()
 {
 	SDL_FreeSurface(bitmap);
-	delete buy;
-	delete cancel;
+	if(!mode)
+	{
+		delete buy;
+		delete cancel;
+	}
 }

+ 6 - 1
CCastleInterface.h

@@ -11,6 +11,7 @@ template <typename T> class AdventureMapButton;
 class CBuildingRect : public Hoverable, public MotionInterested, public ClickableL, public ClickableR//, public TimeInterested
 {
 public:
+	bool moi; //motion interested is active
 	Structure* str;
 	CDefHandler* def;
 	SDL_Surface* border;
@@ -58,6 +59,9 @@ public:
 	void splitF();
 	void activate();
 	void deactivate();
+	void addBuilding(int bid);
+	void removeBuilding(int bid);
+	void recreateBuildings();
 };
 
 class CHallInterface : public IShowable, public IActivable
@@ -76,7 +80,7 @@ public:
 	{
 	public:
 		int BID;
-		int state;// 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
+		int state;// 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
 		//(-1) - forbidden in this town, 0 - possible, 1 - lack of res, 2 - requirements/buildings per turn limit, (3) - already exists
 		void hover(bool on);
 		void clickLeft (tribool down);
@@ -99,6 +103,7 @@ public:
 
 		void activate();
 		void deactivate();
+		std::string getTextForState(int state);
 		void clickRight (tribool down);
 		void show(SDL_Surface * to=NULL);
 		void Buy();

+ 1 - 0
CGameInterface.h

@@ -41,6 +41,7 @@ public:
 	virtual void receivedResource(int type, int val){};
 	virtual void showSelDialog(std::string text, std::vector<CSelectableComponent*> & components, int askID)=0{};
 	virtual void garrisonChanged(const CGObjectInstance * obj){};
+	virtual void buildChanged(const CGTownInstance *town, int buildingID, int what){}; //what: 1 - built, 2 - demolished
 	//battle call-ins 
 	virtual void battleStart(CCreatureSet * army1, CCreatureSet * army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side){}; //called by engine when battle starts; side=0 - left, side=1 - right
 	virtual void battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles){}; //called when battlefield is prepared, prior the battle beginning

+ 16 - 0
CPlayerInterface.cpp

@@ -1856,6 +1856,22 @@ void CPlayerInterface::garrisonChanged(const CGObjectInstance * obj)
 		}
 	}
 }
+void CPlayerInterface::buildChanged(const CGTownInstance *town, int buildingID, int what) //what: 1 - built, 2 - demolished
+{
+	if(curint!=castleInt)
+		return;
+	if(castleInt->town!=town)
+		return;
+	switch(what)
+	{
+	case 1:
+		castleInt->addBuilding(buildingID);
+		break;
+	case 2:
+		castleInt->removeBuilding(buildingID);
+		break;
+	}
+}
 
 void CPlayerInterface::battleStart(CCreatureSet * army1, CCreatureSet * army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, tribool side) //called by engine when battle starts; side=0 - left, side=1 - right
  {

+ 1 - 0
CPlayerInterface.h

@@ -308,6 +308,7 @@ public:
 	void showSelDialog(std::string text, std::vector<CSelectableComponent*> & components, int askID);
 	void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town);
 	void garrisonChanged(const CGObjectInstance * obj);
+	void buildChanged(const CGTownInstance *town, int buildingID, int what); //what: 1 - built, 2 - demolished
 
 	//battles
 	void battleStart(CCreatureSet * army1, CCreatureSet * army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, tribool side); //called by engine when battle starts; side=0 - left, side=1 - right