Переглянути джерело

* VCMI won't crash when r-click neutral stack during the battle
* water won't blink behind shipyard in the Castle
* in the townlist in castle selected town will by placed on the 2nd place (not 3rd)
* fixed memory leaks
* properly displaying two-hex creatures in recruit/split/info window
* minor improvements

Michał W. Urbańczyk 17 роки тому
батько
коміт
7e12926baa
6 змінених файлів з 102 додано та 46 видалено
  1. 7 5
      CBattleInterface.cpp
  2. 26 7
      CCastleInterface.cpp
  3. 1 2
      CCastleInterface.h
  4. 1 0
      CGameInterface.h
  5. 54 25
      CPlayerInterface.cpp
  6. 13 7
      CPlayerInterface.h

+ 7 - 5
CBattleInterface.cpp

@@ -904,11 +904,13 @@ void CBattleHex::clickRight(boost::logic::tribool down)
 		{
 			pom = new StackState();
 			const CGHeroInstance *h = myst.owner == myInterface->attackingHeroInstance->tempOwner ? myInterface->attackingHeroInstance : myInterface->defendingHeroInstance;
-			pom->attackBonus = h->primSkills[0];
-			pom->defenseBonus = h->primSkills[1];
-			pom->luck = h->getCurrentLuck();
-			pom->morale = h->getCurrentMorale();
-
+			if(h)
+			{
+				pom->attackBonus = h->primSkills[0];
+				pom->defenseBonus = h->primSkills[1];
+				pom->luck = h->getCurrentLuck();
+				pom->morale = h->getCurrentMorale();
+			}
 			(new CCreInfoWindow(myst.creature->idNumber,0,pom,boost::function<void()>(),boost::function<void()>()))
 					->activate();
 		}

+ 26 - 7
CCastleInterface.cpp

@@ -232,7 +232,7 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, bool Activate)
 	townlist->genList();
 	townlist->selected = getIndexOf(townlist->items,Town);
 	if((townlist->selected+1) > townlist->SIZE)
-		townlist->from = townlist->selected -  townlist->SIZE + 1;
+		townlist->from = townlist->selected -  townlist->SIZE + 2;
 
 	CSDL_Ext::blueToPlayersAdv(townInt,LOCPLINT->playerID);
 	exit->bitmapOffset = 4;
@@ -343,7 +343,7 @@ void CCastleInterface::buildingClicked(int building)
 
 		crs.push_back(std::make_pair(town->town->basicCreatures[building-30],amount));
 
-		CRecrutationWindow *rw = new CRecrutationWindow(crs,this);
+		CRecrutationWindow *rw = new CRecrutationWindow(crs,boost::bind(&CCallback::recruitCreatures,LOCPLINT->cb,town,_1,_2));
 		rw->activate();
 	}
 	else
@@ -468,7 +468,7 @@ void CCastleInterface::show(SDL_Surface * to)
 	//blit buildings
 	for(int i=0;i<buildings.size();i++)
 	{
-		int frame = (animval)%(buildings[i]->max - buildings[i]->offset);
+		int frame = ((animval)%(buildings[i]->max - buildings[i]->offset)) + buildings[i]->offset;
 		if(frame)
 		{
 			blitAt(buildings[i]->def->ourImages[0].bitmap,buildings[i]->pos.x,buildings[i]->pos.y,to);
@@ -606,10 +606,29 @@ void CCastleInterface::recreateBuildings()
 			vortex->max = 10;
 		}
 	}
-}
-void CCastleInterface::recruit(int ID, int amount)
-{
-	LOCPLINT->cb->recruitCreatures(town,ID,amount);
+	//code for the shipyard in the Castle
+	else if((town->subID == 0) && (town->builtBuildings.find(6)!=town->builtBuildings.end())) 
+	{
+		CBuildingRect *shipyard = NULL;
+		for(int i=0;i<buildings.size();i++)
+		{
+			if(buildings[i]->str->ID==6)
+			{
+				shipyard=buildings[i];
+				break;
+			}
+		}
+		if(town->builtBuildings.find(8)!=town->builtBuildings.end()) //there is citadel
+		{
+			shipyard->offset = 1;
+			shipyard->max = shipyard->def->ourImages.size();
+		}
+		else
+		{
+			shipyard->offset = 0;
+			shipyard->max = 1;
+		}
+	}
 }
 void CHallInterface::CResDataBar::show(SDL_Surface * to)
 {

+ 1 - 2
CCastleInterface.h

@@ -28,7 +28,7 @@ public:
 	void mouseMoved (SDL_MouseMotionEvent & sEvent);
 };
 
