Bläddra i källkod

Golems Factory and Elemental Conflux creature generators supported. Minor improvements. Updated changelog.

Michał W. Urbańczyk 16 år sedan
förälder
incheckning
e358845873

+ 2 - 2
CGameInterface.h

@@ -83,7 +83,7 @@ public:
 	virtual void init(ICallback * CB){};
 	virtual void receivedResource(int type, int val){};
 	virtual void showInfoDialog(const std::string &text, const std::vector<Component*> &components, int soundID){};
-	virtual void showRecruitmentDialog(const CGDwelling *dwelling, int level){}
+	virtual void showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level){}
 	virtual void showShipyardDialog(const IShipyard *obj){} //obj may be town or shipyard; state: 0 - can buid, 1 - lack of resources, 2 - dest tile is blocked, 3 - no water
 	//virtual void showSelDialog(const std::string &text, const std::vector<Component*> &components, ui32 askID){};
 	//virtual void showYesNoDialog(const std::string &text, const std::vector<Component*> &components, ui32 askID){};
@@ -93,7 +93,7 @@ public:
 	virtual void tileRevealed(const std::set<int3> &pos){};
 	virtual void newObject(const CGObjectInstance * obj){}; //eg. ship built in shipyard
 	virtual void yourTurn(){};
-	virtual void availableCreaturesChanged(const CGTownInstance *town){};
+	virtual void availableCreaturesChanged(const CGDwelling *town){};
 	virtual void heroBonusChanged(const CGHeroInstance *hero, const HeroBonus &bonus, bool gain){};//if gain hero received bonus, else he lost it
 	virtual void requestRealized(PackageApplied *pa){};
 	virtual void heroExchangeStarted(si32 hero1, si32 hero2){};

+ 30 - 5
ChangeLog

@@ -1,4 +1,4 @@
-0.72 -> 0.73
+0.72 -> 0.73 (scheguled on 1 Sep) as for r1044
 GENERAL:
 * infowindow popup will be completely on screen
 * fixed possible crash with in game console
@@ -16,6 +16,11 @@ GENERAL:
 * corrected some exp/level values
 * primary skills cannot be negative
 * support for 3 new artifacts: Ring of Vitality, Ring of Life, Vial of Lifeblood
+* fixed timed events reappearing
+* saving system options
+* saving hero direction
+* r-click popups on enemy heroes and towns
+* hero leveling formula matches the H3
 
 ADVENTURE INTERFACE:
 * Garrisoning, then removing hero from garrison move him at the end of the heroes list
@@ -29,7 +34,17 @@ BATTLES:
 * number of units in stack in battle should now fit the box
 * non-living and undead creatures have now always 0 morale
 * partial handling of advmap objects changing battle background (like clover field) (their existence should change the background but nothing else)
-* fixed displaying luck effect animation
+* displaying luck effect animation
+* support for battleground overlays:
+- cursed ground
+- magic plains
+- fiery fields
+- rock lands
+- magic clouds
+- lucid pools
+- holy ground
+- clover field
+- evil fog
 
 TOWNS:
 * fixes for horde buildings
@@ -39,6 +54,7 @@ TOWNS:
 
 HERO WINDOW:
 * garrisoned heroes won't be shown on the list
+* artifacts will be present on morale/luck bonuses list
 
 PREGAME:
 * saves are sorted primary by map format, secondary by name
@@ -46,9 +62,18 @@ PREGAME:
 
 OBJECTS:
 * Fixed primary/secondary skill levels given by a scholar.
-* fixed crash when there was flaggable building next to map edge
-* partial support for adventure map creature dwellings
-
+* fixed problems with 3-tiles monoliths
+* fixed crash with flaggable building next to map edge
+* fixed some descriptions for events
+* New objects supported:
+- Buoy
+- Creature Generators
+- Flotsam
+- Mermaid
+- Ocean bottle
+- Sea Chest 
+- Shipwreck Survivor
+- Sirens 
 
 0.71 -> 0.72 (Jun 1 2009)
 GENERAL:

+ 7 - 6
client/CCastleInterface.cpp

@@ -968,15 +968,16 @@ CRecruitmentWindow * CCastleInterface::showRecruitmentWindow( int building )
 	int level = building-30;
 	assert(level >= 0 && level <= 6);
 
-	std::vector<std::pair<int,int > > crs;
-	int amount = town->creatures[level].first;
+	//std::vector<std::pair<int,int > > crs;
+	//int amount = town->creatures[level].first;
 
