Przeglądaj źródła

Huge commit:
* correctly showing recruitment window (recruitment not ready)
* new slider class
* creature growths handled (horde buildings not yet supported)
* buttons more secure
* info about factions and their creatures
* costs of creatures merged into vector
* info about town structeres state (started)
* new function in CSDL_Ext for drawing borders
* numerous minor changes

Michał W. Urbańczyk 17 lat temu
rodzic
commit
36779118b5

+ 158 - 3
AdventureMapButton.h

@@ -17,7 +17,8 @@ public:
 	char key; //key shortcut
 	char key; //key shortcut
 	T* owner;
 	T* owner;
 	void (T::*function)(); //function in CAdvMapInt called when this button is pressed, different for each button
 	void (T::*function)(); //function in CAdvMapInt called when this button is pressed, different for each button
-	bool colorChange;
+	bool colorChange,
+		actOnDown; //runs when mouse is pressed down over it, not when up
 
 
 	void clickRight (tribool down);
 	void clickRight (tribool down);
 	void clickLeft (tribool down);
 	void clickLeft (tribool down);
@@ -27,7 +28,7 @@ public:
 	void deactivate(); // makes button inactive (but doesn't delete)
 	void deactivate(); // makes button inactive (but doesn't delete)
 
 
 	AdventureMapButton(); //c-tor
 	AdventureMapButton(); //c-tor
-	AdventureMapButton( std::string Name, std::string HelpBox, void(T::*Function)(), int x, int y, std::string defName, T* Owner, bool activ=false,  std::vector<std::string> * add = NULL, bool playerColoredButton = true );//c-tor
+	AdventureMapButton( std::string Name, std::string HelpBox, void(T::*Function)(), int x, int y, std::string defName, T* Owner, bool activ=false,  std::vector<std::string> * add = NULL, bool playerColoredButton = false );//c-tor
 };
 };
 
 
 template <typename T>
 template <typename T>
@@ -38,11 +39,13 @@ AdventureMapButton<T>::AdventureMapButton ()
 	active=false;
 	active=false;
 	ourObj=NULL;
 	ourObj=NULL;
 	state=0;
 	state=0;
+	actOnDown = false;
 }
 }
 template <typename T>
 template <typename T>
 AdventureMapButton<T>::AdventureMapButton
 AdventureMapButton<T>::AdventureMapButton
 ( std::string Name, std::string HelpBox, void(T::*Function)(), int x, int y, std::string defName, T* Owner, bool activ, std::vector<std::string> * add, bool playerColoredButton )
 ( std::string Name, std::string HelpBox, void(T::*Function)(), int x, int y, std::string defName, T* Owner, bool activ, std::vector<std::string> * add, bool playerColoredButton )
 {
 {
+	actOnDown = false;
 	owner = Owner;
 	owner = Owner;
 	type=2;
 	type=2;
 	abs=true;
 	abs=true;
@@ -101,7 +104,12 @@ void AdventureMapButton<T>::clickLeft (tribool down)
 		state=0;
 		state=0;
 	}
 	}
 	show();
 	show();
-	if (pressedL && (down==false))
+	if (actOnDown && down)
+	{
+		pressedL=state;
+		(owner->*function)();
+	}
+	else if (pressedL && (down==false))
 	{
 	{
 		pressedL=state;
 		pressedL=state;
 		(owner->*function)();
 		(owner->*function)();
@@ -366,4 +374,151 @@ void CTownList<T>::draw()
 		blitAt(arrdo->ourImages[0].bitmap,arrdop.x,arrdop.y);
 		blitAt(arrdo->ourImages[0].bitmap,arrdop.x,arrdop.y);
 	else
 	else
 		blitAt(arrdo->ourImages[2].bitmap,arrdop.x,arrdop.y);
 		blitAt(arrdo->ourImages[2].bitmap,arrdop.x,arrdop.y);
+}
+
+
+template<typename T>
+class CSlider : public IShowable, public MotionInterested, public ClickableL
+{
+public:
+	AdventureMapButton<CSlider> left, right, slider; //if vertical then left=up
+	int capacity,//how many elements can be active at same time
+		amount, //how many elements
+		value; //first active element
+	bool horizontal, moving;
+	CDefEssential *imgs ;
+
+	T* owner;
+	void(T::*moved)(int to);
+
+	void redrawSlider(); 
+
+	void sliderClicked();
+	void moveLeft();
+	void clickLeft (tribool down);
+	void mouseMoved (SDL_MouseMotionEvent & sEvent);
+	void moveRight();
+	void moveTo(int to);
+	void activate(); // makes button active
+	void deactivate(); // makes button inactive (but doesn't delete)
+	void show(SDL_Surface * to = NULL);
+	CSlider(int x, int y, int totalw, T*Owner,void(T::*Moved)(int to), int Capacity, int Amount, 
+		int Value=0, bool Horizontal=true);
+	~CSlider();
+};	
+
+template<typename T>
+void CSlider<T>::sliderClicked()
+{
+	if(!moving)
+	{
+		MotionInterested::activate();
+		moving = true;
+	}
+}
+template<typename T>
+void CSlider<T>::mouseMoved (SDL_MouseMotionEvent & sEvent)
+{
+	float v = sEvent.x - pos.x - 16;
+	v/= (pos.w - 48);
+	v*=amount;
+	if(v!=value)
+	{
+		moveTo(v);
+		redrawSlider();
+	}
+}
+template<typename T>
+void CSlider<T>::redrawSlider()
+{
+	slider.show();
+}
+template<typename T>
+void CSlider<T>::moveLeft()
+{
+	moveTo(value-1);
+}
+template<typename T>
+void CSlider<T>::moveRight()
+{
+	moveTo(value+1);
+}
+template<typename T>
+void CSlider<T>::moveTo(int to)
+{
+	if(to<0)
+		to=0;
+	else if(to>amount)
+		to=amount;
+	value = to;
+	float part = (float)to/amount;
+	part*=(pos.w-48);
+	slider.pos.x = part + pos.x + 16;
+	(owner->*moved)(to);
+}
+template<typename T>
+void CSlider<T>::activate() // makes button active
+{
+	left.activate();
+	right.activate();
+	slider.activate();
+	ClickableL::activate();
+}
+template<typename T>
+void CSlider<T>::deactivate() // makes button inactive (but doesn't delete)
+{
+	left.deactivate();
+	right.deactivate();
+	slider.deactivate();
+	ClickableL::deactivate();
+}
+template<typename T>
+void CSlider<T>::clickLeft (tribool down)
+{
+	if(down)
+		return;
+	if(moving)
+	{
+		MotionInterested::deactivate();
+		moving = false;
+	}
+}
+template<typename T>
+void CSlider<T>::show(SDL_Surface * to)
+{
+	left.show();
+	right.show();
+	slider.show();
+}
+template<typename T>
+CSlider<T>::CSlider(int x, int y, int totalw, T*Owner,void(T::*Moved)(int to), int Capacity, int Amount, int Value, bool Horizontal)
+:capacity(Capacity),amount(Amount),value(Value),horizontal(Horizontal), moved(Moved), owner(Owner)
+{
+	moving = false;
+	strongInterest = true;
+	imgs = CGI->spriteh->giveDefEss("IGPCRDIV.DEF");
+
+	left.pos.y = slider.pos.y = right.pos.y = pos.y = y;
+	left.pos.x = pos.x = x;
+	right.pos.x = x + totalw - 16;
+
+	left.owner = right.owner = slider.owner = this;
+	left.function = &CSlider::moveLeft;
+	right.function = &CSlider::moveRight;
+	slider.function = &CSlider::sliderClicked;
+	left.pos.w = left.pos.h = right.pos.w = right.pos.h = slider.pos.w = slider.pos.h = pos.h = 16;
+	pos.w = totalw;
+	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);
+	slider.imgs[0].push_back(imgs->ourImages[4].bitmap);
+	left.notFreeButton = right.notFreeButton = slider.notFreeButton = true;
+	slider.actOnDown = true;
+
+	moveTo(value);
+}
+template<typename T>
+CSlider<T>::~CSlider()
+{
+	delete imgs;
 }
 }

