浏览代码

* nicer movement of creatures on battlefield
* amounts of creatures on battlefield
* partial support for two hex creatures
* a few minor things

mateuszb 17 年之前
父节点
当前提交
063d2279ee
共有 9 个文件被更改,包括 240 次插入38 次删除
  1. 161 20
      CBattleInterface.cpp
  2. 5 3
      CBattleInterface.h
  3. 2 2
      CGameInterface.h
  4. 39 7
      CGameState.cpp
  5. 3 2
      CGameState.h
  6. 2 2
      CPlayerInterface.cpp
  7. 1 1
      CPlayerInterface.h
  8. 22 0
      hch/CCreatureHandler.cpp
  9. 5 1
      hch/CCreatureHandler.h

+ 161 - 20
CBattleInterface.cpp

@@ -9,8 +9,11 @@
 #include "CCallback.h"
 #include "CGameState.h"
 #include <queue>
+#include <sstream>
 
 extern SDL_Surface * screen;
+extern TTF_Font * GEOR13;
+extern SDL_Color zwykly;
 SDL_Surface * CBattleInterface::cellBorder, * CBattleInterface::cellShade;
 
 CBattleInterface::CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2) 
@@ -22,10 +25,11 @@ CBattleInterface::CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, C
 	std::map<int, CStack> stacks = LOCPLINT->cb->battleGetStacks();
 	for(std::map<int, CStack>::iterator b=stacks.begin(); b!=stacks.end(); ++b)
 	{
-		std::pair <int, int> coords = CBattleHex::getXYUnitAnim(b->second.position, b->second.owner == attackingHeroInstance->tempOwner);
+		std::pair <int, int> coords = CBattleHex::getXYUnitAnim(b->second.position, b->second.owner == attackingHeroInstance->tempOwner, b->second.creature);
 		creAnims[b->second.ID] = (new CCreatureAnimation(b->second.creature->animDefName));
 		creAnims[b->second.ID]->setType(2);
 		creAnims[b->second.ID]->pos = genRect(creAnims[b->second.ID]->fullHeight, creAnims[b->second.ID]->fullWidth, coords.first, coords.second);
+		creDir[b->second.ID] = b->second.owner==attackingHeroInstance->tempOwner;
 	}
 	//preparing menu background and terrain
 	std::vector< std::string > & backref = CGI->mh->battleBacks[ LOCPLINT->cb->battleGetBattlefieldType() ];
@@ -33,6 +37,22 @@ CBattleInterface::CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, C
 	menu = CGI->bitmaph->loadBitmap("CBAR.BMP");
 	CSDL_Ext::blueToPlayersAdv(menu, hero1->tempOwner);
 
+	//preparing graphics for displaying amounts of creatures
+	amountBasic = CGI->bitmaph->loadBitmap("CMNUMWIN.BMP");
+	amountNormal = CGI->bitmaph->loadBitmap("CMNUMWIN.BMP");
+	CSDL_Ext::alphaTransform(amountNormal);
+	for(int g=0; g<amountNormal->format->palette->ncolors; ++g)
+	{
+		if((amountNormal->format->palette->colors+g)->b != 132 &&
+			(amountNormal->format->palette->colors+g)->g != 231 &&
+			(amountNormal->format->palette->colors+g)->r != 255) //it's not yellow border
+		{
+			(amountNormal->format->palette->colors+g)->r = (float)((amountNormal->format->palette->colors+g)->r) * 0.54f;
+			(amountNormal->format->palette->colors+g)->g = (float)((amountNormal->format->palette->colors+g)->g) * 0.19f;
+			(amountNormal->format->palette->colors+g)->b = (float)((amountNormal->format->palette->colors+g)->b) * 0.93f;
+		}
+	}
+
 	//blitting menu background and terrain
 	blitAt(background, 0, 0);
 	blitAt(menu, 0, 556);
@@ -206,15 +226,68 @@ void CBattleInterface::show(SDL_Surface * to)
 		defendingHero->show(to);
 
 	//showing units //a lot of work...