-	const std::vector<ui32> &cres = town->creatures[level].second;
+	//const std::vector<ui32> &cres = town->creatures[level].second;
 
-	for(size_t i = 0; i < cres.size(); i++)
-		crs.push_back(std::make_pair((int)cres[i],amount));
+	//for(size_t i = 0; i < cres.size(); i++)
+	//	crs.push_back(std::make_pair((int)cres[i],amount));
+	//CRecruitmentWindow *rw = new CRecruitmentWindow(crs,boost::bind(&CCallback::recruitCreatures,LOCPLINT->cb,town,_1,_2));
 
-	CRecruitmentWindow *rw = new CRecruitmentWindow(crs,boost::bind(&CCallback::recruitCreatures,LOCPLINT->cb,town,_1,_2));
+	CRecruitmentWindow *rw = new CRecruitmentWindow(town, level, town, boost::bind(&CCallback::recruitCreatures,LOCPLINT->cb,town,_1,_2));
 	LOCPLINT->pushInt(rw);
 	return rw;
 }

+ 10 - 11
client/CPlayerInterface.cpp

@@ -1500,15 +1500,21 @@ void CPlayerInterface::updateWater()
 
 }
 
-void CPlayerInterface::availableCreaturesChanged( const CGTownInstance *town )
+void CPlayerInterface::availableCreaturesChanged( const CGDwelling *town )
 {
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
-	if(castleInt)
+	if(castleInt && town->ID == TOWNI_TYPE)
 	{
 		CFortScreen *fs = dynamic_cast<CFortScreen*>(listInt.front());
 		if(fs)
 			fs->draw(castleInt,false);
 	}
+	else if(listInt.size() && (town->ID == 17  ||  town->ID == 20)) //external dwelling
+	{
+		CRecruitmentWindow *crw = dynamic_cast<CRecruitmentWindow*>(listInt.front());
+		if(crw)
+			crw->initCres();
+	}
 }
 
 void CPlayerInterface::heroBonusChanged( const CGHeroInstance *hero, const HeroBonus &bonus, bool gain )
@@ -1723,18 +1729,11 @@ const CGHeroInstance * CPlayerInterface::getWHero( int pos )
 	return wanderingHeroes[pos];
 }
 
-void CPlayerInterface::showRecruitmentDialog(const CGDwelling *dwelling, int level)
+void CPlayerInterface::showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level)
 {
 	waitWhileDialog();
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
-	std::vector<std::pair<int,int> > cres;
-	for(int i = 0; i < dwelling->creatures.size(); i++)
-	{
-		if(i == level || level < 0)
-			for(size_t j = 0; j < dwelling->creatures[i].second.size(); j++)
-				cres.push_back( std::make_pair(dwelling->creatures[i].second[j],dwelling->creatures[i].first));
-	}
-	CRecruitmentWindow *cr = new CRecruitmentWindow(cres, boost::bind(&CCallback::recruitCreatures, cb, dwelling, _1, _2));
+	CRecruitmentWindow *cr = new CRecruitmentWindow(dwelling, level, dst, boost::bind(&CCallback::recruitCreatures, cb, dwelling, _1, _2));
 	pushInt(cr);
 }
 

+ 2 - 2
client/CPlayerInterface.h

@@ -162,7 +162,7 @@ public:
 	void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town);
 	void receivedResource(int type, int val);
 	void showInfoDialog(const std::string &text, const std::vector<Component*> &components, int soundID);
-	void showRecruitmentDialog(const CGDwelling *dwelling, int level);
+	void showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level);
 	void showShipyardDialog(const IShipyard *obj); //obj may be town or shipyard; 
 	void showBlockingDialog(const std::string &text, const std::vector<Component> &components, ui32 askID, int soundID, bool selection, bool cancel); //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID.
 	void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, boost::function<void()> &onEnd);
@@ -170,7 +170,7 @@ public:
 	void tileRevealed(const std::set<int3> &pos); //called when fog of war disappears from given tiles
 	void newObject(const CGObjectInstance * obj);
 	void yourTurn();
-	void availableCreaturesChanged(const CGTownInstance *town);
+	void availableCreaturesChanged(const CGDwelling *town);
 	void heroBonusChanged(const CGHeroInstance *hero, const HeroBonus &bonus, bool gain);//if gain hero received bonus, else he lost it
 	void requestRealized(PackageApplied *pa);
 	void heroExchangeStarted(si32 hero1, si32 hero2);

