فهرست منبع

* correct handling of flying creatures in battles
* minor changes

mateuszb 16 سال پیش
والد
کامیت
9eb6128b27
10فایلهای تغییر یافته به همراه144 افزوده شده و 83 حذف شده
  1. 91 61
      CBattleInterface.cpp
  2. 1 1
      CBattleInterface.h
  3. 2 2
      CGameInterface.h
  4. 18 3
      CGameState.cpp
  5. 1 1
      CGameState.h
  6. 2 2
      CPlayerInterface.cpp
  7. 1 1
      CPlayerInterface.h
  8. 2 2
      client/Client.cpp
  9. 2 2
      lib/NetPacks.h
  10. 24 8
      server/CGameHandler.cpp

+ 91 - 61
CBattleInterface.cpp

@@ -466,7 +466,7 @@ void CBattleInterface::show(SDL_Surface * to)
 		for(size_t v=0; v<stackAliveByHex[b].size(); ++v)
 		{
 			int animType = creAnims[stackAliveByHex[b][v]]->getType();
-			bool incrementFrame = (animCount%(4/animSpeed)==0) && animType!=0 && animType!=5 && animType!=20 && animType!=21 && animType!=3 && animType!=2;
+			bool incrementFrame = (animCount%(4/animSpeed)==0) && animType!=5 && animType!=20 && animType!=3 && animType!=2;
 			if(animType == 2)
 			{
 				if(standingFrame.find(stackAliveByHex[b][v])!=standingFrame.end())
@@ -854,8 +854,9 @@ bool CBattleInterface::reverseCreature(int number, int hex, bool wideTrick)
 	if(creAnims[number]==NULL)
 		return false; //there is no such creature
 	creAnims[number]->setType(8);
-	int firstFrame = creAnims[number]->getFrame();
-	for(int g=0; creAnims[number]->getFrame() != creAnims[number]->framesInGroup(8) + firstFrame - 1; ++g)
+	//int firstFrame = creAnims[number]->getFrame();
+	//for(int g=0; creAnims[number]->getFrame() != creAnims[number]->framesInGroup(8) + firstFrame - 1; ++g)
+	while(!creAnims[number]->onLastFrameInGroup())
 	{
 		show();
 		CSDL_Ext::update();
@@ -883,8 +884,9 @@ bool CBattleInterface::reverseCreature(int number, int hex, bool wideTrick)
 	}
 
 	creAnims[number]->setType(7);
-	firstFrame = creAnims[number]->getFrame();
-	for(int g=0; creAnims[number]->getFrame() != creAnims[number]->framesInGroup(7) + firstFrame - 1; ++g)
+	//firstFrame = creAnims[number]->getFrame();
+	//for(int g=0; creAnims[number]->getFrame() != creAnims[number]->framesInGroup(7) + firstFrame - 1; ++g)
+	while(!creAnims[number]->onLastFrameInGroup())
 	{
 		show();
 		CSDL_Ext::update();
@@ -1006,7 +1008,7 @@ void CBattleInterface::stackActivated(int number)
 	}
 }
 
-void CBattleInterface::stackMoved(int number, int destHex, bool endMoving)
+void CBattleInterface::stackMoved(int number, int destHex, bool endMoving, int distance)
 {
 	bool startMoving = creAnims[number]->getType()==20;
 	//a few useful variables
@@ -1014,6 +1016,10 @@ void CBattleInterface::stackMoved(int number, int destHex, bool endMoving)
 	int steps = creAnims[number]->framesInGroup(0)*getAnimSpeedMultiplier()-1;
 	int hexWbase = 44, hexHbase = 42;
 	bool twoTiles = LOCPLINT->cb->battleGetCreature(number).isDoubleWide();
+	CStack * movedStack = LOCPLINT->cb->battleGetStackByID(number);
+	
+	std::pair<int, int> begPosition = CBattleHex::getXYUnitAnim(curStackPos, movedStack->attackerOwned, movedStack->creature);
+	std::pair<int, int> endPosition = CBattleHex::getXYUnitAnim(destHex, movedStack->attackerOwned, movedStack->creature);
 
 	if(startMoving) //animation of starting move; some units don't have this animation (ie. halberdier)
 	{
@@ -1027,78 +1033,102 @@ void CBattleInterface::stackMoved(int number, int destHex, bool endMoving)
 	}
 
 	int mutPos = BattleInfo::mutualPosition(curStackPos, destHex);
+	float stepX=0.0, stepY=0.0; //how far stack is moved in one frame; calculated later
 
+	//reverse unit if necessary
+	if((begPosition.first > endPosition.first) && creDir[number] == true)
+	{
+		reverseCreature(number, curStackPos, twoTiles);
+	}
+	else if ((begPosition.first < endPosition.first) && creDir[number] == false)
 	{
-		switch(mutPos) //reverse unit if necessary
+		reverseCreature(number, curStackPos, twoTiles);
+	}
+	if(creAnims[number]->getType() != 0)
+	{
+		creAnims[number]->setType(0);
+	}
+	//unit reversed
+
+	//step shift calculation
+	float posX = creAnims[number]->pos.x, posY = creAnims[number]->pos.y; // for precise calculations ;]
+	if(mutPos == -1 && movedStack->creature->isFlying()) 
+	{
+		steps *= distance;
+
+		stepX = (endPosition.first - (float)begPosition.first)/steps;
+		stepY = (endPosition.second - (float)begPosition.second)/steps;
+	}
+	else
+	{
+		switch(mutPos)
 		{
-		case 0:	case 4:	case 5:
-			if(creDir[number] == true)
-				reverseCreature(number, curStackPos, twoTiles);
+		case 0:
+			stepX = (-1.0)*((float)hexWbase)/(2.0f*steps);
+			stepY = (-1.0)*((float)hexHbase)/((float)steps);
 			break;
-		case 1:	case 2: case 3:
-			if(creDir[number] == false)
-				reverseCreature(number, curStackPos, twoTiles);
+		case 1:
+			stepX = ((float)hexWbase)/(2.0f*steps);
+			stepY = (-1.0)*((float)hexHbase)/((float)steps);
+			break;
+		case 2:
+			stepX = ((float)hexWbase)/((float)steps);
+			stepY = 0.0;
+			break;
+		case 3:
+			stepX = ((float)hexWbase)/(2.0f*steps);
+			stepY = ((float)hexHbase)/((float)steps);
+			break;
+		case 4:
+			stepX = (-1.0)*((float)hexWbase)/(2.0f*steps);
+			stepY = ((float)hexHbase)/((float)steps);
+			break;
+		case 5:
+			stepX = (-1.0)*((float)hexWbase)/((float)steps);
+			stepY = 0.0;
 			break;
-		}
-		//moving instructions
-		float posX = creAnims[number]->pos.x, posY = creAnims[number]->pos.y; // for precise calculations ;]
-		for(int i=0; i<steps; ++i)
-		{
-			switch(mutPos)
-			{
-			case 0:
-				posX -= ((float)hexWbase)/(2.0f*steps);
-				creAnims[number]->pos.x = posX;
-				posY -= ((float)hexHbase)/((float)steps);
-				creAnims[number]->pos.y = posY;
-				break;
-			case 1:
-				posX += ((float)hexWbase)/(2.0f*steps);
-				creAnims[number]->pos.x = posX;
-				posY -= ((float)hexHbase)/((float)steps);
-				creAnims[number]->pos.y = posY;
-				break;
-			case 2:
-				posX += ((float)hexWbase)/((float)steps);
-				creAnims[number]->pos.x = posX;
-				break;
-			case 3:
-				posX += ((float)hexWbase)/(2.0f*steps);
-				creAnims[number]->pos.x = posX;
-				posY += ((float)hexHbase)/((float)steps);
-				creAnims[number]->pos.y = posY;
-				break;
-			case 4:
-				posX -= ((float)hexWbase)/(2.0f*steps);
-				creAnims[number]->pos.x = posX;
-				posY += ((float)hexHbase)/((float)steps);
-				creAnims[number]->pos.y = posY;
-				break;
-			case 5:
-				posX -= ((float)hexWbase)/((float)steps);
-				creAnims[number]->pos.x = posX;
-				break;
-			}
-			show();
-			CSDL_Ext::update();
-			SDL_framerateDelay(LOCPLINT->mainFPSmng);
-			if((animCount+1)%(4/animSpeed)==0)
-				creAnims[number]->incrementFrame();
 		}
 	}
+	//step shifts calculated
+
+	//switch(mutPos) //reverse unit if necessary
+	//{
+	//case 0:	case 4:	case 5:
+	//	if(creDir[number] == true)
+	//		reverseCreature(number, curStackPos, twoTiles);
+	//	break;
+	//case 1:	case 2: case 3:
+	//	if(creDir[number] == false)
+	//		reverseCreature(number, curStackPos, twoTiles);
+	//	break;
+	//}
+
+	//moving instructions
+	for(int i=0; i<steps; ++i)
+	{
+		posX += stepX;
+		creAnims[number]->pos.x = posX;
+		posY += stepY;
+		creAnims[number]->pos.y = posY;
+		
+		show();
+		CSDL_Ext::update();
+		SDL_framerateDelay(LOCPLINT->mainFPSmng);
+	}
+	//unit moved
 
 	if(endMoving) //animation of ending move
 	{
 		if(creAnims[number]->framesInGroup(21)!=0) // some units don't have this animation (ie. halberdier)
 		{
 			creAnims[number]->setType(21);
-			for(int i=0; i<creAnims[number]->framesInGroup(21)*getAnimSpeedMultiplier()-1; ++i)
+
+			//for(int i=0; i<creAnims[number]->framesInGroup(21)*getAnimSpeedMultiplier()-1; ++i)
+			while(!creAnims[number]->onLastFrameInGroup())
 			{
 				show();
 				CSDL_Ext::update();
 				SDL_framerateDelay(LOCPLINT->mainFPSmng);
-				if((animCount+1)%(4/animSpeed)==0)
-					creAnims[number]->incrementFrame();
 			}
 		}
 		creAnims[number]->setType(2); //resetting to default

+ 1 - 1
CBattleInterface.h

@@ -249,7 +249,7 @@ public:
 	void stackRemoved(CStack stack); //stack disappeared from batlefiled
 	//void stackKilled(int ID, int dmg, int killed, int IDby, bool byShooting); //stack has been killed (but corpses remain)
 	void stackActivated(int number); //active stack has been changed
-	void stackMoved(int number, int destHex, bool endMoving); //stack with id number moved to destHex
+	void stackMoved(int number, int destHex, bool endMoving, int distance); //stack with id number moved to destHex
 	void stacksAreAttacked(std::vector<SStackAttackedInfo> attackedInfos); //called when a certain amount of stacks has been attacked
 	void stackAttacking(int ID, int dest); //called when stack with id ID is attacking something on hex dest
 	void newRound(int number); //caled when round is ended; number is the number of round

+ 2 - 2
CGameInterface.h

@@ -78,7 +78,7 @@ public:
 	virtual void battleStackAttacked(BattleStackAttacked * bsa){}; //called when stack receives damage (after battleAttack())
 	virtual void battleEnd(BattleResult *br){};
 	virtual void battleNewRound(int round){}; //called at the beggining of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
-	virtual void battleStackMoved(int ID, int dest){};
+	virtual void battleStackMoved(int ID, int dest, int distance){};
 	virtual void battleSpellCasted(SpellCasted *sc){};
 	virtual void battleStart(CCreatureSet *army1, CCreatureSet *army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side){}; //called by engine when battle starts; side=0 - left, side=1 - right
 	virtual void battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles){}; //called when battlefield is prepared, prior the battle beginning
@@ -95,7 +95,7 @@ public:
 	virtual void yourTurn(){};
 	virtual void heroKilled(const CGHeroInstance*){};
 	virtual void heroCreated(const CGHeroInstance*){};
-	virtual void battleStackMoved(int ID, int dest, bool startMoving, bool endMoving){};
+	virtual void battleStackMoved(int ID, int dest, int distance){};
 	virtual void battleStackAttacking(int ID, int dest){};
 	virtual void battleStackIsAttacked(int ID, int dmg, int killed, int IDby, bool byShooting){};
 	virtual BattleAction activeStack(int stackID) {BattleAction ba; ba.actionType = 3; ba.stackNumber = stackID; return ba;};

+ 18 - 3
CGameState.cpp

@@ -333,6 +333,7 @@ signed char BattleInfo::mutualPosition(int hex1, int hex2)
 		return 3;
 	return -1;
 }
+
 std::vector<int> BattleInfo::neighbouringTiles(int hex)
 {
 #define CHECK_AND_PUSH(tile) {int hlp = (tile); if(hlp>=0 && hlp<BFIELD_SIZE && (hlp%BFIELD_WIDTH!=16) && hlp%BFIELD_WIDTH) ret.push_back(hlp);}
@@ -346,12 +347,25 @@ std::vector<int> BattleInfo::neighbouringTiles(int hex)
 #undef CHECK_AND_PUSH
 	return ret;
 }
-std::vector<int> BattleInfo::getPath(int start, int dest, bool*accessibility)
+std::pair< std::vector<int>, int > BattleInfo::getPath(int start, int dest, bool*accessibility, bool flyingCreature)
 {							
 	int predecessor[BFIELD_SIZE]; //for getting the Path
 	int dist[BFIELD_SIZE]; //calculated distances
 
-	makeBFS(start,accessibility,predecessor,dist);
+	if(flyingCreature)
+	{
+		bool acc[BFIELD_SIZE]; //full accessibility table
+		for(int b=0; b<BFIELD_SIZE; ++b) //initialization of acc
+		{
+			acc[b] = true;
+		}
+
+		makeBFS(start, acc, predecessor, dist);
+	}
+	else
+	{
+		makeBFS(start, accessibility, predecessor, dist);
+	}
 
 	//making the Path
 	std::vector<int> path;
@@ -361,7 +375,8 @@ std::vector<int> BattleInfo::getPath(int start, int dest, bool*accessibility)
 		path.push_back(curElem);
 		curElem = predecessor[curElem];
 	}
-	return path;
+
+	return std::make_pair(path, dist[dest]);
 }
 
 CStack::CStack(CCreature * C, int A, int O, int I, bool AO, int S)