-class CCastleInterface : public IShowable, public IActivable, public IRecruit
+class CCastleInterface : public IShowable, public IActivable
 {
 public:
 	bool showing;
@@ -64,7 +64,6 @@ public:
 	void addBuilding(int bid);
 	void removeBuilding(int bid);
 	void recreateBuildings();
-	void recruit(int ID, int amount);
 };
 
 class CHallInterface : public IShowable, public IActivable

+ 1 - 0
CGameInterface.h

@@ -35,6 +35,7 @@ struct BattleAction
 
 struct StackState
 {
+	StackState(){attackBonus=defenseBonus=healthBonus=speedBonus=morale=luck=shotsLeft=currentHealth=0;};
 	int attackBonus, defenseBonus, healthBonus, speedBonus;
 	int currentHealth;
 	int shotsLeft;

+ 54 - 25
CPlayerInterface.cpp

@@ -2662,6 +2662,28 @@ void CTownList::draw()
 }
 
 
+CCreaturePic::CCreaturePic(CCreature *cre)
+:c(cre)
+{
+	anim = new CCreatureAnimation(cre->animDefName);
+}
+CCreaturePic::~CCreaturePic()
+{
+	delete anim;
+}
+int CCreaturePic::blitPic(SDL_Surface *to, int x, int y, bool nextFrame)
+{
+	blitAt(CGI->creh->backgrounds[c->faction],x,y);//curx-50,pos.y+130-65);
+	SDL_Rect dst = genRect(130,100,x,y);
+	if(c->isDoubleWide())
+		x-=15;
+	return anim->nextFrameMiddle(to,x+70,y+45,true,nextFrame,false,&dst);
+}
+SDL_Surface * CCreaturePic::getPic(bool nextFrame)
+{
+	//TODO: write
+	return NULL;
+}
 void CRecrutationWindow::close()
 {
 	deactivate();
@@ -2677,7 +2699,7 @@ void CRecrutationWindow::Max()
 }
 void CRecrutationWindow::Buy()
 {
-	rec->recruit(creatures[which].ID,slider->value);
+	recruit(creatures[which].ID,slider->value);
 	close();
 }
 void CRecrutationWindow::Cancel()
@@ -2762,15 +2784,13 @@ void CRecrutationWindow::show(SDL_Surface * to)
 	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);
-		SDL_Rect dst = genRect(130,100,curx-50,pos.y+130-65);
-		creatures[i].anim->nextFrameMiddle(screen,curx+20,pos.y+110,true,!(c%2),false,&dst);
+		creatures[i].pic->blitPic(screen,curx-50,pos.y+130-65,!(c%2));
 		curx += 120;
 	}
 	c++;
 }
-CRecrutationWindow::CRecrutationWindow(std::vector<std::pair<int,int> > &Creatures, IRecruit *irec) //creatures - pairs<creature_ID,amount>
-:rec(irec)
+CRecrutationWindow::CRecrutationWindow(const std::vector<std::pair<int,int> > &Creatures, const boost::function<void(int,int)> &Recruit) //creatures - pairs<creature_ID,amount>
+:recruit(Recruit)
 {
 	which = 0;
 	creatures.resize(Creatures.size());
@@ -2782,7 +2802,7 @@ CRecrutationWindow::CRecrutationWindow(std::vector<std::pair<int,int> > &Creatur
 		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);
+		creatures[i].pic = new CCreaturePic(&CGI->creh->creatures[Creatures[i].first]);
 		amounts[i] = CGI->creh->creatures[Creatures[i].first].maxAmount(LOCPLINT->cb->getResourceAmount());
 	}
 	SDL_Surface *hhlp = CGI->bitmaph->loadBitmap("TPRCRT.bmp");