-	for(std::map<int, CCreatureAnimation*>::iterator j=creAnims.begin(); j!=creAnims.end(); ++j)
+	int stackByHex[187];
+	for(int b=0; b<187; ++b)
+		stackByHex[b] = -1;
+	for(std::map<int, CStack>::iterator j=stacks.begin(); j!=stacks.end(); ++j)
 	{
-		j->second->nextFrame(to, j->second->pos.x, j->second->pos.y, stacks[j->first].owner == attackingHeroInstance->tempOwner, animCount%2==0 || j->second->getType()==0, j->first==activeStack); //increment always when moving
+		stackByHex[j->second.position] = j->second.ID;
+	}
+	for(int b=0; b<187; ++b)
+	{
+		if(stackByHex[b]!=-1)
+		{
+			creAnims[stackByHex[b]]->nextFrame(to, creAnims[stackByHex[b]]->pos.x, creAnims[stackByHex[b]]->pos.y, creDir[stackByHex[b]], animCount%2==0 || creAnims[stackByHex[b]]->getType()==0, stackByHex[b]==activeStack); //increment always when moving
+			//printing amount
+			if(stacks[stackByHex[b]].attackerOwned)
+			{
+				CSDL_Ext::blit8bppAlphaTo24bpp(amountNormal, NULL, to, &genRect(amountNormal->h, amountNormal->w, creAnims[stackByHex[b]]->pos.x + 220, creAnims[stackByHex[b]]->pos.y + 260));
+				std::stringstream ss;
+				ss<<stacks[stackByHex[b]].amount;
+				CSDL_Ext::printAtMiddleWB(ss.str(), creAnims[stackByHex[b]]->pos.x + 220 + 14, creAnims[stackByHex[b]]->pos.y + 260 + 4, GEOR13, 20, zwykly, to);
+			}
+			else
+			{
+				CSDL_Ext::blit8bppAlphaTo24bpp(amountNormal, NULL, to, &genRect(amountNormal->h, amountNormal->w, creAnims[stackByHex[b]]->pos.x + 202, creAnims[stackByHex[b]]->pos.y + 260));
+				std::stringstream ss;
+				ss<<stacks[stackByHex[b]].amount;
+				CSDL_Ext::printAtMiddleWB(ss.str(), creAnims[stackByHex[b]]->pos.x + 202 + 14, creAnims[stackByHex[b]]->pos.y + 260 + 4, GEOR13, 20, zwykly, to);
+			}
+		}
 	}
 	//units shown
 
 	CSDL_Ext::update();
 }
 
+bool CBattleInterface::reverseCreature(int number, int hex)
+{
+	if(creAnims[number]==NULL)
+		return false; //there is no such creature
+	creAnims[number]->setType(8);
+	for(int g=0; g<creAnims[number]->framesInGroup(8); ++g)
+	{
+		show();
+		SDL_framerateDelay(LOCPLINT->mainFPSmng);
+	}
+	creDir[number] = !creDir[number];
+
+	CStack curs = LOCPLINT->cb->battleGetStackByID(number);
+	std::pair <int, int> coords = CBattleHex::getXYUnitAnim(hex, creDir[number], curs.creature);
+	creAnims[number]->pos.x = coords.first;
+	creAnims[number]->pos.y = coords.second;
+
+	creAnims[number]->setType(7);
+	for(int g=0; g<creAnims[number]->framesInGroup(7); ++g)
+	{
+		show();
+		SDL_framerateDelay(LOCPLINT->mainFPSmng);
+	}
+	creAnims[number]->setType(2);
+
+	return true;
+}
+
 void CBattleInterface::bOptionsf()
 {
 }
@@ -270,6 +343,7 @@ void CBattleInterface::newStack(CStack stack)
 {
 	creAnims[stack.ID] = new CCreatureAnimation(stack.creature->animDefName);
 	creAnims[stack.ID]->setType(2);
+	creDir[stack.ID] = stack.owner==attackingHeroInstance->tempOwner;
 }
 
 void CBattleInterface::stackRemoved(CStack stack)