+ 10 - 10
CAdvmapInterface.cpp

@@ -807,34 +807,34 @@ CAdvMapInt::CAdvMapInt(int Player)
 :player(Player),
 :player(Player),
 statusbar(7,556),
 statusbar(7,556),
 kingOverview(CGI->preth->zelp[293].first,CGI->preth->zelp[293].second,
 kingOverview(CGI->preth->zelp[293].first,CGI->preth->zelp[293].second,
-			 &CAdvMapInt::fshowOverview, 679, 196, "IAM002.DEF", this),
+			 &CAdvMapInt::fshowOverview, 679, 196, "IAM002.DEF", this,false,NULL,true),
 
 
 underground(CGI->preth->zelp[294].first,CGI->preth->zelp[294].second,
 underground(CGI->preth->zelp[294].first,CGI->preth->zelp[294].second,
-		   &CAdvMapInt::fswitchLevel, 711, 196, "IAM010.DEF", this, false, new std::vector<std::string>(1,std::string("IAM003.DEF"))),
+		   &CAdvMapInt::fswitchLevel, 711, 196, "IAM010.DEF", this, false, new std::vector<std::string>(1,std::string("IAM003.DEF")),true),
 
 
 questlog(CGI->preth->zelp[295].first,CGI->preth->zelp[295].second,
 questlog(CGI->preth->zelp[295].first,CGI->preth->zelp[295].second,
-		 &CAdvMapInt::fshowQuestlog, 679, 228, "IAM004.DEF", this),
+		 &CAdvMapInt::fshowQuestlog, 679, 228, "IAM004.DEF", this,false,NULL,true),
 
 
 sleepWake(CGI->preth->zelp[296].first,CGI->preth->zelp[296].second,
 sleepWake(CGI->preth->zelp[296].first,CGI->preth->zelp[296].second,
-		  &CAdvMapInt::fsleepWake, 711, 228, "IAM005.DEF", this),
+		  &CAdvMapInt::fsleepWake, 711, 228, "IAM005.DEF", this,false,NULL,true),
 
 
 moveHero(CGI->preth->zelp[297].first,CGI->preth->zelp[297].second,
 moveHero(CGI->preth->zelp[297].first,CGI->preth->zelp[297].second,
-		  &CAdvMapInt::fmoveHero, 679, 260, "IAM006.DEF", this),
+		  &CAdvMapInt::fmoveHero, 679, 260, "IAM006.DEF", this,false,NULL,true),
 
 
 spellbook(CGI->preth->zelp[298].first,CGI->preth->zelp[298].second,
 spellbook(CGI->preth->zelp[298].first,CGI->preth->zelp[298].second,
-		  &CAdvMapInt::fshowSpellbok, 711, 260, "IAM007.DEF", this),
+		  &CAdvMapInt::fshowSpellbok, 711, 260, "IAM007.DEF", this,false,NULL,true),
 
 
 advOptions(CGI->preth->zelp[299].first,CGI->preth->zelp[299].second,
 advOptions(CGI->preth->zelp[299].first,CGI->preth->zelp[299].second,
-		  &CAdvMapInt::fadventureOPtions, 679, 292, "IAM008.DEF", this),
+		  &CAdvMapInt::fadventureOPtions, 679, 292, "IAM008.DEF", this,false,NULL,true),
 
 
 sysOptions(CGI->preth->zelp[300].first,CGI->preth->zelp[300].second,
 sysOptions(CGI->preth->zelp[300].first,CGI->preth->zelp[300].second,
-		  &CAdvMapInt::fsystemOptions, 711, 292, "IAM009.DEF", this),
+		  &CAdvMapInt::fsystemOptions, 711, 292, "IAM009.DEF", this,false,NULL,true),
 
 
 nextHero(CGI->preth->zelp[301].first,CGI->preth->zelp[301].second,
 nextHero(CGI->preth->zelp[301].first,CGI->preth->zelp[301].second,
-		  &CAdvMapInt::fnextHero, 679, 324, "IAM000.DEF", this),
+		  &CAdvMapInt::fnextHero, 679, 324, "IAM000.DEF", this,false,NULL,true),
 
 
 endTurn(CGI->preth->zelp[302].first,CGI->preth->zelp[302].second,
 endTurn(CGI->preth->zelp[302].first,CGI->preth->zelp[302].second,
-		  &CAdvMapInt::fendTurn, 679, 356, "IAM001.DEF", this),
+		  &CAdvMapInt::fendTurn, 679, 356, "IAM001.DEF", this,false,NULL,true),
 
 
 townList(5,&genRect(192,48,747,196),747,196,747,372)
 townList(5,&genRect(192,48,747,196),747,196,747,372)
 {
 {

+ 18 - 0
CCallback.cpp

@@ -46,13 +46,31 @@ void CCallback::newTurn()
 	}
 	}
 	for ( std::map<int, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end();i++)
 	for ( std::map<int, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end();i++)
 	{
 	{
+		//handle heroes/////////////////////////////
 		for (int j=0;j<(*i).second.heroes.size();j++)
 		for (int j=0;j<(*i).second.heroes.size();j++)
 		{
 		{
 			(*i).second.heroes[j]->movement = valMovePoints((*i).second.heroes[j]);
 			(*i).second.heroes[j]->movement = valMovePoints((*i).second.heroes[j]);
 		}
 		}
+
+
+		//handle towns/////////////////////////////
 		for(int j=0;j<i->second.towns.size();j++)
 		for(int j=0;j<i->second.towns.size();j++)
 		{
 		{
 			i->second.towns[j]->builded=0;
 			i->second.towns[j]->builded=0;
+			if(getDate(1)==1) //first day of week
+			{
+				for(int k=0;k<CREATURES_PER_TOWN;k++)
+				{
+					int growth;
+					if(i->second.towns[j]->creatureDwelling(k))//basic growth
+						  growth=CGI->creh->creatures[i->second.towns[j]->town->basicCreatures[k]].growth;
+					if(i->second.towns[j]->builtBuildings.find(9)!=i->second.towns[j]->builtBuildings.end()) //castle +100%
+						growth*=2;
+					else if(i->second.towns[j]->builtBuildings.find(9)!=i->second.towns[j]->builtBuildings.end()) //castle +100%
+						growth*=1.5;
+					i->second.towns[j]->strInfo.creatures[k]+=growth;
+				}
+			}
 		}
 		}
 	}
 	}
 }
 }

