浏览代码

- implemented scholar skill
- fixed some remaining building issues (#361)
- Portal of Summoning will now be present in fort window
- some fixes for Thieves Guild window (partial #386)

Ivan Savenko 15 年之前
父节点
当前提交
a00e5cc177
共有 7 个文件被更改,包括 147 次插入120 次删除
  1. 45 42
      client/CCastleInterface.cpp
  2. 4 3
      client/CCastleInterface.h
  3. 10 6
      client/GUIClasses.cpp
  4. 56 41
      config/buildings5.txt
  5. 23 11
      hch/CObjectHandler.cpp
  6. 4 16
      lib/map.cpp
  7. 5 1
      server/CGameHandler.cpp

+ 45 - 42
client/CCastleInterface.cpp

@@ -580,7 +580,7 @@ void CCastleInterface::buildingClicked(int building)
 
 	if(building >= 30)
 	{
-		showRecruitmentWindow(building);
+		showRecruitmentWindow((building-30)%CREATURES_PER_TOWN);
 	}
 	else
 	{
@@ -761,14 +761,10 @@ void CCastleInterface::buildingClicked(int building)
 						
 	/*Dungeon*/		case 5: //Portal of Summoning
 						if (town->creatures[CREATURES_PER_TOWN].second.empty())
-						{//extra dwelling has no creatures in it. no external dwellinngs
+						//extra dwelling has no creatures in it
 							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));
-						}
+							this->showRecruitmentWindow(CREATURES_PER_TOWN);
 					break;
 	/*Stronghold*/		case 6: //Ballista Yard
 					enterBlacksmith(4);
@@ -1198,9 +1194,7 @@ void CCastleInterface::CCreaInfo::hover(bool on)
 void CCastleInterface::CCreaInfo::clickLeft(tribool down, bool previousState)
 {
 	if(previousState && (!down))
-	{
-		LOCPLINT->castleInt->showRecruitmentWindow(level+37);
-	}
+		LOCPLINT->castleInt->showRecruitmentWindow(level);
 }
 
 int CCastleInterface::CCreaInfo::AddToString(std::string from, std::string & to, int numb)
@@ -1379,26 +1373,12 @@ void CCastleInterface::CTownInfo::show(SDL_Surface * to)
 		blitAt(pic->ourImages[bid-10].bitmap,pos.x,pos.y,to);
 }
 
-CRecruitmentWindow * CCastleInterface::showRecruitmentWindow( int building )
+void CCastleInterface::showRecruitmentWindow( int level )
 {
-	if(building>36) //upg dwelling
-		building-=7;
-
-	int level = building-30;
 	assert(level >= 0 && level < town->creatures.size());
 
-	//std::vector<std::pair<int,int > > crs;
-	//int amount = town->creatures[level].first;
-
-	//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));
-	//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,level), -87);
 	GH.pushInt(rw);
-	return rw;
 }
 
 void CCastleInterface::enterMageGuild()