@@ -284,11 +358,49 @@ void CBattleInterface::stackActivated(int number)
 	activeStack = number;
 }
 
-void CBattleInterface::stackMoved(int number, int destHex)
+void CBattleInterface::stackMoved(int number, int destHex, bool startMoving, bool endMoving)
 {
 	int curStackPos = LOCPLINT->cb->battleGetPos(number);
-	int steps = 6;
+	int steps = creAnims[number]->framesInGroup(0);
 	int hexWbase = 44, hexHbase = 42;
+
+	if(startMoving) //animation of starting move
+	{
+		for(int i=0; i<creAnims[number]->framesInGroup(20); ++i)
+		{
+			show();
+			SDL_framerateDelay(LOCPLINT->mainFPSmng);
+		}
+	}
+
+	switch(CBattleHex::mutualPosition(curStackPos, destHex)) //reverse unit if necessary
+	{
+	case 0:
+		if(creDir[number] == true)
+			reverseCreature(number, curStackPos);
+		break;
+	case 1:
+		if(creDir[number] == false)
+			reverseCreature(number, curStackPos);
+		break;
+	case 2:
+		if(creDir[number] == false)
+			reverseCreature(number, curStackPos);
+		break;
+	case 3:
+		if(creDir[number] == false)
+			reverseCreature(number, curStackPos);
+		break;
+	case 4:
+		if(creDir[number] == true)
+			reverseCreature(number, curStackPos);
+		break;
+	case 5:
+		if(creDir[number] == true)
+			reverseCreature(number, curStackPos);
+		break;
+	}
+	//moving instructions
 	creAnims[number]->setType(0);
 	for(int i=0; i<steps; ++i)
 	{
@@ -320,11 +432,26 @@ void CBattleInterface::stackMoved(int number, int destHex)
 		show();
 		SDL_framerateDelay(LOCPLINT->mainFPSmng);
 	}
+
+	if(endMoving) //animation of starting move
+	{
+		for(int i=0; i<creAnims[number]->framesInGroup(21); ++i)
+		{
+			show();
+			SDL_framerateDelay(LOCPLINT->mainFPSmng);
+		}
+	}
 	
-	creAnims[number]->setType(2); //resetting to delault
+	creAnims[number]->setType(2); //resetting to default
 	CStack curs = LOCPLINT->cb->battleGetStackByID(number);
+	if(endMoving) //resetting to default
+	{
+		if(creDir[number] != (curs.owner == attackingHeroInstance->tempOwner))
+			reverseCreature(number, destHex);
+		//creDir[number] = (curs.owner == attackingHeroInstance->tempOwner);
+	}
 	
-	std::pair <int, int> coords = CBattleHex::getXYUnitAnim(destHex, curs.owner == attackingHeroInstance->tempOwner);
+	std::pair <int, int> coords = CBattleHex::getXYUnitAnim(destHex, creDir[number], curs.creature);
 	creAnims[number]->pos.x = coords.first;
 	creAnims[number]->pos.y = coords.second;
 }
@@ -360,6 +487,20 @@ void CBattleInterface::showRange(SDL_Surface * to, int ID)
 
 void CBattleHero::show(SDL_Surface *to)
 {
+	//animation of flag
+	if(flip)
+	{
+		CSDL_Ext::blit8bppAlphaTo24bpp(flag->ourImages[flagAnim].bitmap, NULL, screen, &genRect(flag->ourImages[flagAnim].bitmap->h, flag->ourImages[flagAnim].bitmap->w, 752, 39));
+	}
+	else
+	{
+		CSDL_Ext::blit8bppAlphaTo24bpp(flag->ourImages[flagAnim].bitmap, NULL, screen, &genRect(flag->ourImages[flagAnim].bitmap->h, flag->ourImages[flagAnim].bitmap->w, 31, 39));
+	}
+	{
+		++flagAnim;
+		flagAnim %= flag->ourImages.size();
+	}
+	//animation of hero
 	int tick=-1;
 	for(int i=0; i<dh->ourImages.size(); ++i)
 	{
@@ -377,18 +518,6 @@ void CBattleHero::show(SDL_Surface *to)
 			break;
 		}
 	}