+ 1 - 1
CGameState.h

@@ -118,7 +118,7 @@ struct DLL_EXPORT BattleInfo
 	void getAccessibilityMap(bool *accessibility, int stackToOmmit=-1); //send pointer to at least 187 allocated bytes
 	void getAccessibilityMapForTwoHex(bool *accessibility, bool atackerSide, int stackToOmmit=-1, bool addOccupiable = false); //send pointer to at least 187 allocated bytes
 	void makeBFS(int start, bool*accessibility, int *predecessor, int *dists); //*accessibility must be prepared bool[187] array; last two pointers must point to the at least 187-elements int arrays - there is written result
-	std::vector<int> getPath(int start, int dest, bool*accessibility);
+	std::pair< std::vector<int>, int > getPath(int start, int dest, bool*accessibility, bool flyingCreature); //returned value: pair<path, length>; length may be different than number of elements in path since flying vreatures jump between distant hexes
 	std::vector<int> getAccessibility(int stackID, bool addOccupiable); //returns vector of accessible tiles (taking into account the creature range)
 
 	bool isStackBlocked(int ID); //returns true if there is neighbouring enemy stack

+ 2 - 2
CPlayerInterface.cpp

@@ -2215,10 +2215,10 @@ void CPlayerInterface::battleResultQuited()
 	LOCPLINT->showingDialog->setn(false);
 }
 