@@ -1817,7 +1797,7 @@ void CFortScreen::show( SDL_Surface * to)
 {
 	blitAt(bg,pos,to);
 	static unsigned char anim = 1;
-	for (int i=0; i<CREATURES_PER_TOWN; i++)
+	for (int i=0; i<crePics.size(); i++)
 	{
 		crePics[i]->blitPic(to,pos.x+positions[i].x+159,pos.y+positions[i].y+4,!(anim%4));
 	}
@@ -1853,6 +1833,11 @@ void CFortScreen::close()
 
 CFortScreen::CFortScreen( CCastleInterface * owner )
 {
+	if (owner->town->creatures.size() > CREATURES_PER_TOWN 
+	        && owner->town->creatures[CREATURES_PER_TOWN].second.size() )//dungeon with active portal
+		fortSize = CREATURES_PER_TOWN+1;
+	else
+		fortSize = CREATURES_PER_TOWN;
 	resdatabar = new CMinorResDataBar;
 	pos = owner->pos;
 	bg = NULL;
@@ -1862,8 +1847,11 @@ CFortScreen::CFortScreen( CCastleInterface * owner )
 	exit = new AdventureMapButton(temp,"",boost::bind(&CFortScreen::close,this),pos.x+748,pos.y+556,"TPMAGE1.DEF",SDLK_RETURN);
 	positions += genRect(126,386,10,22),genRect(126,386,404,22),
 		genRect(126,386,10,155),genRect(126,386,404,155),
-		genRect(126,386,10,288),genRect(126,386,404,288),
-		genRect(126,386,206,421);
+		genRect(126,386,10,288),genRect(126,386,404,288);
+	if (fortSize == CREATURES_PER_TOWN)
+		positions += genRect(126,386,206,421);
+	else
+		positions += genRect(126,386,10,421),genRect(126,386,404,421);
 	draw(owner,true);
 	resdatabar->pos += pos;
 }
@@ -1874,22 +1862,40 @@ void CFortScreen::draw( CCastleInterface * owner, bool first)
 		SDL_FreeSurface(bg);
 	char buf[20];
 	memset(buf,0,20);
-	SDL_Surface *bg2 = BitmapHandler::loadBitmap("TPCASTL7.bmp"),
-		*icons =  BitmapHandler::loadBitmap("ZPCAINFO.bmp");
+	SDL_Surface *bg2;
+	if (fortSize == CREATURES_PER_TOWN)
+		bg2 = BitmapHandler::loadBitmap("TPCASTL7.bmp");
+	else
+		bg2 = BitmapHandler::loadBitmap("TPCASTL8.bmp");
+		
+	SDL_Surface *icons =  BitmapHandler::loadBitmap("ZPCAINFO.bmp");
 	SDL_SetColorKey(icons,SDL_SRCCOLORKEY,SDL_MapRGB(icons->format,0,255,255));
 	graphics->blueToPlayersAdv(bg2,LOCPLINT->playerID);
 	bg = SDL_ConvertSurface(bg2,screen->format,0); 
 	SDL_FreeSurface(bg2);
 	printAtMiddle(CGI->buildh->buildings[owner->town->subID][owner->town->fortLevel()+6]->Name(),400,13,FONT_MEDIUM,zwykly,bg);
-	for(int i=0;i<CREATURES_PER_TOWN; i++)
+	for(int i=0;i<fortSize; i++)
 	{
-		bool upgraded = owner->town->creatureDwelling(i,true);
-		bool present = owner->town->creatureDwelling(i,false);
-		CCreature *c = CGI->creh->creatures[upgraded ? owner->town->town->upgradedCreatures[i] : owner->town->town->basicCreatures[i]];
+		int dwelling;// ID of buiding with this creature
+		CCreature *c;
+		bool present = true;
+		if ( i < CREATURES_PER_TOWN )
+		{
+			bool upgraded = owner->town->creatureDwelling(i,true);
+			present = owner->town->creatureDwelling(i,false);
+			c = CGI->creh->creatures[upgraded ? owner->town->town->upgradedCreatures[i] : owner->town->town->basicCreatures[i]];
+			dwelling = 30+i+upgraded*7;
+		}
+		else
+		{
+			c = CGI->creh->creatures[owner->town->creatures[i].second[0]];
+			dwelling = 22;//Portal of summon
+		}
+
 		printAtMiddle(c->namePl,positions[i].x+79,positions[i].y+10,FONT_SMALL,zwykly,bg); //cr. name
-		blitAt(owner->bicons->ourImages[30+i+upgraded*7].bitmap,positions[i].x+4,positions[i].y+21,bg); //dwelling pic
-		printAtMiddle(CGI->buildh->buildings[owner->town->subID][30+i+upgraded*7]->Name(),positions[i].x+79,positions[i].y+100,FONT_SMALL,zwykly,bg); //dwelling name
-		if(present) //if creature is present print avail able quantity
+		blitAt(owner->bicons->ourImages[dwelling].bitmap,positions[i].x+4,positions[i].y+21,bg); //dwelling pic
+		printAtMiddle(CGI->buildh->buildings[owner->town->subID][dwelling]->Name(),positions[i].x+79,positions[i].y+100,FONT_SMALL,zwykly,bg); //dwelling name
+		if(present) //if creature is present print available quantity
 		{
 			SDL_itoa(owner->town->creatures[i].first,buf,10);
 			printAtMiddle(CGI->generaltexth->allTexts[217] + buf,positions[i].x+79,positions[i].y+118,FONT_SMALL,zwykly,bg);
@@ -1939,7 +1945,7 @@ void CFortScreen::draw( CCastleInterface * owner, bool first)
 			crePics.push_back(new CCreaturePic(c,false));
 			if(present)
 			{
-				recAreas.push_back(new RecArea(30+i+upgraded*7));
+				recAreas.push_back(new RecArea(i));
 				recAreas.back()->pos = positions[i] + pos;
 			}
 		}
@@ -1949,10 +1955,7 @@ void CFortScreen::draw( CCastleInterface * owner, bool first)
 void CFortScreen::RecArea::clickLeft(tribool down, bool previousState)
 {
 	if(!down && previousState)
-	{
-		LOCPLINT->castleInt->showRecruitmentWindow(bid);
-	}
-	//ClickableL::clickLeft(down);
+		LOCPLINT->castleInt->showRecruitmentWindow(level);
 }
 
 void CFortScreen::RecArea::clickRight(tribool down, bool previousState)

+ 4 - 3
client/CCastleInterface.h

@@ -138,7 +138,7 @@ public:
 	void enterTavern();
 	void enterMageGuild();
 	void splitClicked(); //for hero meeting (splitting stacks is handled by garrison int)
-	CRecruitmentWindow * showRecruitmentWindow(int building);
+	void showRecruitmentWindow( int level );
 	void enterHall();
 	void close();
 	void splitF();
@@ -209,13 +209,14 @@ class CFortScreen : public CIntObject
 	class RecArea : public CIntObject
 	{
 	public:
-		int bid;
-		RecArea(int BID):bid(BID){used = LCLICK | RCLICK;}; //c-tor
+		int level;
+		RecArea(int LEVEL):level(LEVEL){used = LCLICK | RCLICK;}; //c-tor
 		void clickLeft(tribool down, bool previousState);
 		void clickRight(tribool down, bool previousState);
 	};
 public:
 	CMinorResDataBar * resdatabar;
+	int fortSize;
 	AdventureMapButton *exit;
 	SDL_Surface * bg;
 	std::vector<Rect> positions;

+ 10 - 6
client/GUIClasses.cpp

@@ -3781,6 +3781,7 @@ void CAltarWindow::calcTotalExp()
 			val += valOfArt * arts->artifactsOnAltar.count(*i);
 		}
 	}