+ 63 - 33
client/GUIClasses.cpp

@@ -1588,7 +1588,7 @@ void CTownList::draw(SDL_Surface * to)
 }
 
 
-CCreaturePic::CCreaturePic(CCreature *cre, bool Big)
+CCreaturePic::CCreaturePic(const CCreature *cre, bool Big)
 :c(cre),big(Big)
 {
 	anim = new CCreatureAnimation(cre->animDefName);
@@ -1629,8 +1629,12 @@ void CRecruitmentWindow::Max()
 }
 void CRecruitmentWindow::Buy()
 {
-	recruit(creatures[which].ID,slider->value);
-	close();
+	recruit(creatures[which].ID, slider->value);
+	if(level >= 0)
+		close();
+	else
+		slider->moveTo(0);
+
 }
 void CRecruitmentWindow::Cancel()
 {
@@ -1654,25 +1658,25 @@ void CRecruitmentWindow::clickLeft(tribool down)
 				slider->moveTo(newAmount);
 			else
 				slider->moveTo(slider->value);
-			curx = 192 + 51 - (102*creatures.size()/2) - (18*(creatures.size()-1)/2);
+			curx = 192 + 51 - (102*creatures.size()/2) - (13*(creatures.size()-1)/2);
 			for(int j=0;j<creatures.size();j++)
 			{
 				if(which==j)
 					drawBorder(bitmap,curx,64,102,132,int3(255,0,0));
 				else
 					drawBorder(bitmap,curx,64,102,132,int3(239,215,123));
-				curx += 120;
+				curx += 115;
 			}
 			break;
 		}
-		curx += 120;
+		curx += 115;
 	}
 }
 void CRecruitmentWindow::clickRight( boost::logic::tribool down )
 {
 	if(down)
 	{
-		int curx = 192 + 51 - (102*creatures.size()/2) - (18*(creatures.size()-1)/2);
+		int curx = 192 + 51 - (102*creatures.size()/2) - (13*(creatures.size()-1)/2);
 		for(int i=0;i<creatures.size();i++)
 		{
 			if(isItIn(&genRect(132,102,pos.x+curx,pos.y+64),LOCPLINT->current->motion.x,LOCPLINT->current->motion.y))
@@ -1681,7 +1685,7 @@ void CRecruitmentWindow::clickRight( boost::logic::tribool down )
 				LOCPLINT->pushInt(popup);
 				break;
 			}
-			curx += 120;
+			curx += 115;
 		}
 	}
 }
@@ -1735,35 +1739,24 @@ void CRecruitmentWindow::show(SDL_Surface * to)
 		curx+=32;
 	}
 
-	curx = pos.x + 192 + 102 - (102*creatures.size()/2) - (18*(creatures.size()-1)/2);
+	curx = pos.x + 192 + 102 - (102*creatures.size()/2) - (13*(creatures.size()-1)/2);
 	for(int i=0; i<creatures.size(); ++i)
 	{
 		creatures[i].pic->blitPic(to, curx-50, pos.y+130-65, !(animCounter%4));
-		curx += 120;
+		curx += 115;
 	}
 
 	++animCounter;
 	bar->show(to);
 }
 
-CRecruitmentWindow::CRecruitmentWindow(const std::vector<std::pair<int,int> > &Creatures, const boost::function<void(int,int)> &Recruit) //creatures - pairs<creature_ID,amount>
-:recruit(Recruit), which(Creatures.size()-1)
+CRecruitmentWindow::CRecruitmentWindow(const CGDwelling *Dwelling, int Level, const CArmedInstance *Dst, const boost::function<void(int,int)> &Recruit)
+:recruit(Recruit), dwelling(Dwelling), dst(Dst), level(Level)
 {
-	creatures.resize(Creatures.size());
-	amounts.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].pic = new CCreaturePic(&CGI->creh->creatures[Creatures[i].first]);
-		amounts[i] = CGI->creh->creatures[Creatures[i].first].maxAmount(LOCPLINT->cb->getResourceAmount());
-	}
+	which = 0;
 	SDL_Surface *hhlp = BitmapHandler::loadBitmap("TPRCRT.bmp");
 	graphics->blueToPlayersAdv(hhlp,LOCPLINT->playerID);