+ 27 - 9
CCastleInterface.cpp

@@ -229,7 +229,6 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, bool Activate)
 
 
 
 
 	//garrison
 	//garrison
-	std::sort(buildings.begin(),buildings.end(),srthlp);
 	garr = new CGarrisonInt(305,387,4,32,townInt,243,13,town,town->visitingHero);
 	garr = new CGarrisonInt(305,387,4,32,townInt,243,13,town,town->visitingHero);
 
 
 	if(Activate)
 	if(Activate)
@@ -312,6 +311,19 @@ void CCastleInterface::splitF()
 void CCastleInterface::buildingClicked(int building)
 void CCastleInterface::buildingClicked(int building)
 {
 {
 	std::cout<<"You've clicked on "<<building<<std::endl;
 	std::cout<<"You've clicked on "<<building<<std::endl;
+	if(building >= 30)
+	{
+		if(building>36)
+			building-=7;
+		std::vector<std::pair<int,int > > crs;
+		int amount = (const_cast<CGTownInstance*>(town))->strInfo.creatures[building-30]; //trzeba odconstowac, bo inaczej operator [] by sypal :(
+		crs.push_back(std::make_pair(town->town->basicCreatures[building-30],amount));
+
+		if(town->builtBuildings.find(building+7) != town->builtBuildings.end()) //check if there is an upgraded building
+			crs.push_back(std::make_pair(town->town->upgradedCreatures[building-30],amount));
+		CRecrutationWindow *rw = new CRecrutationWindow(crs);
+		rw->activate();
+	}
 	switch(building)
 	switch(building)
 	{
 	{
 	case 10: case 11: case 12: case 13:
 	case 10: case 11: case 12: case 13:
@@ -367,11 +379,10 @@ void CCastleInterface::showAll(SDL_Surface * to)
 		int cid = -1;
 		int cid = -1;
 		if (town->builtBuildings.find(30+i)!=town->builtBuildings.end())
 		if (town->builtBuildings.find(30+i)!=town->builtBuildings.end())
 		{
 		{
-			cid = (14*town->subID)+(i*2);
 			if (town->builtBuildings.find(30+CREATURES_PER_TOWN+i)!=town->builtBuildings.end())
 			if (town->builtBuildings.find(30+CREATURES_PER_TOWN+i)!=town->builtBuildings.end())
-			{
-				cid++;
-			}
+				cid = town->town->upgradedCreatures[i];
+			else
+				cid = town->town->basicCreatures[i];
 		}
 		}
 		if (cid>=0)
 		if (cid>=0)
 		{
 		{
@@ -545,6 +556,7 @@ void CCastleInterface::recreateBuildings()
 		else
 		else
 			break;
 			break;
 	}
 	}
+	std::sort(buildings.begin(),buildings.end(),srthlp);
 }
 }
 
 
 void CHallInterface::CResDataBar::show(SDL_Surface * to)
 void CHallInterface::CResDataBar::show(SDL_Surface * to)
@@ -811,7 +823,8 @@ void CHallInterface::CBuildWindow::activate()
 	ClickableR::activate();
 	ClickableR::activate();
 	if(mode)
 	if(mode)
 		return;
 		return;
-	buy->activate();
+	if(state==7)
+		buy->activate();
 	cancel->activate();
 	cancel->activate();
 }
 }
 void CHallInterface::CBuildWindow::deactivate()
 void CHallInterface::CBuildWindow::deactivate()
@@ -820,7 +833,8 @@ void CHallInterface::CBuildWindow::deactivate()
 	ClickableR::deactivate();
 	ClickableR::deactivate();
 	if(mode)
 	if(mode)
 		return;
 		return;
-	buy->deactivate();
+	if(state==7)
+		buy->deactivate();
 	cancel->deactivate();
 	cancel->deactivate();
 }
 }
 void CHallInterface::CBuildWindow::Buy()
 void CHallInterface::CBuildWindow::Buy()
@@ -956,8 +970,12 @@ CHallInterface::CBuildWindow::CBuildWindow(int Tid, int Bid, int State, bool Mod
 	}
 	}
 	if(!mode)
 	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);
+		buy = new AdventureMapButton<CBuildWindow>
+			("","",&CBuildWindow::Buy,pos.x+45,pos.y+446,"IBUY30.DEF",this,false,NULL,false);
+		cancel = new AdventureMapButton<CBuildWindow>
+			("","",&CBuildWindow::close,pos.x+290,pos.y+445,"ICANCEL.DEF",this,false,NULL,false);
+		if(state!=7)
+			buy->state=2;
 	}
 	}
 	activate();
 	activate();
 }
 }

+ 149 - 3
CPlayerInterface.cpp