+	val *=(100+hero->getSecSkillLevel(21)*5)/100.0f;
 	expOnAltar->setTxt(boost::lexical_cast<std::string>(val));
 }
 
@@ -6235,15 +6236,16 @@ CThievesGuildWindow::CThievesGuildWindow(const CGObjectInstance * _owner)
 
 	//loading backround and converting to more bpp form
 	SDL_Surface * bg = background = BitmapHandler::loadBitmap("TpRank.bmp", false);
+	graphics->blueToPlayersAdv(bg,LOCPLINT->playerID);
 	background = newSurface(bg->w, bg->h);
 	blitAt(bg, 0, 0, background);
 	SDL_FreeSurface(bg);
 
-	exitb = new AdventureMapButton (std::string(), std::string(), boost::bind(&CThievesGuildWindow::bexitf,this), 748, 556, "HSBTNS.def", SDLK_RETURN);
+	exitb = new AdventureMapButton (std::string(), std::string(), boost::bind(&CThievesGuildWindow::bexitf,this), 748, 556, "TPMAGE1.def", SDLK_RETURN);
 	statusBar = new CGStatusBar(3, 555, "TStatBar.bmp", 742);
 
 	resdatabar = new CMinorResDataBar();
-	resdatabar->pos.x += pos.x - 3;
+	resdatabar->pos.x += pos.x;
 	resdatabar->pos.y += pos.y;
 
 	static std::vector< std::list< ui8 > > SThievesGuildInfo::* fields[] = { &SThievesGuildInfo::numOfTowns, &SThievesGuildInfo::numOfHeroes, &SThievesGuildInfo::gold,
@@ -6271,7 +6273,9 @@ CThievesGuildWindow::CThievesGuildWindow(const CGObjectInstance * _owner)
 		{
 			y = 52 + 32*g;
 		}
-		printAtMiddle(CGI->generaltexth->jktexts[24+g], 135, y, FONT_MEDIUM, tytulowy, background);
+		std::string text = CGI->generaltexth->jktexts[24+g];
+		boost::algorithm::trim_if(text,boost::algorithm::is_any_of("\""));
+		printAtMiddle(text, 135, y, FONT_MEDIUM, tytulowy, background);
 	}
 
 	CDefHandler * strips = CDefHandler::giveDef("PRSTRIPS.DEF");