-	if(flip)
-	{
-		CSDL_Ext::blit8bppAlphaTo24bpp(flag->ourImages[flagAnim].bitmap, NULL, screen, &genRect(flag->ourImages[flagAnim].bitmap->h, flag->ourImages[flagAnim].bitmap->w, 752, 39));
-	}
-	else
-	{
-		CSDL_Ext::blit8bppAlphaTo24bpp(flag->ourImages[flagAnim].bitmap, NULL, screen, &genRect(flag->ourImages[flagAnim].bitmap->h, flag->ourImages[flagAnim].bitmap->w, 31, 39));
-	}
-	{
-		++flagAnim;
-		flagAnim %= flag->ourImages.size();
-	}
 }
 
 CBattleHero::CBattleHero(std::string defName, int phaseG, int imageG, bool flipG, unsigned char player): phase(phaseG), image(imageG), flip(flipG), flagAnim(0)
@@ -421,7 +550,7 @@ CBattleHero::~CBattleHero()
 	delete flag;
 }
 
-std::pair<int, int> CBattleHex::getXYUnitAnim(int hexNum, bool attacker)
+std::pair<int, int> CBattleHex::getXYUnitAnim(int hexNum, bool attacker, CCreature * creature)
 {
 	std::pair<int, int> ret = std::make_pair(-500, -500); //returned value
 	ret.second = -139 + 42 * (hexNum/17); //counting y
@@ -434,6 +563,18 @@ std::pair<int, int> CBattleHex::getXYUnitAnim(int hexNum, bool attacker)
 	{
 		ret.first = -219 + 22 * ( ((hexNum/17) + 1)%2 ) + 44 * (hexNum % 17);
 	}
+	//shifting position for double - hex creatures
+	if(creature->isDoubleWide())
+	{
+		if(attacker)
+		{
+			ret.first -= 42;
+		}
+		else
+		{
+			ret.first += 42;
+		}
+	}
 	//returning
 	return ret;
 }

+ 5 - 3
CBattleInterface.h

@@ -32,7 +32,7 @@ public:
 	//CStack * ourStack;
 	bool hovered, strictHovered;
 	CBattleInterface * myInterface; //interface that owns me
-	static std::pair<int, int> getXYUnitAnim(int hexNum, bool attacker); //returns (x, y) of left top corner of animation
+	static std::pair<int, int> getXYUnitAnim(int hexNum, bool attacker, CCreature * creature); //returns (x, y) of left top corner of animation
 	static signed char mutualPosition(int hex1, int hex2); //returns info about mutual position of given hexes (-1 - they distant, 0 - left top, 1 - right top, 2 - right, 3 - right bottom, 4 - left bottom, 5 - left)
 	//for user interactions
 	void hover (bool on);
