2
0
Эх сурвалжийг харах

- Implemented Portal of Summoning (Dungeon)

Ivan Savenko 15 жил өмнө
parent
commit
bb7615309f

+ 2 - 2
CCallback.cpp

@@ -64,12 +64,12 @@ void CCallback::selectionMade(int selection, int asker)
 	QueryReply pack(asker,selection);
 	*cl->serv << &pack;
 }
-void CCallback::recruitCreatures(const CGObjectInstance *obj, ui32 ID, ui32 amount)
+void CCallback::recruitCreatures(const CGObjectInstance *obj, ui32 ID, ui32 amount, si32 level/*=-1*/)
 {
 	if(player!=obj->tempOwner  &&  obj->ID != 106)
 		return;
 
-	RecruitCreatures pack(obj->id,ID,amount);
+	RecruitCreatures pack(obj->id,ID,amount,level);
 	sendRequest(&pack);
 }
 

+ 2 - 2
CCallback.h

@@ -80,7 +80,7 @@ public:
 	//town
 	virtual void recruitHero(const CGObjectInstance *townOrTavern, const CGHeroInstance *hero)=0;
 	virtual bool buildBuilding(const CGTownInstance *town, si32 buildingID)=0;
-	virtual void recruitCreatures(const CGObjectInstance *obj, ui32 ID, ui32 amount)=0;
+	virtual void recruitCreatures(const CGObjectInstance *obj, ui32 ID, ui32 amount, si32 level=-1)=0;
 	virtual bool upgradeCreature(const CArmedInstance *obj, int stackPos, int newID=-1)=0; //if newID==-1 then best possible upgrade will be made
 	virtual void swapGarrisonHero(const CGTownInstance *town)=0;
 	
@@ -221,7 +221,7 @@ public:
 	bool swapArtifacts(const CGHeroInstance * hero1, ui16 pos1, const CGHeroInstance * hero2, ui16 pos2);
 	bool assembleArtifacts(const CGHeroInstance * hero, ui16 artifactSlot, bool assemble, ui32 assembleTo);
 	bool buildBuilding(const CGTownInstance *town, si32 buildingID);
-	void recruitCreatures(const CGObjectInstance *obj, ui32 ID, ui32 amount);
+	void recruitCreatures(const CGObjectInstance *obj, ui32 ID, ui32 amount, si32 level=-1);
 	bool dismissCreature(const CArmedInstance *obj, int stackPos);
 	bool upgradeCreature(const CArmedInstance *obj, int stackPos, int newID=-1);
 	void endTurn();

+ 58 - 45
client/CCastleInterface.cpp

@@ -754,7 +754,15 @@ void CCastleInterface::buildingClicked(int building)
 						break;
 						
 	/*Dungeon*/		case 5: //Portal of Summoning
-					tlog4<<"Portal of Summoning not handled\n";
+						if (town->creatures[CREATURES_PER_TOWN].second.empty())
+						{//extra dwelling has no creatures in it. no external dwellinngs
+							LOCPLINT->showInfoDialog(CGI->generaltexth->tcommands[30], std::vector<SComponent*>(), soundBase::sound_todo);
+						}
+						else 
+						{
+							GH.pushInt(new CRecruitmentWindow(town, CREATURES_PER_TOWN, town, 
+									boost::bind(&CCallback::recruitCreatures,LOCPLINT->cb,town,_1,_2,CREATURES_PER_TOWN), -87));
+						}
 					break;
 	/*Stronghold*/		case 6: //Ballista Yard
 					enterBlacksmith(4);
@@ -1147,22 +1155,24 @@ void CCastleInterface::recreateIcons()
 				crid = town->town->basicCreatures[i];
 		}
 		if (crid>=0)
-			creainfo.push_back(new CCreaInfo(crid,bid));
+			creainfo.push_back(new CCreaInfo(crid,(bid-30)%CREATURES_PER_TOWN));
 	}
+	if(town->subID == 5 && vstd::contains(town->builtBuildings, 22) && //we have Portal of Summoning
+			!town->creatures[CREATURES_PER_TOWN].second.empty()) // with some creatures in it
+		creainfo.push_back(new CCreaInfo(town->creatures[CREATURES_PER_TOWN].second[0], CREATURES_PER_TOWN));
 }
 
 CCastleInterface::CCreaInfo::~CCreaInfo()
 {
 }