@@ -6284,7 +6288,7 @@ CThievesGuildWindow::CThievesGuildWindow(const CGObjectInstance * _owner)
 		{
 			blitAt(strips->ourImages[g-1].bitmap, 250 + 66*g, 7, background);
 		}
-		printAtMiddle(CGI->generaltexth->jktexts[16+g], 283 + 66*g, 20, FONT_MEDIUM, tytulowy, background);
+		printAtMiddle(CGI->generaltexth->jktexts[16+g], 283 + 66*g, 24, FONT_BIG, tytulowy, background);
 		SDL_Surface * box = BitmapHandler::loadBitmap(colorToBox[tgi.playerColors[g]]);
 		blitAt(box, 253 + 66*g, 334, background);
 		SDL_FreeSurface(box);
@@ -6327,12 +6331,12 @@ CThievesGuildWindow::CThievesGuildWindow(const CGObjectInstance * _owner)
 		//printing stats
 		if(it->second.details)
 		{
+			printAtWB(CGI->generaltexth->allTexts[184], 191 + 66*counter, 396, FONT_TINY, 10, zwykly, background);
 			for (int i=0; i<it->second.details->primskills.size(); ++i)
 			{
-				printAt(CGI->generaltexth->allTexts[380+i], 191 + 66*counter, 394 + 11*i, FONT_SMALL, zwykly, background);
 				std::ostringstream skill;
 				skill << it->second.details->primskills[i];
-				printTo(skill.str(), 244 + 66 * counter, 410 + 11*i, FONT_SMALL, zwykly, background);
+				printTo(skill.str(), 244 + 66 * counter, 407 + 11*i, FONT_TINY, zwykly, background);
 			}
 		}
 

+ 56 - 41
config/buildings5.txt

@@ -1,41 +1,56 @@
-0	11
-1	12
-2	13
-3	7
-4	8
-5	9
-6	5
-7	16
-8	14
-9	15
-10	23
-11	0
-12	1
-13	2
-14	3
-15	4
-16	6
-17	26
-18	17
-19	22
-20	21
-21	23
-22	30
-23	37
-24	-1
-25	31
-26	38
-27	-2
-28	32
-29	39
-30	-3
-31	33
-32	40
-33	-4
-34	34
-35	41
-36	-5
-37	35
-38	42
-39	36
-40	43
+-1	0	11
+-1	1	12
+-1	2	13
+-1	3	7
+-1	4	8
+-1	5	9
+-1	6	5
+-1	7	16
+-1	8	14
+-1	9	15
+-1	10	17
+-1	11	0
+-1	12	1
+-1	13	2
+-1	14	3
+-1	15	4
+-1	16	6
+-1	17	26
+-1	18	17
+-1	19	22
+-1	20	22
+-1	21	23
+-1	22	30
+-1	23	37
+-1	24	-1
+-1	25	31
+-1	26	38
+-1	27	-2
+-1	28	32
+-1	29	39
+-1	30	-3
+-1	31	33
+-1	32	40
+-1	33	-4
+-1	34	34
+-1	35	41
+-1	36	-5
+-1	37	35
+-1	38	42
+-1	39	36
+-1	40	43
+0	20	21
+1	19	21
+2	18	22
+2	19	23
+2	20	21
+3	20	23
+3	18	21
+4	19	21
+5	20	23
+5	18	21
+6	19	21
+7	20	17
+7	18	22
+7	19	21
+8	18	21