@@ -695,12 +695,19 @@ void CButtonBase::show(SDL_Surface * to)
 		to=ekran;
 		to=ekran;
 	if (abs)
 	if (abs)
 	{
 	{
-		blitAt(imgs[curimg][state+bitmapOffset],pos.x,pos.y,to);
+		blitAt(imgs[curimg]
+			[( (state+bitmapOffset) < (imgs[curimg].size()) )	?	
+				(state+bitmapOffset)	:
+				(imgs[curimg].size()-1)			]
+													,pos.x,pos.y,to);
 		//updateRect(&pos,to);
 		//updateRect(&pos,to);
 	}
 	}
 	else
 	else
 	{
 	{
-		blitAt(imgs[curimg][state+bitmapOffset],pos.x+ourObj->pos.x,pos.y+ourObj->pos.y,to);
+		blitAt(imgs[curimg]
+			[( (state+bitmapOffset) < (imgs[curimg].size()) )	?	
+				(state+bitmapOffset)	:
+				(imgs[curimg].size()-1)			],pos.x+ourObj->pos.x,pos.y+ourObj->pos.y,to);
 		//updateRect(&genRect(pos.h,pos.w,pos.x+ourObj->pos.x,pos.y+ourObj->pos.y),to);
 		//updateRect(&genRect(pos.h,pos.w,pos.x+ourObj->pos.x,pos.y+ourObj->pos.y),to);
 		
 		
 	}
 	}
@@ -1588,7 +1595,7 @@ void CPlayerInterface::handleMouseMotion(SDL_Event *sEvent)
 	}
 	}
 	for(int i=0; i<motioninterested.size();i++)
 	for(int i=0; i<motioninterested.size();i++)
 	{
 	{
-		if (isItIn(&motioninterested[i]->pos,sEvent->motion.x,sEvent->motion.y))
+		if (motioninterested[i]->strongInterest || isItIn(&motioninterested[i]->pos,sEvent->motion.x,sEvent->motion.y))
 		{
 		{
 			motioninterested[i]->mouseMoved(sEvent->motion);
 			motioninterested[i]->mouseMoved(sEvent->motion);
 		}
 		}
@@ -2298,3 +2305,142 @@ void CHeroList::draw()
 	else
 	else
 		blitAt(arrdo->ourImages[2].bitmap,arrdop.x,arrdop.y);
 		blitAt(arrdo->ourImages[2].bitmap,arrdop.x,arrdop.y);
 }
 }
+void CRecrutationWindow::close()
+{
+	deactivate();
+	delete this;
+	LOCPLINT->curint->activate();
+	CCastleInterface *pom;
+	if(pom=dynamic_cast<CCastleInterface*>(LOCPLINT->curint))
+		pom->showAll();
+}
+void CRecrutationWindow::Max()
+{
+	slider->moveTo(slider->amount);
+}
+void CRecrutationWindow::Buy()
+{
+	close();
+}
+void CRecrutationWindow::Cancel()
+{
+	close();
+}
+void CRecrutationWindow::sliderMoved(int to)
+{
+}
+void CRecrutationWindow::clickLeft(tribool down)
+{
+}
+void CRecrutationWindow::activate()
+{
+	LOCPLINT->objsToBlit.push_back(this);
+	buy->activate();
+	max->activate();
+	cancel->activate();
+	slider->activate();
+}
+void CRecrutationWindow::deactivate()
+{
+	LOCPLINT->objsToBlit.erase(std::find(LOCPLINT->objsToBlit.begin(),LOCPLINT->objsToBlit.end(),this));
+	buy->deactivate();
+	max->deactivate();
+	cancel->deactivate();
+	slider->deactivate();
+}
+void CRecrutationWindow::show(SDL_Surface * to)
+{
+	static char c=0;
+	blitAt(bitmap,pos.x,pos.y,to?to:ekran);
+	buy->show();
+	max->show();
+	cancel->show();
+	slider->show();
+	char pom[15];
+	itoa(creatures[which].amount,pom,10); //available
+	printAtMiddle(pom,pos.x+205,pos.y+252,GEOR13,zwykly,ekran);
+	itoa(slider->value,pom,10); //recruit
+	printAtMiddle(pom,pos.x+279,pos.y+252,GEOR13,zwykly,ekran);
+
+	int curx = pos.x+115-creatures[which].res.size()*16;
+	for(int i=0;i<creatures[which].res.size();i++)
+	{
+		blitAt(CGI->townh->resources->ourImages[creatures[which].res[i].first].bitmap,curx,pos.y+243,ekran);
+		blitAt(CGI->townh->resources->ourImages[creatures[which].res[i].first].bitmap,curx+258,pos.y+243,ekran);
+		itoa(creatures[which].res[i].second,pom,10);
+		printAtMiddle(pom,curx+12,pos.y+286,GEOR13,zwykly,ekran);
+		itoa(creatures[which].res[i].second * slider->value,pom,10);
+		printAtMiddle(pom,curx+12+258,pos.y+286,GEOR13,zwykly,ekran);
+		curx+=32;
+	}
+
+	curx = pos.x + 192 + 102 - (102*creatures.size()/2) - (18*(creatures.size()-1)/2);
+	for(int i=0;i<creatures.size();i++)
+	{
+		blitAt(CGI->creh->backgrounds[CGI->creh->creatures[creatures[i].ID].faction],curx-50,pos.y+130-65);
+		creatures[i].anim->nextFrameMiddle(ekran,curx+20,pos.y+110,true,!(c%2),false);
+		curx += 120;
+	}
+	c++;
+}
+CRecrutationWindow::CRecrutationWindow(std::vector<std::pair<int,int> > &Creatures) //creatures - pairs<creature_ID,amount>
+{
+	creatures.resize(Creatures.size());
+	for(int i=0;i<creatures.size();i++)
+	{
+		creatures[i].amount = Creatures[i].second;
+		creatures[i].ID = Creatures[i].first;
+		for(int j=0;j<CGI->creh->creatures[Creatures[i].first].cost.size();j++)
+			if(CGI->creh->creatures[Creatures[i].first].cost[j])
+				creatures[i].res.push_back(std::make_pair(j,CGI->creh->creatures[Creatures[i].first].cost[j]));
+		creatures[i].anim = new CCreatureAnimation(CGI->creh->creatures[Creatures[i].first].animDefName);
+	}
+	SDL_Surface *hhlp = CGI->bitmaph->loadBitmap("TPRCRT.bmp");
+	blueToPlayersAdv(hhlp,LOCPLINT->playerID);
+	bitmap = SDL_ConvertSurface(hhlp,ekran->format,0); //na 8bitowej mapie by sie psulo
+	SDL_SetColorKey(bitmap,SDL_SRCCOLORKEY,SDL_MapRGB(bitmap->format,0,255,255));
+	SDL_FreeSurface(hhlp);
+	pos.x = ekran->w/2 - bitmap->w/2;
+	pos.y = ekran->h/2 - bitmap->h/2;
+	pos.w = bitmap->w;
+	pos.h = bitmap->h;
+	slider = new CSlider<CRecrutationWindow>(pos.x+176,pos.y+279,135,this,&CRecrutationWindow::sliderMoved,1,creatures[0].amount,0,true);
+	std::string pom;
+	printAtMiddle(CGI->generaltexth->allTexts[16] + " " + CGI->creh->creatures[creatures[0].ID].namePl,243,32,GEOR16,tytulowy,bitmap); //eg "Recruit Dragon flies"
+	printAtMiddle(CGI->generaltexth->allTexts[346],113,231,GEOR13,zwykly,bitmap); //cost per troop t
+	printAtMiddle(CGI->generaltexth->allTexts[465],205,231,GEOR13,zwykly,bitmap); //available t
+	printAtMiddle(CGI->generaltexth->allTexts[16],279,231,GEOR13,zwykly,bitmap); //recruit t
+	printAtMiddle(CGI->generaltexth->allTexts[466],373,231,GEOR13,zwykly,bitmap); //total cost t
+	drawBorder(bitmap,172,222,67,42,int3(239,215,123));
+	drawBorder(bitmap,246,222,67,42,int3(239,215,123));
+	drawBorder(bitmap,64,222,99,76,int3(239,215,123));
+	drawBorder(bitmap,322,222,99,76,int3(239,215,123));
+	drawBorder(bitmap,133,312,66,34,int3(173,142,66));
+	drawBorder(bitmap,211,312,66,34,int3(173,142,66));
+	drawBorder(bitmap,289,312,66,34,int3(173,142,66));
+
+	//border for creatures
+	int curx = 192 + 51 - (102*creatures.size()/2) - (18*(creatures.size()-1)/2);
+	for(int i=0;i<creatures.size();i++)
+	{
+		creatures[i].pos.x = curx+1;
+		creatures[i].pos.y = 65;
+		creatures[i].pos.w = 100;
+		creatures[i].pos.h = 130;
+		drawBorder(bitmap,curx,64,102,132,int3(255,0,0));
+		curx += 120;
+	}
+
+	max = new AdventureMapButton<CRecrutationWindow>("","",&CRecrutationWindow::Max,pos.x+134,pos.y+313,"IRCBTNS.DEF",this);
+	buy = new AdventureMapButton<CRecrutationWindow>("","",&CRecrutationWindow::Buy,pos.x+212,pos.y+313,"IBY6432.DEF",this);
+	cancel = new AdventureMapButton<CRecrutationWindow>("","",&CRecrutationWindow::Cancel,pos.x+290,pos.y+313,"ICN6432.DEF",this);
+	LOCPLINT->curint->deactivate();
+	which = 0;
+	//AdventureMapButton( std::string Name, std::string HelpBox, void(T::*Function)(), 
+	//int x, int y, std::string defName, T* Owner, bool activ=false,  std::vector<std::string> * add = NULL, bool playerColoredButton = true );//c-tor
+}//(int x, int y, int totalw, T*Owner,void(T::*Moved)(int to), int Capacity, int Amount, int Value, bool Horizontal)
+CRecrutationWindow::~CRecrutationWindow()
+{
+	SDL_FreeSurface(bitmap);
+	delete slider;
+}