-CCastleInterface::CCreaInfo::CCreaInfo(int CRID, int BID)
+CCastleInterface::CCreaInfo::CCreaInfo(int CRID, int LVL)
 {
 	used = LCLICK | RCLICK | HOVER;
 	CCastleInterface * ci=LOCPLINT->castleInt;
-	bid = BID;
+	level = LVL;
 	crid = CRID;
-	int i = (bid-30)%CREATURES_PER_TOWN;
-	pos.x = ci->pos.x+14+(55*(i%4));
-	pos.y = (i>3)?(507+ci->pos.y):(459+ci->pos.y);
+	pos.x = ci->pos.x+14+(55*(level%4));
+	pos.y = (level>3)?(507+ci->pos.y):(459+ci->pos.y);
 	pos.w = 48;
 	pos.h = 48;
 }
@@ -1178,13 +1188,14 @@ void CCastleInterface::CCreaInfo::hover(bool on)
 	else
 		GH.statusbar->clear();
 }
+
 void CCastleInterface::CCreaInfo::clickLeft(tribool down, bool previousState)
 {
 	if(previousState && (!down))
 	{
-		LOCPLINT->castleInt->showRecruitmentWindow(bid);
+		LOCPLINT->castleInt->showRecruitmentWindow(level+37);
 	}
-};
+}
 
 int CCastleInterface::CCreaInfo::AddToString(std::string from, std::string & to, int numb)
 {
@@ -1193,7 +1204,7 @@ int CCastleInterface::CCreaInfo::AddToString(std::string from, std::string & to,
 	boost::algorithm::replace_first(from,"%+d", "+"+boost::lexical_cast<std::string>(numb));
 	to+="\n"+from;
 	return numb;
-};
+}
 
 void CCastleInterface::CCreaInfo::clickRight(tribool down, bool previousState)
 {
@@ -1202,7 +1213,6 @@ void CCastleInterface::CCreaInfo::clickRight(tribool down, bool previousState)
 		CCastleInterface * ci=LOCPLINT->castleInt;
 		std::set<si32> bld =ci->town->builtBuildings;
 		int summ=0, cnt=0;
-		int level=(bid-30)%CREATURES_PER_TOWN;
 		std::string descr=CGI->generaltexth->allTexts[589];//Growth of creature is number
 		boost::algorithm::replace_first(descr,"%s",CGI->creh->creatures[crid]->nameSing);
 		boost::algorithm::replace_first(descr,"%d", boost::lexical_cast<std::string>(
@@ -1212,47 +1222,50 @@ void CCastleInterface::CCreaInfo::clickRight(tribool down, bool previousState)
 		summ = CGI->creh->creatures[crid]->growth;
 		boost::algorithm::replace_first(descr,"%d", boost::lexical_cast<std::string>(summ));
 		
+		if ( level>=0 && level<CREATURES_PER_TOWN)
+		{
 
-		if ( bld.find(9)!=bld.end())//castle +100% to basic
-			summ+=AddToString(CGI->buildh->buildings[ci->town->subID][9]->Name()+" %+d",descr,summ);
-		else if ( bld.find(8)!=bld.end())//else if citadel+50% to basic
-			summ+=AddToString(CGI->buildh->buildings[ci->town->subID][8]->Name()+" %+d",descr,summ/2);
+			if ( bld.find(9)!=bld.end())//castle +100% to basic
+				summ+=AddToString(CGI->buildh->buildings[ci->town->subID][9]->Name()+" %+d",descr,summ);
+			else if ( bld.find(8)!=bld.end())//else if citadel+50% to basic
+				summ+=AddToString(CGI->buildh->buildings[ci->town->subID][8]->Name()+" %+d",descr,summ/2);
 
-		if(ci->town->town->hordeLvl[0]==level)//horde, x to summ
-		if((bld.find(18)!=bld.end()) || (bld.find(19)!=bld.end()))
-			summ+=AddToString(CGI->buildh->buildings[ci->town->subID][18]->Name()+" %+d",descr,
-				CGI->creh->creatures[crid]->hordeGrowth);
+			if(ci->town->town->hordeLvl[0]==level)//horde, x to summ
+			if((bld.find(18)!=bld.end()) || (bld.find(19)!=bld.end()))
+				summ+=AddToString(CGI->buildh->buildings[ci->town->subID][18]->Name()+" %+d",descr,
+					CGI->creh->creatures[crid]->hordeGrowth);
 
-		if(ci->town->town->hordeLvl[1]==level)//horde, x to summ
-		if((bld.find(24)!=bld.end()) || (bld.find(25)!=bld.end()))
-			summ+=AddToString(CGI->buildh->buildings[ci->town->subID][24]->Name()+" %+d",descr,
-				CGI->creh->creatures[crid]->hordeGrowth);
+			if(ci->town->town->hordeLvl[1]==level)//horde, x to summ
+			if((bld.find(24)!=bld.end()) || (bld.find(25)!=bld.end()))
+				summ+=AddToString(CGI->buildh->buildings[ci->town->subID][24]->Name()+" %+d",descr,
+					CGI->creh->creatures[crid]->hordeGrowth);
 
-		cnt = 0;
+			cnt = 0;
 
-		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[ci->town->town->basicCreatures[level]]->idNumber == (*it)->creatures[0].second[0])
-					cnt++;//external dwellings count to summ
-		summ+=AddToString(CGI->generaltexth->allTexts[591],descr,cnt);
+			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[ci->town->town->basicCreatures[level]]->idNumber == (*it)->creatures[0].second[0])
+						cnt++;//external dwellings count to summ
+			summ+=AddToString(CGI->generaltexth->allTexts[591],descr,cnt);
 
-		const CGHeroInstance * ch = ci->town->garrisonHero;
-		for (cnt = 0; cnt<2; cnt++) // "loop" to avoid copy-pasting code
-		{
-			if(ch)
+			const CGHeroInstance * ch = ci->town->garrisonHero;
+			for (cnt = 0; cnt<2; cnt++) // "loop" to avoid copy-pasting code
 			{
-				for(std::list<Bonus>::const_iterator i=ch->bonuses.begin(); i != ch->bonuses.end(); i++)
-					if(i->type == Bonus::CREATURE_GROWTH && i->subtype == level)
-						if (i->source == Bonus::ARTIFACT)
-							summ+=AddToString(CGI->arth->artifacts[i->id]->Name()+" %+d",descr,i->val);
+				if(ch)
+				{
+					for(std::list<Bonus>::const_iterator i=ch->bonuses.begin(); i != ch->bonuses.end(); i++)
+						if(i->type == Bonus::CREATURE_GROWTH && i->subtype == level)
+							if (i->source == Bonus::ARTIFACT)
+								summ+=AddToString(CGI->arth->artifacts[i->id]->Name()+" %+d",descr,i->val);
+				};
+				ch = ci->town->visitingHero;
 			};
-			ch = ci->town->visitingHero;
-		};
 
-		//TODO player bonuses
+			//TODO player bonuses
 
-		if(bld.find(26)!=bld.end()) //grail - +50% to ALL growth
-			summ+=AddToString(CGI->buildh->buildings[ci->town->subID][26]->Name()+" %+d",descr,summ/2);
+			if(bld.find(26)!=bld.end()) //grail - +50% to ALL growth
+				summ+=AddToString(CGI->buildh->buildings[ci->town->subID][26]->Name()+" %+d",descr,summ/2);
+		}
 
 		CInfoPopup *mess = new CInfoPopup();//creating popup
 		mess->free = true;
@@ -1268,7 +1281,7 @@ void CCastleInterface::CCreaInfo::show(SDL_Surface * to)
 {
 	blitAt(graphics->smallImgs[crid],pos.x+8,pos.y,to);
 	std::ostringstream oss;
-	oss << '+' << LOCPLINT->castleInt->town->creatureGrowth((bid-30)%CREATURES_PER_TOWN);
+	oss << '+' << LOCPLINT->castleInt->town->creatureGrowth(level);
 	CSDL_Ext::printAtMiddle(oss.str(),pos.x+24,pos.y+40,FONT_SMALL,zwykly,to);
 }
 
@@ -1366,7 +1379,7 @@ CRecruitmentWindow * CCastleInterface::showRecruitmentWindow( int building )
 		building-=7;
 
 	int level = building-30;
-	assert(level >= 0 && level <= 6);
+	assert(level >= 0 && level < town->creatures.size());
 
 	//std::vector<std::pair<int,int > > crs;
 	//int amount = town->creatures[level].first;
@@ -1377,7 +1390,7 @@ CRecruitmentWindow * CCastleInterface::showRecruitmentWindow( int building )
 	//	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(town, level, town, boost::bind(&CCallback::recruitCreatures,LOCPLINT->cb,town,_1,_2), -87);
+	CRecruitmentWindow *rw = new CRecruitmentWindow(town, level, town, boost::bind(&CCallback::recruitCreatures,LOCPLINT->cb,town,_1,_2,level), -87);
 	GH.pushInt(rw);
 	return rw;
 }