@@ -2832,6 +2852,13 @@ CRecrutationWindow::CRecrutationWindow(std::vector<std::pair<int,int> > &Creatur
 }//(int x, int y, int totalw, T*Owner,void(T::*Moved)(int to), int Capacity, int Amount, int Value, bool Horizontal)
 CRecrutationWindow::~CRecrutationWindow()
 {
+	for(int i=0;i<creatures.size();i++)
+	{
+		delete creatures[i].pic;
+	}
+	delete max;
+	delete buy;
+	delete cancel;
 	SDL_FreeSurface(bitmap);
 	delete slider;
 }
@@ -2852,8 +2879,8 @@ CSplitWindow::CSplitWindow(int cid, int max, CGarrisonInt *Owner)
 	slider = new CSlider(pos.x+21,pos.y+194,257,boost::bind(&CSplitWindow::sliderMoved,this,_1),1,max,0,true);
 	a1 = max;
 	a2 = 0;
-	anim = new CCreatureAnimation(CGI->creh->creatures[cid].animDefName);
-	anim->setType(1);
+	anim = new CCreaturePic(&CGI->creh->creatures[cid]);
+	anim->anim->setType(1);
 
 	std::string title = CGI->generaltexth->allTexts[256];
 	boost::algorithm::replace_first(title,"%s",CGI->creh->creatures[cid].namePl);
@@ -2862,6 +2889,10 @@ CSplitWindow::CSplitWindow(int cid, int max, CGarrisonInt *Owner)
 CSplitWindow::~CSplitWindow()
 {
 	SDL_FreeSurface(bitmap);
+	delete ok;
+	delete cancel;
+	delete slider;
+	delete anim;
 }
 void CSplitWindow::activate()
 {
@@ -2910,27 +2941,20 @@ void CSplitWindow::show(SDL_Surface * to)
 	printAtMiddle(pom,pos.x+70,pos.y+237,GEOR16,zwykly,screen);
 	itoa(a2,pom,10);
 	printAtMiddle(pom,pos.x+233,pos.y+237,GEOR16,zwykly,screen);
-
-
-	blitAt(CGI->creh->backgrounds[CGI->creh->creatures[c].faction],pos.x+20,pos.y+54);
-	anim->nextFrameMiddle(screen,pos.x+20+70,pos.y+54+55,true,false,false);
-
-	blitAt(CGI->creh->backgrounds[CGI->creh->creatures[c].faction],pos.x+177,pos.y+54);
-	anim->nextFrameMiddle(screen,pos.x+177+70,pos.y+54+55,true,false,false);
+	anim->blitPic(screen,pos.x+20,pos.y+54,false);
+	anim->blitPic(screen,pos.x+177,pos.y+54,false);
 }
 void CSplitWindow::keyPressed (SDL_KeyboardEvent & key)
 {
-	//TODO: zeby sie dalo recznie wpisywac
+	//TODO: make manual typing possible 
 }
 