+ 23 - 11
hch/CObjectHandler.cpp

@@ -1862,7 +1862,9 @@ int CGTownInstance::mageGuildLevel() const
 }
 bool CGTownInstance::creatureDwelling(const int & level, bool upgraded) const
 {
-	return builtBuildings.find(30+level+upgraded*7)!=builtBuildings.end();
+	if ( level<0 || level >= CREATURES_PER_TOWN )
+		return false;
+	return vstd::contains(builtBuildings, 30+level+upgraded*CREATURES_PER_TOWN);
 }
 int CGTownInstance::getHordeLevel(const int & HID)  const//HID - 0 or 1; returns creature level or -1 if that horde structure is not present
 {
@@ -2437,6 +2439,8 @@ void CGVisitableOPH::onNAHeroVisit(int heroID, bool alreadyVisited) const
 			}
 		case 100: //give exp
 			{
+				const CGHeroInstance *h = cb->getHero(heroID);
+				val = val*(100+h->getSecSkillLevel(21)*5)/100.0f;
 				InfoWindow iw;
 				iw.soundID = sound;
 				iw.components.push_back(Component(id,subid,val,0));
@@ -2731,9 +2735,9 @@ void CTownBonus::onHeroVisit (const CGHeroInstance * h) const
 						break;
 					case 5://academy of battle scholars
 						what = 4;
-						val = 1000;
+						val = 1000*(100+h->getSecSkillLevel(21)*5)/100.0f;
 						mid = 583;
-						iw.components.push_back (Component(Component::EXPERIENCE, 0, 1000, 0));
+						iw.components.push_back (Component(Component::EXPERIENCE, 0, val, 0));
 						break;
 				}
 				break;
@@ -3686,7 +3690,8 @@ void CGPickable::onHeroVisit( const CGHeroInstance * h ) const
 				sd.player = h->tempOwner;
 				sd.text << std::pair<ui8,ui32>(11,146);
 				sd.components.push_back(Component(2,6,val1,0));
-				sd.components.push_back(Component(5,0,val2,0));
+				int expVal = val2*(100+h->getSecSkillLevel(21)*5)/100.0f;
+				sd.components.push_back(Component(5,0,expVal, 0));
 				sd.soundID = soundBase::chest;
 				boost::function<void(ui32)> fun = boost::bind(&CGPickable::chosen,this,_1,h->id);
 				cb->showBlockingDialog(&sd,fun);