+ 32 - 1
CPlayerInterface.h

@@ -4,7 +4,7 @@
 #include "SDL.h"
 #include "SDL.h"
 #include "SDL_framerate.h"
 #include "SDL_framerate.h"
 class CDefEssential;
 class CDefEssential;
-
+template <typename T> class AdventureMapButton;
 class CDefHandler;
 class CDefHandler;
 struct HeroMoveDetails;
 struct HeroMoveDetails;
 class CDefEssential;
 class CDefEssential;
@@ -12,6 +12,7 @@ class CGHeroInstance;
 class CAdvMapInt;
 class CAdvMapInt;
 class CCastleInterface;
 class CCastleInterface;
 class CStack;
 class CStack;
+template<typename T>class CSlider;
 class IShowable
 class IShowable
 {
 {
 public:
 public:
@@ -110,6 +111,8 @@ public:
 class MotionInterested: public virtual CIntObject
 class MotionInterested: public virtual CIntObject
 {
 {
 public:
 public:
+	bool strongInterest; //if true - report all mouse movements, if not - only when hovered
+	MotionInterested(){strongInterest=false;};
 	virtual ~MotionInterested(){};
 	virtual ~MotionInterested(){};
 	virtual void mouseMoved (SDL_MouseMotionEvent & sEvent)=0;
 	virtual void mouseMoved (SDL_MouseMotionEvent & sEvent)=0;
 	virtual void activate()=0;
 	virtual void activate()=0;
@@ -424,4 +427,32 @@ public:
 	void hover (bool on);
 	void hover (bool on);
 	void keyPressed (SDL_KeyboardEvent & key);
 	void keyPressed (SDL_KeyboardEvent & key);
 	void draw();
 	void draw();
+};
+class CRecrutationWindow : public IShowable, public ClickableL
+{
+public:
+	struct creinfo
+	{
+		SDL_Rect pos;
+		int ID, amount; //creature ID and available amount
+		CCreatureAnimation *anim;
+		std::vector<std::pair<int,int> > res; //res_id - cost_per_unit
+	};
+	std::vector<creinfo> creatures;
+	CSlider<CRecrutationWindow> *slider;
+	AdventureMapButton<CRecrutationWindow> *max, *buy, *cancel;
+	SDL_Surface *bitmap;
+	int which; //which creature is active
+
+	void close();
+	void Max();
+	void Buy();
+	void Cancel();
+	void sliderMoved(int to);
+	void clickLeft(tribool down);
+	void activate(); 
+	void deactivate();
+	void show(SDL_Surface * to = NULL);
+	CRecrutationWindow(std::vector<std::pair<int,int> > & Creatures); //creatures - pairs<creature_ID,amount>
+	~CRecrutationWindow();
 };
 };

+ 13 - 1
SDL_Extensions.cpp

@@ -806,7 +806,19 @@ void CSDL_Ext::blueToPlayersAdv(SDL_Surface * sur, int player, int mode, void* a
 		}
 		}
 	}
 	}
 }
 }