+ 2 - 2
client/CCastleInterface.h

@@ -77,8 +77,8 @@ class CCastleInterface : public CWindowWithGarrison
 	class CCreaInfo : public CIntObject
 	{
 	public:
-		int crid,bid;
-		CCreaInfo(int CRID, int BID); //c-tor
+		int crid,level;
+		CCreaInfo(int CRID, int LVL); //c-tor
 		~CCreaInfo();//d-tor
 		int AddToString(std::string from, std::string & to, int numb);
 		void hover(bool on);

+ 1 - 1
client/CKingdomInterface.cpp

@@ -1085,7 +1085,7 @@ void CKingdomInterface::CTownItem::CCreaPlace::clickLeft(tribool down, bool prev
 	if (!down && previousState && town)
 	{
 		GH.pushInt (new CRecruitmentWindow(town, type, town, boost::bind
-			(&CCallback::recruitCreatures,LOCPLINT->cb,town,_1,_2)));
+			(&CCallback::recruitCreatures,LOCPLINT->cb,town,_1,_2, type)));
 	}
 }
 

+ 1 - 1
client/CPlayerInterface.cpp

@@ -1197,7 +1197,7 @@ void CPlayerInterface::showRecruitmentDialog(const CGDwelling *dwelling, const C
 {
 	waitWhileDialog();
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
-	CRecruitmentWindow *cr = new CRecruitmentWindow(dwelling, level, dst, boost::bind(&CCallback::recruitCreatures, cb, dwelling, _1, _2));
+	CRecruitmentWindow *cr = new CRecruitmentWindow(dwelling, level, dst, boost::bind(&CCallback::recruitCreatures, cb, dwelling, _1, _2, -1));
 	GH.pushInt(cr);
 }
 

+ 11 - 4
hch/CObjectHandler.cpp

@@ -1758,6 +1758,9 @@ int CGTownInstance::getHordeLevel(const int & HID)  const//HID - 0 or 1; returns
 }
 int CGTownInstance::creatureGrowth(const int & level) const
 {
+	if (level<0 || level >=CREATURES_PER_TOWN)
+		return 0;
+		
 	int ret = VLC->creh->creatures[town->basicCreatures[level]]->growth;
 	switch(fortLevel())
 	{
@@ -1922,7 +1925,10 @@ void CGTownInstance::initObj()
 	blockVisit = true;
 	hoverName = name + ", " + town->Name();
 
-	creatures.resize(CREATURES_PER_TOWN);
+	if (subID == 5)
+		creatures.resize(CREATURES_PER_TOWN+1);//extra dwelling for Dungeon
+	else
+		creatures.resize(CREATURES_PER_TOWN);
 	for (int i = 0; i < CREATURES_PER_TOWN; i++)
 	{
 		if(creatureDwelling(i,false))
@@ -1930,15 +1936,16 @@ void CGTownInstance::initObj()
 		if(creatureDwelling(i,true))
 			creatures[i].second.push_back(town->upgradedCreatures[i]);
 	}
+
 	switch (subID)
 	{ //add new visitable objects
 		case 0:
 			bonusingBuildings.push_back (new COPWBonus(21, this)); //Stables
 			break;
-		case 2: case 3: case 5: case 6:
+		case 5:
+			bonusingBuildings.push_back (new COPWBonus(21, this)); //Vortex
+		case 2: case 3: case 6:
 			bonusingBuildings.push_back (new CTownBonus(23, this));
-			if (subID == 5)
-				bonusingBuildings.push_back (new COPWBonus(21, this)); //Vortex
 			break;
 		case 7:
 			bonusingBuildings.push_back (new CTownBonus(17, this));

+ 3 - 3
lib/NetPacks.h

@@ -1316,14 +1316,14 @@ struct RazeStructure : public BuildStructure
 struct RecruitCreatures : public CPackForServer
 {
 	RecruitCreatures(){};
-	RecruitCreatures(si32 TID, si32 CRID, si32 Amount):tid(TID),crid(CRID),amount(Amount){};
+	RecruitCreatures(si32 TID, si32 CRID, si32 Amount, si32 Level):tid(TID),crid(CRID),amount(Amount),level(Level){};
 	si32 tid; //town id
 	ui32 crid, amount;//creature ID and amount
-
+	si32 level;//dwelling level to buy from, -1 if any
 	bool applyGh(CGameHandler *gh);
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
-		h & tid & crid & amount;
+		h & tid & crid & amount & level;
 	}
 };
 

+ 60 - 10
server/CGameHandler.cpp

@@ -928,6 +928,33 @@ static bool evntCmp(const CMapEvent *a, const CMapEvent *b)
 	return *a < *b;
 }
 
+void CGameHandler::setPortalDwelling(const CGTownInstance * town, bool forced=false)
+{// bool forced = true - if creature should be replaced, if false - only if no creature was set
+
+	if (forced || town->creatures[CREATURES_PER_TOWN].second.empty())//we need to change creature
+		{
+			SetAvailableCreatures ssi;
+			ssi.tid = town->id;
+			ssi.creatures = town->creatures;
+			ssi.creatures[CREATURES_PER_TOWN].second.clear();//remove old one
+			
+			std::vector<CGDwelling *> dwellings = gs->getPlayer(town->tempOwner)->dwellings;
+			if (dwellings.empty())//no dwellings - just remove
+			{
+				sendAndApply(&ssi);
+				return;
+			}
+			
+			ui32 dwellpos = rand()%dwellings.size();//take random dwelling
+			ui32 creapos = rand()%dwellings[dwellpos]->creatures.size();//for multi-creature dwellings like Golem Factory
+			ui32 creature = dwellings[dwellpos]->creatures[creapos].second[0];
+			
+			ssi.creatures[CREATURES_PER_TOWN].first = VLC->creh->creatures[creature]->growth;
+			ssi.creatures[CREATURES_PER_TOWN].second.push_back(creature);
+			sendAndApply(&ssi);
+		}
+}
+
 void CGameHandler::newTurn()
 {
 	tlog5 << "Turn " << gs->day+1 << std::endl;
@@ -1023,6 +1050,9 @@ void CGameHandler::newTurn()
 		ui8 player = (*j)->tempOwner;
 		if(gs->getDate(1)==7) //first day of week
 		{
+			if ((*j)->subID == 5 && vstd::contains((*j)->builtBuildings, 22))
+				setPortalDwelling(*j, true);//set creatures for Portal of Summoning
+			
 			if  ((**j).subID == 1 && gs->getDate(0) && player < PLAYER_LIMIT && vstd::contains((**j).builtBuildings, 22))//dwarven treasury
 					n.res[player][6] += hadGold[player]/10; //give 10% of starting gold
 		
@@ -1856,10 +1886,11 @@ bool CGameHandler::teleportHero(si32 hid, si32 dstid, ui8 source, ui8 asker/* =
 		&& complain("Cannot teleport hero to town without Castle gate in it"))
 			return false;
 	int3 pos = t->visitablePos();
-	pos.x++;//FIXME: get correct visitable position
+	pos.x++;//FIXME: get visitable position in more correct way (if any)
 	stopHeroVisitCastle(from->id, hid);
 	moveHero(hid,pos,1);
 	heroVisitCastle(dstid, hid);
+	return true;
 }
 
 void CGameHandler::setOwner(int objid, ui8 owner)
@@ -1869,14 +1900,28 @@ void CGameHandler::setOwner(int objid, ui8 owner)
 	sendAndApply(&sop);
 
 	winLoseHandle(1<<owner | 1<<oldOwner);
-	if(owner < PLAYER_LIMIT && getTown(objid) && !gs->getPlayer(owner)->towns.size()) //player lost last town
+	if(owner < PLAYER_LIMIT && getTown(objid)) //town captured
 	{
-		InfoWindow iw;
-		iw.player = oldOwner;
-		iw.text.addTxt(MetaString::GENERAL_TXT, 6); //%s, you have lost your last town.  If you do not conquer another town in the next week, you will be eliminated.
-		sendAndApply(&iw);
+		const CGTownInstance * town = getTown(objid);
+		if (town->subID == 5 && vstd::contains(town->builtBuildings, 22))
+			setPortalDwelling(town);
+		
+		if (!gs->getPlayer(owner)->towns.size())//player lost last town
+		{
+			InfoWindow iw;
+			iw.player = oldOwner;
+			iw.text.addTxt(MetaString::GENERAL_TXT, 6); //%s, you have lost your last town.  If you do not conquer another town in the next week, you will be eliminated.
+			sendAndApply(&iw);
+		}
 	}
+	
+	const CGObjectInstance * obj = getObj(objid);
+	if ((obj->id == 17 || obj->id == 20 ) && gs->getPlayer(owner)->dwellings.size()==1 )//first dwelling captured
+		BOOST_FOREACH(const CGTownInstance *t, gs->getPlayer(owner)->towns)
+			if (t->subID == 5 && vstd::contains(t->builtBuildings, 22))
+				setPortalDwelling(t);//set initial creatures for all portals of summoning
 }
+
 void CGameHandler::setHoverName(int objid, MetaString* name)
 {
 	SetHoverName shn(objid, *name);
@@ -2570,6 +2615,10 @@ bool CGameHandler::buildStructure( si32 tid, si32 bid )
 		gb.bonus.id = 17;
 		sendAndApply(&gb);
 	}
+	else if ( t->subID == 5 && bid == 22 )
+	{
+		setPortalDwelling(t);
+	}
 
 	ns.bid.insert(bid);
 	ns.builded = t->builded + 1;
@@ -2634,7 +2683,7 @@ void CGameHandler::sendMessageToAll( const std::string &message )
 	sendToAllClients(&sm);
 }
 
-bool CGameHandler::recruitCreatures( si32 objid, ui32 crid, ui32 cram )
+bool CGameHandler::recruitCreatures( si32 objid, ui32 crid, ui32 cram, si32 fromLvl )
 {
 	const CGDwelling *dw = static_cast<CGDwelling*>(gs->map->objects[objid]);
 	const CArmedInstance *dst = NULL;
@@ -2654,12 +2703,13 @@ bool CGameHandler::recruitCreatures( si32 objid, ui32 crid, ui32 cram )
 
 	//verify
 	bool found = false;
-	int level = -1;
-
+	int level = 0;
 
 	typedef std::pair<const int,int> Parka;
-	for(level = 0; level < dw->creatures.size(); level++) //iterate through all levels
+	for(; level < dw->creatures.size(); level++) //iterate through all levels
 	{
+		if ( (fromLvl != -1) && ( level !=fromLvl ) )
+			continue;
 		const std::pair<ui32, std::vector<ui32> > &cur = dw->creatures[level]; //current level info <amount, list of cr. ids>
 		int i = 0;
 		for(; i < cur.second.size(); i++) //look for crid among available creatures list on current level

+ 2 - 1
server/CGameHandler.h

@@ -155,6 +155,7 @@ public:
 	void changeObjPos(int objid, int3 newPos, ui8 flags);
 	void useScholarSkill(si32 hero1, si32 hero2);
 	void heroExchange(si32 hero1, si32 hero2);
+	void setPortalDwelling(const CGTownInstance * town, bool forced);
 	//////////////////////////////////////////////////////////////////////////
 
 	void init(StartInfo *si, int Seed);
@@ -179,7 +180,7 @@ public:
 	bool swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, ui16 destSlot);
 	bool garrisonSwap(si32 tid);
 	bool upgradeCreature( ui32 objid, ui8 pos, ui32 upgID );
-	bool recruitCreatures(si32 objid, ui32 crid, ui32 cram);
+	bool recruitCreatures(si32 objid, ui32 crid, ui32 cram, si32 level);
 	bool buildStructure(si32 tid, si32 bid);
 	bool razeStructure(si32 tid, si32 bid);
 	bool disbandCreature( si32 id, ui8 pos );

+ 1 - 1
server/NetPacksServer.cpp

@@ -86,7 +86,7 @@ bool BuildStructure::applyGh( CGameHandler *gh )
 
 bool RecruitCreatures::applyGh( CGameHandler *gh )
 {
-	return gh->recruitCreatures(tid,crid,amount);
+	return gh->recruitCreatures(tid,crid,amount,level);
 }
 
 bool UpgradeCreature::applyGh( CGameHandler *gh )