-	bitmap = SDL_ConvertSurface(hhlp,screen->format,0); //na 8bitowej mapie by sie psulo //it wouldn't work on 8bpp map
+	bitmap = SDL_ConvertSurface(hhlp,screen->format,0);
 	SDL_SetColorKey(bitmap,SDL_SRCCOLORKEY,SDL_MapRGB(bitmap->format,0,255,255));
 	SDL_FreeSurface(hhlp);
 	pos.x = screen->w/2 - bitmap->w/2;
@@ -1774,8 +1767,10 @@ CRecruitmentWindow::CRecruitmentWindow(const std::vector<std::pair<int,int> > &C
 	max = new AdventureMapButton(CGI->generaltexth->zelp[553],boost::bind(&CRecruitmentWindow::Max,this),pos.x+134,pos.y+313,"IRCBTNS.DEF",SDLK_m);
 	buy = new AdventureMapButton(CGI->generaltexth->zelp[554],boost::bind(&CRecruitmentWindow::Buy,this),pos.x+212,pos.y+313,"IBY6432.DEF",SDLK_RETURN);
 	cancel = new AdventureMapButton(CGI->generaltexth->zelp[555],boost::bind(&CRecruitmentWindow::Cancel,this),pos.x+290,pos.y+313,"ICN6432.DEF",SDLK_ESCAPE);
-	slider = new CSlider(pos.x+176,pos.y+279,135,boost::bind(&CRecruitmentWindow::sliderMoved,this, _1),1,std::min(amounts[0],creatures[0].amount),0,true);
-	std::string pom;
+	slider = new CSlider(pos.x+176,pos.y+279,135,boost::bind(&CRecruitmentWindow::sliderMoved,this, _1),1,0,0,true);
+
+	initCres();
+
 	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
@@ -1789,7 +1784,7 @@ CRecruitmentWindow::CRecruitmentWindow(const std::vector<std::pair<int,int> > &C
 	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);
+	int curx = 192 + 51 - (102*creatures.size()/2) - (13*(creatures.size()-1)/2);
 	for(int i=0;i<creatures.size();i++)
 	{
 		creatures[i].pos.x = curx+1;
@@ -1800,7 +1795,7 @@ CRecruitmentWindow::CRecruitmentWindow(const std::vector<std::pair<int,int> > &C
 			drawBorder(bitmap,curx,64,102,132,int3(255,0,0));
 		else
 			drawBorder(bitmap,curx,64,102,132,int3(239,215,123));
-		curx += 120;
+		curx += 115;
 	}
 
 	if(!creatures[0].amount ||  !amounts[0])
@@ -1813,10 +1808,7 @@ CRecruitmentWindow::CRecruitmentWindow(const std::vector<std::pair<int,int> > &C
 
 CRecruitmentWindow::~CRecruitmentWindow()
 {
-	for(int i=0;i<creatures.size();i++)
-	{
-		delete creatures[i].pic;
-	}
+	cleanCres();
 	delete max;
 	delete buy;
 	delete cancel;
@@ -1825,6 +1817,44 @@ CRecruitmentWindow::~CRecruitmentWindow()
 	delete bar;
 }
 
+void CRecruitmentWindow::initCres()
+{
+	cleanCres();
+	for(int i=0; i<dwelling->creatures.size(); i++)
+	{
+		if(level >= 0 && i != level) 
+			continue;
+
+		for(int j = dwelling->creatures[i].second.size() - 1; j >= 0 ; j--)
+		{
+			creatures.resize(creatures.size()+1);
+			creinfo &cur = creatures.back();
+
+			cur.amount = dwelling->creatures[i].first;
+			cur.ID = dwelling->creatures[i].second[j];
+			const CCreature *cre = &CGI->creh->creatures[cur.ID];
+			cur.pic = new CCreaturePic(cre);
+
+			for(int k=0; k<cre->cost.size(); k++)
+				if(cre->cost[k])
+					cur.res.push_back(std::make_pair(k,cre->cost[k]));
+			amounts.push_back(cre->maxAmount(LOCPLINT->cb->getResourceAmount()));
+		}
+	}
+
+	slider->amount = std::min(amounts[which],creatures[which].amount);
+}
+
+void CRecruitmentWindow::cleanCres()
+{
+	for(int i=0;i<creatures.size();i++)
+	{
+		delete creatures[i].pic;
+	}
+	creatures.clear();
+	amounts.clear();
+}
+
 CSplitWindow::CSplitWindow(int cid, int max, CGarrisonInt *Owner, int Last, int val)
 {
 	last = Last;

+ 10 - 3
client/GUIClasses.h

@@ -45,6 +45,7 @@ class CCreatureAnimation;
 class CSelectableComponent;
 class CCreatureSet;
 class CGObjectInstance;
+class CGDwelling;
 class CSlider;
 struct UpgradeInfo;
 template <typename T> struct CondSh;
@@ -314,10 +315,10 @@ public:
 class CCreaturePic //draws picture with creature on background, use nextFrame=true to get animation
 {
 public:
-	CCreature *c; //which creature's picture
+	const CCreature *c; //which creature's picture
 	bool big; //big => 100x130; !big => 100x120
 	CCreatureAnimation *anim; //displayed animation
-	CCreaturePic(CCreature *cre, bool Big=true); //c-tor
+	CCreaturePic(const CCreature *cre, bool Big=true); //c-tor
 	~CCreaturePic(); //d-tor
 	int blitPic(SDL_Surface *to, int x, int y, bool nextFrame); //prints creature on screen
 	SDL_Surface * getPic(bool nextFrame); //returns frame of animation
@@ -342,6 +343,10 @@ public:
 	CStatusBar *bar;
 	int which; //which creature is active
 
+	const CGDwelling *dwelling;
+	int level;
+	const CArmedInstance *dst;
+
 	void close();
 	void Max();
 	void Buy();
@@ -352,7 +357,9 @@ public:
 	void activate();
 	void deactivate();
 	void show(SDL_Surface * to);
-	CRecruitmentWindow(const std::vector<std::pair<int,int> > & Creatures, const boost::function<void(int,int)> & Recruit); //creatures - pairs<creature_ID,amount> //c-tor
+	void cleanCres();
+	void initCres();
+	CRecruitmentWindow(const CGDwelling *Dwelling, int Level, const CArmedInstance *Dst, const boost::function<void(int,int)> & Recruit); //creatures - pairs<creature_ID,amount> //c-tor
 	~CRecruitmentWindow(); //d-tor
 };
 

+ 6 - 4
client/NetPacksClient.cpp

@@ -204,9 +204,9 @@ void NewStructures::applyCl( CClient *cl )
 
 void SetAvailableCreatures::applyCl( CClient *cl )
 {
-	CGTownInstance *t = GS(cl)->getTown(tid);
-	if(vstd::contains(cl->playerint,t->tempOwner))
-		cl->playerint[t->tempOwner]->availableCreaturesChanged(t);
+	const CGDwelling *dw = static_cast<const CGDwelling*>(cl->getObj(tid));
+	if(vstd::contains(cl->playerint,dw->tempOwner))
+		cl->playerint[dw->tempOwner]->availableCreaturesChanged(dw);
 }
 
 void SetHeroesInTown::applyCl( CClient *cl )
@@ -484,9 +484,11 @@ void OpenWindow::applyCl(CClient *cl)
 		}
 		break;
 	case RECRUITMENT_FIRST:
+	case RECRUITMENT_ALL:
 		{
 			const CGDwelling *dw = dynamic_cast<const CGDwelling*>(cl->getObj(id1));
-			INTERFACE_CALL_IF_PRESENT(dw->tempOwner,showRecruitmentDialog, dw, 0);
+			const CArmedInstance *dst = dynamic_cast<const CArmedInstance*>(cl->getObj(id2));
+			INTERFACE_CALL_IF_PRESENT(dw->tempOwner,showRecruitmentDialog, dw, dst, window == RECRUITMENT_FIRST ? 0 : -1);
 		}
 		break;
 	case SHIPYARD_WINDOW:

+ 15 - 7
hch/CObjectHandler.cpp

@@ -979,19 +979,25 @@ void CGDwelling::initObj()
 
 	case 20:
 		creatures.resize(4);
-		if(subID == 0) // Elemental Conflux 
+		if(subID == 1) //Golem Factory
 		{
 			creatures[0].second.push_back(32);  //Stone Golem
 			creatures[1].second.push_back(33);  //Iron Golem  
 			creatures[2].second.push_back(116); //Gold Golem
 			creatures[3].second.push_back(117); //Diamond Golem
+			//guards
+			army.slots[0].first = 116;
+			army.slots[0].second = VLC->creh->creatures[116].getRandomAmount(ran);
 		}
-		else if(subID == 1) //Golem Factory
+		else if(subID == 0) // Elemental Conflux 
 		{
 			creatures[0].second.push_back(112); //Air Elemental
 			creatures[1].second.push_back(113); //Earth Elemental
 			creatures[2].second.push_back(114); //Fire Elemental
 			creatures[3].second.push_back(115); //Water Elemental
+			//guards
+			army.slots[0].first = 113;
+			army.slots[0].second = VLC->creh->creatures[113].getRandomAmount(ran);
 		}
 		else
 		{
@@ -1014,9 +1020,9 @@ void CGDwelling::onHeroVisit( const CGHeroInstance * h ) const
 		bd.player = h->tempOwner;
 		bd.flags = BlockingDialog::ALLOW_CANCEL;
 		bd.text.addTxt(MetaString::GENERAL_TXT, 421); //Much to your dismay, the %s is guarded by %s %s. Do you wish to fight the guards?
-		bd.text.addReplacement(MetaString::CREGENS, subID);
+		bd.text.addReplacement(ID == 17 ? MetaString::CREGENS : MetaString::CREGENS4, subID);
 		bd.text.addReplacement(MetaString::ARRAY_TXT, 176 + CCreature::getQuantityID(army.slots.begin()->second.second)*3);
-		bd.text.addReplacement(MetaString::CRE_PL_NAMES, creatures[0].second[0]);
+		bd.text.addReplacement(MetaString::CRE_PL_NAMES, army.slots.begin()->second.first);
 		cb->showBlockingDialog(&bd, boost::bind(&CGDwelling::wantsFight, this, h, _1));
 		return;
 	}
@@ -1110,12 +1116,14 @@ void CGDwelling::heroAcceptsCreatures( const CGHeroInstance *h, ui32 answer ) co
 			cb->sendAndApply(&iw);
 		}
 	}
-	else if(ID == 17)
+	else
 	{
 		OpenWindow ow;
 		ow.id1 = id;
-		ow.id2 = id;
-		ow.window = OpenWindow::RECRUITMENT_FIRST;
+		ow.id2 = h->id;
+		ow.window = ID == 17 
+			? OpenWindow::RECRUITMENT_FIRST 
+			: OpenWindow::RECRUITMENT_ALL;
 		cb->sendAndApply(&ow);
 	}
 }