-
+void CSDL_Ext::drawBorder(SDL_Surface * sur, int x, int y, int w, int h, int3 color)
+{
+	for(int i=0;i<w;i++)
+	{
+		SDL_PutPixel(sur,x+i,y,color.x,color.y,color.z);
+		SDL_PutPixel(sur,x+i,y+h-1,color.x,color.y,color.z);
+	}
+	for(int i=0; i<h;i++)
+	{
+		SDL_PutPixel(sur,x,y+i,color.x,color.y,color.z);
+		SDL_PutPixel(sur,x+w-1,y+i,color.x,color.y,color.z);
+	}
+}
 void CSDL_Ext::setPlayerColor(SDL_Surface * sur, unsigned char player)
 void CSDL_Ext::setPlayerColor(SDL_Surface * sur, unsigned char player)
 {
 {
 	if(player==254)
 	if(player==254)

+ 1 - 0
SDL_Extensions.h

@@ -47,6 +47,7 @@ namespace CSDL_Ext
 	void blueToPlayersAdv(SDL_Surface * sur, int player, int mode=0, void* additionalInfo=NULL); //substitute blue color by another one, makes it nicer keeping nuances
 	void blueToPlayersAdv(SDL_Surface * sur, int player, int mode=0, void* additionalInfo=NULL); //substitute blue color by another one, makes it nicer keeping nuances
 																							//mode 1 is calibrated for hero infobox
 																							//mode 1 is calibrated for hero infobox
 																							//mode 2 is calibrated for resbar and gets in additionalInfo a pointer to the set of (SDL_Color) which shouldn't be replaced
 																							//mode 2 is calibrated for resbar and gets in additionalInfo a pointer to the set of (SDL_Color) which shouldn't be replaced
+	void drawBorder(SDL_Surface * sur, int x, int y, int w, int h, int3 color);
 	void setPlayerColor(SDL_Surface * sur, unsigned char player); //sets correct color of flags; -1 for neutral
 	void setPlayerColor(SDL_Surface * sur, unsigned char player); //sets correct color of flags; -1 for neutral
 	std::string processStr(std::string str, std::vector<std::string> & tor); //replaces %s in string
 	std::string processStr(std::string str, std::vector<std::string> & tor); //replaces %s in string
 	SDL_Surface * newSurface(int w, int h, SDL_Surface * mod=ekran); //creates new surface, with flags/format same as in surface given
 	SDL_Surface * newSurface(int w, int h, SDL_Surface * mod=ekran); //creates new surface, with flags/format same as in surface given

+ 10 - 0
config/cr_bgs.txt

@@ -0,0 +1,10 @@
+0	CRBKGCAS.bmp
+5	CRBKGDUN.bmp
+8	CRBKGELE.bmp
+1	CRBKGRAM.bmp
+2	CRBKGTOW.bmp
+3	CRBKGINF.bmp
+4	CRBKGNEC.bmp
+6	CRBKGSTR.bmp
+7	CRBKGFOR.bmp
+-1	CRBKGNEU.bmp

+ 196 - 0
config/cr_factions.txt

@@ -0,0 +1,196 @@
+0	0
+1	0
+2	0
+3	0
+4	0
+5	0
+6	0
+7	0
+8	0
+9	0
+10	0
+11	0
+12	0
+13	0
+14	1
+15	1
+16	1
+17	1
+18	1
+19	1
+20	1
+21	1
+22	1
+23	1
+24	1
+25	1
+26	1
+27	1
+28	2
+29	2
+30	2
+31	2
+32	2
+33	2
+34	2
+35	2
+36	2
+37	2
+38	2
+39	2
+40	2
+41	2
+42	3
+43	3
+44	3
+45	3
+46	3
+47	3
+48	3
+49	3
+50	3
+51	3
+52	3
+53	3
+54	3
+55	3
+56	4
+57	4
+58	4
+59	4
+60	4
+61	4
+62	4
+63	4
+64	4
+65	4
+66	4
+67	4
+68	4
+69	4
+70	5
+71	5
+72	5
+73	5
+74	5
+75	5
+76	5
+77	5
+78	5
+79	5
+80	5
+81	5
+82	5
+83	5
+84	6
+85	6
+86	6
+87	6
+88	6
+89	6
+90	6
+91	6
+92	6
+93	6
+94	6
+95	6
+96	6
+97	6
+98	7
+99	7
+100	7
+101	7
+102	7
+103	7
+104	7
+105	7
+106	7
+107	7
+108	7
+109	7
+110	7
+111	7
+112	8
+113	8
+114	8
+115	8
+116	-1
+117	-1
+118	8
+119	8
+120	8
+121	8
+122	-1
+123	8
+124	-1
+125	8
+126	-1
+127	8
+128	-1
+129	8
+130	8
+131	8
+132	-1
+133	-1
+134	-1
+135	-1
+136	-1
+137	-1
+138	-1
+139	-1
+140	-1
+141	-1
+142	-1
+143	-1
+144	-1
+145	-1
+146	-1
+147	-1
+148	-1
+149	-1
+150	0
+151	1
+152	2
+153	3
+154	4
+155	5
+156	6
+157	7
+158	8
+159	-1
+160	-1
+161	-1
+162	-1
+163	-1
+164	-1
+165	-1
+166	-1
+167	-1
+168	-1
+169	-1
+170	-1
+171	-1
+172	-1
+173	-1
+174	-1
+175	-1
+176	-1
+177	-1
+178	-1
+179	-1
+180	-1
+181	-1
+182	-1
+183	-1
+184	-1
+185	-1
+186	-1
+187	-1
+188	-1
+189	-1
+190	-1
+191	-1
+192	-1
+193	-1
+194	-1
+195	-1

+ 63 - 0
config/creatures_upgr.txt

@@ -0,0 +1,63 @@
+0	0	1
+0	1	3
+0	2	5
+0	3	7
+0	4	9
+0	5	11
+0	6	13
+1	0	15
+1	1	17
+1	2	19
+1	3	21
+1	4	23
+1	5	25
+1	6	27
+2	0	29
+2	1	31
+2	2	33
+2	3	35
+2	4	37
+2	5	39
+2	6	41
+3	0	43
+3	1	45
+3	2	47
+3	3	49
+3	4	51
+3	5	53
+3	6	55
+4	0	57
+4	1	59
+4	2	61
+4	3	63
+4	4	65
+4	5	67
+4	6	69
+5	0	71
+5	1	73
+5	2	75
+5	3	77
+5	4	79
+5	5	81
+5	6	83
+6	0	85
+6	1	87
+6	2	89
+6	3	91
+6	4	93
+6	5	95
+6	6	97
+7	0	99
+7	1	101
+7	2	103
+7	3	105
+7	4	107
+7	5	109
+7	6	111
+8	0	119
+8	1	127
+8	2	123
+8	3	129
+8	4	125
+8	5	121
+8	6	131

+ 37 - 8
hch/CCreatureHandler.cpp

@@ -50,6 +50,7 @@ void CCreatureHandler::loadCreatures()
 	while(i<buf.size())
 	while(i<buf.size())
 	{
 	{
 		CCreature ncre;
 		CCreature ncre;
+		ncre.cost.resize(RESOURCE_QUANTITY);
 		ncre.level=0;
 		ncre.level=0;
 		int befi=i;
 		int befi=i;
 		for(i; i<andame; ++i)
 		for(i; i<andame; ++i)
@@ -75,7 +76,7 @@ void CCreatureHandler::loadCreatures()
 			if(buf[i]=='\t')
 			if(buf[i]=='\t')
 				break;
 				break;
 		}
 		}
-		ncre.wood = atoi(buf.substr(befi, i-befi).c_str());
+		ncre.cost[0] = atoi(buf.substr(befi, i-befi).c_str());
 		++i;
 		++i;
 
 
 		befi=i;
 		befi=i;
@@ -84,7 +85,7 @@ void CCreatureHandler::loadCreatures()
 			if(buf[i]=='\t')
 			if(buf[i]=='\t')
 				break;
 				break;
 		}
 		}