@@ -3699,13 +3704,14 @@ void CGPickable::onHeroVisit( const CGHeroInstance * h ) const
 
 void CGPickable::chosen( int which, int heroID ) const
 {
+	const CGHeroInstance *h = cb->getHero(heroID);
 	switch(which)
 	{
 	case 1: //player pick gold
 		cb->giveResource(cb->getOwner(heroID),6,val1);
 		break;
 	case 2: //player pick exp
-		cb->changePrimSkill(heroID, 4, val2);
+		cb->changePrimSkill(heroID, 4, val2*(100+h->getSecSkillLevel(21)*5)/100.0f);
 		break;
 	default:
 		throw std::string("Unhandled treasure choice");
@@ -4220,13 +4226,18 @@ void CGSeerHut::completeQuest (const CGHeroInstance * h) const //reward
 	switch (rewardType)
 	{
 		case 1: //experience
-			cb->changePrimSkill(h->id, 4, rVal, false);
-			iw.components.push_back (Component (Component::EXPERIENCE, 0, rVal, 0));
+		{
+			int expVal = rVal*(100+h->getSecSkillLevel(21)*5)/100.0f;
+			cb->changePrimSkill(h->id, 4, expVal, false);
+			iw.components.push_back (Component (Component::EXPERIENCE, 0, expVal, 0));
 			break;
+		}
 		case 2: //mana points
+		{
 			cb->setManaPoints(h->id, h->mana+rVal);
 			iw.components.push_back (Component (Component::PRIM_SKILL, 5, rVal, 0));
 			break;
+		}
 		case 3: case 4: //morale /luck
 		{
 			Bonus hb(Bonus::ONE_WEEK, (rewardType == 3 ? Bonus::MORALE : Bonus::LUCK),
@@ -4682,10 +4693,11 @@ void CGPandoraBox::giveContents( const CGHeroInstance *h, bool afterBattle ) con
 
 	if(gainedExp || changesPrimSkill || abilities.size())
 	{
+		int expVal = gainedExp*(100+h->getSecSkillLevel(21)*5)/100.0f;
 		getText(iw,afterBattle,175,h);
 
-		if(gainedExp)
-			iw.components.push_back(Component(Component::EXPERIENCE,0,gainedExp,0));
+		if(expVal)
+			iw.components.push_back(Component(Component::EXPERIENCE,0,expVal,0));
 		for(int i=0; i<primskills.size(); i++)
 			if(primskills[i])
 				iw.components.push_back(Component(Component::PRIM_SKILL,i,primskills[i],0));
@@ -4696,8 +4708,8 @@ void CGPandoraBox::giveContents( const CGHeroInstance *h, bool afterBattle ) con
 		cb->showInfoDialog(&iw);
 
 		//give exp
-		if(gainedExp)
-			cb->changePrimSkill(h->id,4,gainedExp,false);
+		if(expVal)
+			cb->changePrimSkill(h->id,4,expVal,false);
 		//give prim skills
 		for(int i=0; i<primskills.size(); i++)
 			if(primskills[i])

+ 4 - 16
lib/map.cpp

@@ -29,23 +29,11 @@ static std::set<si32> convertBuildings(const std::set<si32> h3m, int castleID)
 	std::ifstream b5(DATA_DIR "/config/buildings5.txt");
 	while(!b5.eof())
 	{
-		int a, b;
-		b5 >> a >> b;
-		if(castleID==8 && b==17) //magic university ID 17 (h3m) => 21 (vcmi)
-			b=21;
-		if(castleID==4 && a==20) //necropolis, skeleton transformer
-			b=22;
-		if(castleID==4 && a==19) //necropolis, necromancy aplifier
-			b=21;
-		if(castleID==3 && a==18) //inferno, brimstone clouds
-			b=21;
-		if(castleID==3 && a==20) //inferno, order of fire
-			b=23;
-		if(castleID==8 && a==10) //conflux, artifact merchant
-			b=17;
-		mapa[a]=b;
+		int h3, VCMI, town;
+		b5 >> town >> h3 >> VCMI;
+		if ( town == castleID || town == -1 )
+			mapa[h3]=VCMI;
 	}
-
 	for(std::set<si32>::const_iterator i=h3m.begin();i!=h3m.end();i++)
 	{
 		if(mapa[*i]>=0)

+ 5 - 1
server/CGameHandler.cpp

@@ -571,6 +571,10 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
 
 	//end battle, remove all info, free memory
 	giveExp(*battleResult.data);
+	if (hero1)
+		battleResult.data->exp[0] *= (100+hero1->getSecSkillLevel(21)*5)/100.0f;//sholar skill
+	if (hero2)
+		battleResult.data->exp[1] *= (100+hero2->getSecSkillLevel(21)*5)/100.0f;
 	sendAndApply(battleResult.data);
 
 	//if one hero has lost we will erase him
@@ -4936,7 +4940,7 @@ bool CGameHandler::sacrificeCreatures(const IMarket *market, const CGHeroInstanc
 	int dump, exp;
 	market->getOffer(crid, 0, dump, exp, CREATURE_EXP);
 	exp *= count;
-	changePrimSkill	(hero->id, 4, exp);
+	changePrimSkill	(hero->id, 4, exp*(100+hero->getSecSkillLevel(21)*5)/100.0f);
 
 	return true;
 }