-void CPlayerInterface::battleStackMoved(int ID, int dest)
+void CPlayerInterface::battleStackMoved(int ID, int dest, int distance)
 {
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
-	battleInt->stackMoved(ID, dest, dest==curAction->destinationTile);
+	battleInt->stackMoved(ID, dest, dest==curAction->destinationTile, distance);
 }
 void CPlayerInterface::battleSpellCasted(SpellCasted *sc)
 {

+ 1 - 1
CPlayerInterface.h

@@ -490,7 +490,7 @@ public:
 	void battleEnd(BattleResult *br);
 	void battleResultQuited();
 	void battleNewRound(int round); //called at the beggining of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
-	void battleStackMoved(int ID, int dest);
+	void battleStackMoved(int ID, int dest, int distance);
 	void battleSpellCasted(SpellCasted *sc);
 	void battleStackAttacked(BattleStackAttacked * bsa);
 	void battleStart(CCreatureSet *army1, CCreatureSet *army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side); //called by engine when battle starts; side=0 - left, side=1 - right

+ 2 - 2
client/Client.cpp

@@ -520,9 +520,9 @@ void CClient::process(int what)
 			*serv >> br;
 			tlog5 << "Stack "<<br.stack <<" moves to the tile "<<br.tile<<std::endl;
 			if(playerint.find(gs->curB->side1) != playerint.end())
-				playerint[gs->curB->side1]->battleStackMoved(br.stack,br.tile);
+				playerint[gs->curB->side1]->battleStackMoved(br.stack, br.tile, br.distance);
 			if(playerint.find(gs->curB->side2) != playerint.end())
-				playerint[gs->curB->side2]->battleStackMoved(br.stack,br.tile);
+				playerint[gs->curB->side2]->battleStackMoved(br.stack, br.tile, br.distance);
 			gs->apply(&br);
 			break;
 		}