-		ncre.mercury = atoi(buf.substr(befi, i-befi).c_str());
+		ncre.cost[1] = atoi(buf.substr(befi, i-befi).c_str());
 		++i;
 		++i;
 
 
 		befi=i;
 		befi=i;
@@ -93,7 +94,7 @@ void CCreatureHandler::loadCreatures()
 			if(buf[i]=='\t')
 			if(buf[i]=='\t')
 				break;
 				break;
 		}
 		}
-		ncre.ore = atoi(buf.substr(befi, i-befi).c_str());
+		ncre.cost[2] = atoi(buf.substr(befi, i-befi).c_str());
 		++i;
 		++i;
 
 
 		befi=i;
 		befi=i;
@@ -102,7 +103,7 @@ void CCreatureHandler::loadCreatures()
 			if(buf[i]=='\t')
 			if(buf[i]=='\t')
 				break;
 				break;
 		}
 		}
-		ncre.sulfur = atoi(buf.substr(befi, i-befi).c_str());
+		ncre.cost[3] = atoi(buf.substr(befi, i-befi).c_str());
 		++i;
 		++i;
 
 
 		befi=i;
 		befi=i;
@@ -111,7 +112,7 @@ void CCreatureHandler::loadCreatures()
 			if(buf[i]=='\t')
 			if(buf[i]=='\t')
 				break;
 				break;
 		}
 		}
-		ncre.crystal = atoi(buf.substr(befi, i-befi).c_str());
+		ncre.cost[4] = atoi(buf.substr(befi, i-befi).c_str());
 		++i;
 		++i;
 
 
 		befi=i;
 		befi=i;
@@ -120,7 +121,7 @@ void CCreatureHandler::loadCreatures()
 			if(buf[i]=='\t')
 			if(buf[i]=='\t')
 				break;
 				break;
 		}
 		}
-		ncre.gems = atoi(buf.substr(befi, i-befi).c_str());
+		ncre.cost[5] = atoi(buf.substr(befi, i-befi).c_str());
 		++i;
 		++i;
 
 
 		befi=i;
 		befi=i;
@@ -129,7 +130,7 @@ void CCreatureHandler::loadCreatures()
 			if(buf[i]=='\t')
 			if(buf[i]=='\t')
 				break;
 				break;
 		}
 		}
-		ncre.gold = atoi(buf.substr(befi, i-befi).c_str());
+		ncre.cost[6] = atoi(buf.substr(befi, i-befi).c_str());
 		++i;
 		++i;
 
 
 		befi=i;
 		befi=i;
@@ -322,6 +323,31 @@ void CCreatureHandler::loadCreatures()
 			}
 			}
 		}
 		}
 	}
 	}
+	ifs.close();
+	ifs.clear();
+
+
+	ifs.open("config/cr_bgs.txt"); 
+	while(!ifs.eof())
+	{
+		int id;
+		std::string name;
+		ifs >> id >> name;
+		backgrounds[id]=CGI->bitmaph->loadBitmap(name);
+	}
+	ifs.close();
+	ifs.clear();
+
+
+	ifs.open("config/cr_factions.txt"); 
+	while(!ifs.eof())
+	{
+		int id, fact;
+		ifs >> id >> fact;
+		creatures[id].faction = fact;
+	}
+	ifs.close();
+	ifs.clear();
 
 
 	//loading 32x32px imgs
 	//loading 32x32px imgs
 	CDefHandler *smi = CGI->spriteh->giveDef("CPRSMALL.DEF");
 	CDefHandler *smi = CGI->spriteh->giveDef("CPRSMALL.DEF");
@@ -742,7 +768,10 @@ int CCreatureAnimation::readNormalNr (int pos, int bytCon, unsigned char * str,
 	}
 	}
 	return ret;
 	return ret;
 }
 }