@@ -51,13 +51,14 @@ class CBattleObstacle
 class CBattleInterface : public IActivable, public IShowable
 {
 private:
-	SDL_Surface * background, * menu;
+	SDL_Surface * background, * menu, * amountBasic, * amountNormal;
 	AdventureMapButton<CBattleInterface> * bOptions, * bSurrender, * bFlee, * bAutofight, * bSpell,
 		* bWait, * bDefence, * bConsoleUp, * bConsoleDown;
 	CBattleHero * attackingHero, * defendingHero;
 	CCreatureSet * army1, * army2; //fighting armies
 	CGHeroInstance * attackingHeroInstance, * defendingHeroInstance;
 	std::map< int, CCreatureAnimation * > creAnims; //animations of creatures from fighting armies (order by BattleInfo's stacks' ID)
+	std::map< int, bool > creDir; // <creatureID, if false reverse creature's animation>
 	unsigned char animCount;
 	int activeStack; //number of active stack; -1 - no one
 	void showRange(SDL_Surface * to, int ID); //show helper funtion ot mark range of a unit
@@ -88,12 +89,13 @@ public:
 	void activate();
 	void deactivate();
 	void show(SDL_Surface * to = NULL);
+	bool reverseCreature(int number, int hex); //reverses animation of given creature playing animation of reversing
 
 	//call-ins
 	void newStack(CStack stack); //new stack appeared on battlefield
 	void stackRemoved(CStack stack); //stack disappeared from batlefiled
 	void stackActivated(int number); //active stack has been changed
-	void stackMoved(int number, int destHex); //stack with id number moved to destHex
+	void stackMoved(int number, int destHex, bool startMoving, bool endMoving); //stack with id number moved to destHex
 	void stackAttacking(int ID, int dest); //called when stack with id ID is attacking something on hex dest
 	void turnEnded(); //caled when current unit cannot get new orders
 	void hexLclicked(int whichOne); //hex only call-in

+ 2 - 2
CGameInterface.h

@@ -58,7 +58,7 @@ public:
 	virtual void actionFinished(BattleAction action){};//occurs AFTER every action taken by any stack or by the hero
 	virtual void activeStack(int stackID){}; //called when it's turn of that stack
 	virtual void battleEnd(CCreatureSet * army1, CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2, std::vector<int> capturedArtifacts, int expForWinner, bool winner){};
-	virtual void battleStackMoved(int ID, int dest)=0;
+	virtual void battleStackMoved(int ID, int dest, bool startMoving, bool endMoving)=0;
 	//
 
 };
@@ -74,6 +74,6 @@ public:
 	virtual void yourTurn(){};
 	virtual void heroKilled(const CGHeroInstance*){};
 	virtual void heroCreated(const CGHeroInstance*){};
-	virtual void battleStackMoved(int ID, int dest){};
+	virtual void battleStackMoved(int ID, int dest, bool startMoving, bool endMoving){};
 };
 #endif //CGAMEINTERFACE_H

+ 39 - 7
CGameState.cpp

@@ -12,7 +12,7 @@ class CMP_stack
 public:
 	bool operator ()(const CStack* a, const CStack* b)
 	{
-		return (a->creature->speed)<(b->creature->speed);
+		return (a->creature->speed)>(b->creature->speed);
 	}
 } cmpst ;
 