+ 2 - 2
lib/NetPacks.h

@@ -520,11 +520,11 @@ struct BattleResult : public CPack<BattleResult>//3003
 
 struct BattleStackMoved : public CPack<BattleStackMoved>//3004
 {
-	ui32 stack, tile;
+	ui32 stack, tile, distance;
 	BattleStackMoved(){type = 3004;};
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
-		h & stack & tile;
+		h & stack & tile & distance;
 	}
 };
 

+ 24 - 8
server/CGameHandler.cpp

@@ -1574,15 +1574,31 @@ void CGameHandler::moveStack(int stack, int dest)
 	//if(dists[dest] > curStack->creature->speed && !(stackAtEnd && dists[dest] == curStack->creature->speed+1)) //we can attack a stack if we can go to adjacent hex
 	//	return false;
 
-	std::vector<int> path = gs->curB->getPath(curStack->position,dest,accessibility);
-	int tilesToMove = std::max((int)(path.size() - curStack->speed()), 0);
-	for(int v=path.size()-1; v>=tilesToMove; --v)
+	std::pair< std::vector<int>, int > path = gs->curB->getPath(curStack->position, dest, accessibility, curStack->creature->isFlying());
+	if(curStack->creature->isFlying())
 	{
-		//inform clients about move
-		BattleStackMoved sm;
-		sm.stack = curStack->ID;
-		sm.tile = path[v];
-		sendAndApply(&sm);
+		if(path.second <= curStack->speed() && path.first.size() > 0)
+		{
+			//inform clients about move
+			BattleStackMoved sm;
+			sm.stack = curStack->ID;
+			sm.tile = path.first[0];
+			sm.distance = path.second;
+			sendAndApply(&sm);
+		}
+	}
+	else //for non-flying creatures
+	{
+		int tilesToMove = std::max((int)(path.first.size() - curStack->speed()), 0);
+		for(int v=path.first.size()-1; v>=tilesToMove; --v)
+		{
+			//inform clients about move
+			BattleStackMoved sm;
+			sm.stack = curStack->ID;
+			sm.tile = path.first[v];
+			sm.distance = path.second;
+			sendAndApply(&sm);
+		}
 	}
 }
 CGameHandler::CGameHandler(void)