-
-
 void CCreInfoWindow::show(SDL_Surface * to)
 {
 	char pom[15];
 	blitAt(bitmap,pos.x,pos.y,screen);
-	blitAt(CGI->creh->backgrounds[c->faction],pos.x+21,pos.y+48,screen);
-	anim->nextFrameMiddle(screen,pos.x+90,pos.y+95,true,false,false);
+	anim->blitPic(screen,pos.x+21,pos.y+48,(type) && anf);
+	anf=!anf;
 	if(upgrade)
 		upgrade->show();
 	if(dismiss)
@@ -2951,8 +2975,8 @@ CCreInfoWindow::CCreInfoWindow
 	pos.h = bitmap->h;
 	blueToPlayersAdv(bitmap,LOCPLINT->playerID);
 	SDL_SetColorKey(bitmap,SDL_SRCCOLORKEY,SDL_MapRGB(bitmap->format,0,255,255));
-	anim = new CCreatureAnimation(c->animDefName);
-	anim->setType(1);
+	anim = new CCreaturePic(c);
+	if(!type) anim->anim->setType(1);
 
 	char pom[25];int hlp=0;
 	printAtMiddle(c->namePl,149,30,GEOR13,zwykly,bitmap); //creature name
@@ -3034,10 +3058,14 @@ CCreInfoWindow::~CCreInfoWindow()
 {
 	SDL_FreeSurface(bitmap);
 	delete anim;
+	delete upgrade;
+	delete ok;
+	delete dismiss;
 }
 void CCreInfoWindow::activate()
 {
-	ClickableR::activate();
+	if(!type)
+		ClickableR::activate();
 	LOCPLINT->objsToBlit.push_back(this);
 	if(ok)
 		ok->activate();
@@ -3074,7 +3102,8 @@ void CCreInfoWindow::keyPressed (SDL_KeyboardEvent & key)
 }
 void CCreInfoWindow::deactivate()
 {
-	ClickableR::deactivate(); 
+	if(!type)
+		ClickableR::deactivate(); 
 	LOCPLINT->objsToBlit.erase(std::find(LOCPLINT->objsToBlit.begin(),LOCPLINT->objsToBlit.end(),this));
 	if(ok)
 		ok->deactivate();

+ 13 - 7
CPlayerInterface.h

@@ -449,10 +449,15 @@ public:
 	void draw();
 };
 
-class IRecruit
+class CCreaturePic //draws 100x130 picture with creature on background, use nextFrame=true to get animation
 {
 public:
-	virtual void recruit(int ID, int amount)=0;
+	CCreature *c;
+	CCreatureAnimation *anim;
+	CCreaturePic(CCreature *cre);
+	~CCreaturePic();
+	int blitPic(SDL_Surface *to, int x, int y, bool nextFrame);
+	SDL_Surface * getPic(bool nextFrame);
 };
 
 class CRecrutationWindow : public IShowable, public ClickableL
@@ -461,13 +466,13 @@ public:
 	struct creinfo
 	{
 		SDL_Rect pos;
+		CCreaturePic *pic;
 		int ID, amount; //creature ID and available amount
-		CCreatureAnimation *anim;
 		std::vector<std::pair<int,int> > res; //res_id - cost_per_unit
 	};
 	std::vector<int> amounts; //how many creatures we can afford
 	std::vector<creinfo> creatures;
-	IRecruit *rec;
+	boost::function<void(int,int)> recruit; //void (int ID, int amount) <-- call to recruit creatures
 	CSlider *slider;
 	AdventureMapButton *max, *buy, *cancel;
 	SDL_Surface *bitmap;
@@ -482,7 +487,7 @@ public:
 	void activate(); 
 	void deactivate();
 	void show(SDL_Surface * to = NULL);
-	CRecrutationWindow(std::vector<std::pair<int,int> > & Creatures, IRecruit *irec); //creatures - pairs<creature_ID,amount>
+	CRecrutationWindow(const std::vector<std::pair<int,int> > & Creatures, const boost::function<void(int,int)> & Recruit); //creatures - pairs<creature_ID,amount>
 	~CRecrutationWindow();
 };
 
@@ -491,7 +496,7 @@ class CSplitWindow : public IShowable, public KeyInterested
 public:
 	CGarrisonInt *gar;
 	CSlider *slider;
-	CCreatureAnimation *anim;
+	CCreaturePic *anim;
 	AdventureMapButton *ok, *cancel;
 	SDL_Surface *bitmap;
 	int a1, a2, c;
@@ -513,9 +518,10 @@ class CCreInfoWindow : public IShowable, public KeyInterested, public ClickableR
 public:
 	int type;//0 - rclick popup; 1 - normal window
 	SDL_Surface *bitmap;
+	bool anf;
 
 	boost::function<void()> dsm;
-	CCreatureAnimation *anim;
+	CCreaturePic *anim;
 	CCreature *c;
 
 	AdventureMapButton *dismiss, *upgrade, *ok;