@@ -31,7 +31,7 @@ void CGameState::battle(CCreatureSet * army1, CCreatureSet * army2, int3 tile, C
 	curB->stackActionPerformed = false;
 	for(std::map<int,std::pair<CCreature*,int> >::iterator i = army1->slots.begin(); i!=army1->slots.end(); i++)
 	{
-		stacks.push_back(new CStack(i->second.first,i->second.second,0, stacks.size()));
+		stacks.push_back(new CStack(i->second.first,i->second.second,0, stacks.size(), true));
 		stacks[stacks.size()-1]->ID = stacks.size()-1;
 	}
 	//initialization of positions
@@ -85,8 +85,8 @@ void CGameState::battle(CCreatureSet * army1, CCreatureSet * army2, int3 tile, C
 		break;
 	}
 	for(std::map<int,std::pair<CCreature*,int> >::iterator i = army2->slots.begin(); i!=army2->slots.end(); i++)
-		stacks.push_back(new CStack(i->second.first,i->second.second,1, stacks.size()));
-	switch(army2->slots.size()) //for attacker
+		stacks.push_back(new CStack(i->second.first,i->second.second,1, stacks.size(), false));
+	switch(army2->slots.size()) //for defender
 	{
 	case 0:
 		break;
@@ -135,6 +135,17 @@ void CGameState::battle(CCreatureSet * army1, CCreatureSet * army2, int3 tile, C
 	default: //fault
 		break;
 	}
+	for(int g=0; g<stacks.size(); ++g) //shifting positions of two-hex creatures
+	{
+		if((stacks[g]->position%17)==1 && stacks[g]->creature->isDoubleWide())
+		{
+			stacks[g]->position += 1;
+		}
+		else if((stacks[g]->position%17)==15 && stacks[g]->creature->isDoubleWide())
+		{
+			stacks[g]->position -= 1;
+		}
+	}
 	std::stable_sort(stacks.begin(),stacks.end(),cmpst);
 
 	//for start inform players about battle
@@ -180,7 +191,7 @@ void CGameState::battle(CCreatureSet * army1, CCreatureSet * army2, int3 tile, C
 			curB->stackActionPerformed = false;
 			if(stacks[i]->alive) //niech interfejs ruszy oddzialem
 			{
-				unsigned char owner = (stacks[i]->owner)?(hero2->tempOwner):(hero1->tempOwner);
+				unsigned char owner = (stacks[i]->owner)?(hero2 ? hero2->tempOwner : 255):(hero1->tempOwner);
 				unsigned char serialOwner = -1;
 				for(int g=0; g<CGI->playerint.size(); ++g)
 				{
@@ -190,7 +201,10 @@ void CGameState::battle(CCreatureSet * army1, CCreatureSet * army2, int3 tile, C
 						break;
 					}
 				}
-				if(CGI->playerint[serialOwner]->human)
+				if(serialOwner==255) //neutral unit
+				{
+				}
+				else if(CGI->playerint[serialOwner]->human)
 				{
 					((CPlayerInterface*)CGI->playerint[serialOwner])->activeStack(stacks[i]->ID);
 				}
@@ -252,7 +266,16 @@ bool CGameState::battleMoveCreatureStack(int ID, int dest)
 	for(int g=0; g<curB->stacks.size(); ++g)
 	{
 		if(curB->stacks[g]->owner == owner) //we don't want to lock enemy's positions
+		{
 			accessibility[curB->stacks[g]->position] = false;
+			if(curB->stacks[g]->creature->isDoubleWide()) //if it's a double hex creature
+			{
+				if(curB->stacks[g]->attackerOwned)
+					accessibility[curB->stacks[g]->position-1] = false;
+				else
+					accessibility[curB->stacks[g]->position+1] = false;
+			}
+		}
 	}
 	int predecessor[187]; //for getting the Path
 	for(int b=0; b<187; ++b)
@@ -326,7 +349,7 @@ bool CGameState::battleMoveCreatureStack(int ID, int dest)
 	{
 		if(v!=0 || !stackAtEnd) //it's not the last step
 		{
-			LOCPLINT->battleStackMoved(ID, path[v]);
+			LOCPLINT->battleStackMoved(ID, path[v], v==path.size()-1, v==0);
 			curStack->position = path[v];
 		}
 		else //if it's last step and we should attack unit at the end
@@ -361,7 +384,16 @@ std::vector<int> CGameState::battleGetRange(int ID)
 	for(int g=0; g<curB->stacks.size(); ++g)
 	{
 		if(curB->stacks[g]->owner == owner) //we don't want to lock enemy's positions
+		{
 			accessibility[curB->stacks[g]->position] = false;
+			if(curB->stacks[g]->creature->isDoubleWide()) //if it's a double hex creature
+			{
+				if(curB->stacks[g]->attackerOwned)
+					accessibility[curB->stacks[g]->position-1] = false;
+				else
+					accessibility[curB->stacks[g]->position+1] = false;
+			}
+		}
 	}
 
 

+ 3 - 2
CGameState.h

@@ -45,10 +45,11 @@ public:
 	CCreature * creature;
 	int amount;
 	int owner;
+	bool attackerOwned; //if true, this stack is owned by attakcer (this one from left hand side of battle)
 	int position; //position on battlefield
 	bool alive; //true if it is alive
-	CStack(CCreature * C, int A, int O, int I):creature(C),amount(A),owner(O), alive(true), position(-1), ID(I){};
-	CStack() : creature(NULL),amount(-1),owner(255), alive(true), position(-1), ID(-1){};
+	CStack(CCreature * C, int A, int O, int I, bool AO):creature(C),amount(A),owner(O), alive(true), position(-1), ID(I), attackerOwned(AO){};
+	CStack() : creature(NULL),amount(-1),owner(255), alive(true), position(-1), ID(-1), attackerOwned(true){};
 };
 
 class CGameState

+ 2 - 2
CPlayerInterface.cpp

@@ -1986,9 +1986,9 @@ void CPlayerInterface::battleEnd(CCreatureSet * army1, CCreatureSet * army2, CGH
 {
 }
 
-void CPlayerInterface::battleStackMoved(int ID, int dest)
+void CPlayerInterface::battleStackMoved(int ID, int dest, bool startMoving, bool endMoving)
 {
-	dynamic_cast<CBattleInterface*>(curint)->stackMoved(ID, dest);
+	dynamic_cast<CBattleInterface*>(curint)->stackMoved(ID, dest, startMoving, endMoving);
 }
 
 void CPlayerInterface::battleStackAttacking(int ID, int dest)

+ 1 - 1
CPlayerInterface.h

@@ -334,7 +334,7 @@ public:
 	void actionFinished(BattleAction action);//occurs AFTER every action taken by any stack or by the hero
 	void activeStack(int stackID); //called when it's turn of that stack
 	void battleEnd(CCreatureSet * army1, CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2, std::vector<int> capturedArtifacts, int expForWinner, bool winner);
-	void battleStackMoved(int ID, int dest);
+	void battleStackMoved(int ID, int dest, bool startMoving, bool endMoving);
 	void battleStackAttacking(int ID, int dest);
 
 

+ 22 - 0
hch/CCreatureHandler.cpp

@@ -6,6 +6,7 @@
 #include <sstream>
 #include <boost/assign/std/vector.hpp>
 #include <boost/algorithm/string.hpp>
+#include <boost/algorithm/string/find.hpp>
 #include <boost/algorithm/string/replace.hpp>
 #include "../SDL_Extensions.h"
 
@@ -32,6 +33,16 @@ int CCreature::getQuantityID(int quantity)
 	return 8;
 }
 
+bool CCreature::isDoubleWide()
+{
+	return boost::algorithm::find_first(abilityRefs, "DOUBLE_WIDE");
+}
+
+bool CCreature::isFlying()
+{
+	return boost::algorithm::find_first(abilityRefs, "FLYING_ARMY");
+}
+
 void CCreatureHandler::loadCreatures()
 {
 	std::string buf = CGameInfo::mainObj->bitmaph->getTextFile("ZCRTRAIT.TXT");
@@ -953,6 +964,17 @@ int CCreatureAnimation::nextFrame(SDL_Surface *dest, int x, int y, bool attacker
 	return 0;
 }
 
+int CCreatureAnimation::framesInGroup(int group) const
+{
+	int ret = 0; //number of frames in given group
+	for(int g=0; g<SEntries.size(); ++g)
+	{
+		if(SEntries[g].group == group)
+			++ret;
+	}
+	return ret;
+}
+
 CCreatureAnimation::~CCreatureAnimation()
 {
 	delete [] FDef;

+ 5 - 1
hch/CCreatureHandler.h

@@ -40,6 +40,8 @@ public:
 	//TODO - zdolnoœci - na typie wyliczeniowym czy czymœ
 
 	static int getQuantityID(int quantity); //0 - a few, 1 - several, 2 - pack, 3 - lots, 4 - horde, 5 - throng, 6 - swarm, 7 - zounds, 8 - legion
+	bool isDoubleWide(); //returns true if unit is double wide on battlefield
+	bool isFlying(); //returns true if it is a flying unit
 };
 
 class CCreatureSet //seven combined creatures
@@ -96,13 +98,15 @@ private:
 public:
 	int fullWidth, fullHeight; //read-only, please!
 	CCreatureAnimation(std::string name); //c-tor
-	~CCreatureAnimation(); //d-tor //not necessery ATM
+	~CCreatureAnimation(); //d-tor
 
 	void setType(int type); //sets type of animation and cleares framecount
 	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 nextFrameMiddle(SDL_Surface * dest, int x, int y, bool attacker, bool incrementFrame = true, bool yellowBorder = false); //0 - success, any other - error //print next 
+
+	int framesInGroup(int group) const; //retirns number of fromes in given group
 };
 
 #endif //CCREATUREHANDLER_H