+ 3 - 0
lib/CGameState.cpp

@@ -141,6 +141,9 @@ void MetaString::getLocalString(const std::pair<ui8,ui32> &txt, std::string &dst
 		case CREGENS:
 			vec = &VLC->generaltexth->creGens;
 			break;
+		case CREGENS4:
+			vec = &VLC->generaltexth->creGens4;
+			break;
 		case ADVOB_TXT:
 			vec = &VLC->generaltexth->advobtxt;
 			break;

+ 1 - 1
lib/NetPacks.h

@@ -73,7 +73,7 @@ private:
 	enum EMessage {TEXACT_STRING, TLOCAL_STRING, TNUMBER, TREPLACE_ESTRING, TREPLACE_LSTRING, TREPLACE_NUMBER};
 public:
 	enum {GENERAL_TXT=1, XTRAINFO_TXT, OBJ_NAMES, RES_NAMES, ART_NAMES, ARRAY_TXT, CRE_PL_NAMES, CREGENS, MINE_NAMES, 
-		MINE_EVNTS, ADVOB_TXT, ART_EVNTS, SPELL_NAME, SEC_SKILL_NAME, CRE_SING_NAMES};
+		MINE_EVNTS, ADVOB_TXT, ART_EVNTS, SPELL_NAME, SEC_SKILL_NAME, CRE_SING_NAMES, CREGENS4};
 
 	std::vector<ui8> message; //vector of EMessage
 

+ 3 - 1
lib/NetPacksLib.cpp

@@ -350,7 +350,9 @@ DLL_EXPORT void NewStructures::applyGs( CGameState *gs )
 
 DLL_EXPORT void SetAvailableCreatures::applyGs( CGameState *gs )
 {
-	gs->getTown(tid)->creatures = creatures;
+	CGDwelling *dw = dynamic_cast<CGDwelling*>(gs->map->objects[tid]);
+	assert(dw);
+	dw->creatures = creatures;
 }
 
 DLL_EXPORT void SetHeroesInTown::applyGs( CGameState *gs )