-
+int CCreatureAnimation::nextFrameMiddle(SDL_Surface *dest, int x, int y, bool attacker, bool incrementFrame, bool yellowBorder)
+{
+	return nextFrame(dest,x-fullWidth/2,y-fullHeight/2,attacker,incrementFrame,yellowBorder);
+}
 int CCreatureAnimation::nextFrame(SDL_Surface *dest, int x, int y, bool attacker, bool incrementFrame, bool yellowBorder)
 int CCreatureAnimation::nextFrame(SDL_Surface *dest, int x, int y, bool attacker, bool incrementFrame, bool yellowBorder)
 {
 {
 	if(dest->format->BytesPerPixel<3)
 	if(dest->format->BytesPerPixel<3)

+ 5 - 1
hch/CCreatureHandler.h

@@ -14,13 +14,15 @@ class CCreature
 {
 {
 public:
 public:
 	std::string namePl, nameSing, nameRef; //name in singular and plural form; and reference name
 	std::string namePl, nameSing, nameRef; //name in singular and plural form; and reference name
-	int wood, mercury, ore, sulfur, crystal, gems, gold, fightValue, AIValue, growth, hordeGrowth, hitPoints, speed, attack, defence, shots, spells;
+	std::vector<int> cost; //cost[res_id] - amount of that resource
+	int fightValue, AIValue, growth, hordeGrowth, hitPoints, speed, attack, defence, shots, spells;
 	int low1, low2, high1, high2; //TODO - co to w ogóle jest???
 	int low1, low2, high1, high2; //TODO - co to w ogóle jest???
 	int level; // 0 - unknown
 	int level; // 0 - unknown
 	std::string abilityText; //description of abilities
 	std::string abilityText; //description of abilities
 	std::string abilityRefs; //references to abilities, in textformat
 	std::string abilityRefs; //references to abilities, in textformat
 	std::string animDefName;
 	std::string animDefName;
 	int idNumber;
 	int idNumber;
+	int faction; //-1 = neutral
 
 
 	///animation info
 	///animation info
 	float timeBetweenFidgets, walkAnimationTime, attackAnimationTime, flightAnimationDistance;
 	float timeBetweenFidgets, walkAnimationTime, attackAnimationTime, flightAnimationDistance;
@@ -54,6 +56,7 @@ class CCreatureHandler
 public:
 public:
 	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::vector<CCreature> creatures;
 	std::vector<CCreature> creatures;
 	std::map<int,std::vector<CCreature*> > levelCreatures; //level -> list of creatures
 	std::map<int,std::vector<CCreature*> > levelCreatures; //level -> list of creatures
 	std::map<std::string,int> nameToID;
 	std::map<std::string,int> nameToID;
@@ -98,6 +101,7 @@ public:
 	int getType() const; //returns type of animation
 	int getType() const; //returns type of animation
 
 
 	int nextFrame(SDL_Surface * dest, int x, int y, bool attacker, bool incrementFrame = true, bool yellowBorder = false); //0 - success, any other - error //print next 
 	int nextFrame(SDL_Surface * dest, int x, int y, bool attacker, bool incrementFrame = true, bool yellowBorder = false); //0 - success, any other - error //print next 
+	int nextFrameMiddle(SDL_Surface * dest, int x, int y, bool attacker, bool incrementFrame = true, bool yellowBorder = false); //0 - success, any other - error //print next 
 };
 };
 
 
 #endif //CCREATUREHANDLER_H
 #endif //CCREATUREHANDLER_H

+ 9 - 0
hch/CObjectHandler.cpp

@@ -266,6 +266,15 @@ int CGTownInstance::hallLevel() const // -1 - none, 0 - village, 1 - town, 2 - c
 		return 0;
 		return 0;
 	return -1;
 	return -1;
 }
 }
+bool CGTownInstance::creatureDwelling(int level, bool upgraded)
+{
+	return builtBuildings.find(30+level+upgraded*7)!=builtBuildings.end();
+}
+int CGTownInstance::getHordeLevel(int HID) //HID - 0 or 1; returns creature level or -1 if that horde structure is not present
+{
+	//TODO: write
+	return -1;
+}
 int CGTownInstance::dailyIncome() const
 int CGTownInstance::dailyIncome() const
 {
 {
 	int ret = 0;
 	int ret = 0;

+ 8 - 0
hch/CObjectHandler.h

@@ -388,6 +388,12 @@ public:
 	int identifier; 
 	int identifier; 
 
 
 	int income;
 	int income;
+
+	struct StrInfo
+	{
+	public:
+		std::map<int,int> creatures; //level - available amount
+	} strInfo;
 	
 	
 	//TODO:
 	//TODO:
 	std::set<int> forbiddenBuildings, builtBuildings, h3mbuildings;
 	std::set<int> forbiddenBuildings, builtBuildings, h3mbuildings;
@@ -402,6 +408,8 @@ public:
 
 
 	int fortLevel() const; //0 - none, 1 - fort, 2 - citadel, 3 - castle
 	int fortLevel() const; //0 - none, 1 - fort, 2 - citadel, 3 - castle
 	int hallLevel() const; // -1 - none, 0 - village, 1 - town, 2 - city, 3 - capitol
 	int hallLevel() const; // -1 - none, 0 - village, 1 - town, 2 - city, 3 - capitol
+	bool creatureDwelling(int level, bool upgraded=false);
+	int getHordeLevel(int HID); //HID - 0 or 1; returns creature level or -1 if that horde structure is not present
 
 
 	bool hasFort() const;
 	bool hasFort() const;
 	bool hasCapitol() const;
 	bool hasCapitol() const;

+ 14 - 0
hch/CTownHandler.cpp

@@ -226,6 +226,20 @@ void CTownHandler::loadNames()
 		of.close();
 		of.close();
 		of.clear();
 		of.clear();
 
 
+		for(int x=0;x<towns.size();x++)
+			towns[x].upgradedCreatures.resize(7);
+
+		of.open("config/creatures_upgr.txt");
+		while(!of.eof())
+		{
+			int tid, lid, cid; //town,level,creature
+			of >> tid >> lid >> cid;
+			if(lid < towns[tid].upgradedCreatures.size())
+				towns[tid].upgradedCreatures[lid]=cid;
+		}
+		of.close();
+		of.clear();
+
 		
 		
 		of.open("config/requirements.txt");
 		of.open("config/requirements.txt");
 		while(!of.eof())
 		while(!of.eof())

+ 1 - 0
hch/CTownHandler.h

@@ -18,6 +18,7 @@ public:
 	std::string name; //name of type
 	std::string name; //name of type
 	std::vector<std::string> names; //names of the town instances
 	std::vector<std::string> names; //names of the town instances
 	std::vector<int> basicCreatures; //level (from 0) -> ID
 	std::vector<int> basicCreatures; //level (from 0) -> ID
+	std::vector<int> upgradedCreatures; //level (from 0) -> ID
 	int bonus; //pic number
 	int bonus; //pic number
 	int typeID;
 	int typeID;
 };
 };